python/manuel: update to 1.13.0
[oi-userland.git] / components / runtime / openjdk-21 / patches / 1_java-solaris-sparc.patch
blobe090086f19e96222bf5ec22048ca65bfd6997caf
1 diff -Nru jdk21u-jdk-21.0.4-ga.orig/bin/unshuffle_list.txt jdk21u-jdk-21.0.4-ga/bin/unshuffle_list.txt
2 --- jdk21u-jdk-21.0.4-ga.orig/bin/unshuffle_list.txt 2024-07-09 10:07:16.000000000 +0200
3 +++ jdk21u-jdk-21.0.4-ga/bin/unshuffle_list.txt 2024-08-17 19:13:01.360547092 +0200
4 @@ -100,6 +100,7 @@
5 src/langtools/sample : langtools/src/sample
6 src/linux : jdk/src/linux
7 src/sample : jdk/src/sample
8 +src/solaris : jdk/src/solaris
9 src/hotspot/share : hotspot/src/share/vm
10 src/hotspot/cpu/aarch64 : hotspot/src/cpu/aarch64/vm
11 src/hotspot/cpu/arm : hotspot/src/cpu/arm/vm
12 @@ -112,6 +113,7 @@
13 src/hotspot/os/linux : hotspot/src/os/linux/vm
14 src/hotspot/os/posix/dtrace : hotspot/src/os/posix/dtrace
15 src/hotspot/os/posix : hotspot/src/os/posix/vm
16 +src/hotspot/os/solaris : hotspot/src/os/solaris/vm
17 src/hotspot/os/windows : hotspot/src/os/windows/vm
18 src/hotspot/os_cpu/aix_ppc : hotspot/src/os_cpu/aix_ppc/vm
19 src/hotspot/os_cpu/bsd_x86 : hotspot/src/os_cpu/bsd_x86/vm
20 @@ -122,6 +124,7 @@
21 src/hotspot/os_cpu/linux_s390 : hotspot/src/os_cpu/linux_s390/vm
22 src/hotspot/os_cpu/linux_x86 : hotspot/src/os_cpu/linux_x86/vm
23 src/hotspot/os_cpu/linux_zero : hotspot/src/os_cpu/linux_zero/vm
24 +src/hotspot/os_cpu/solaris_x86 : hotspot/src/os_cpu/solaris_x86/vm
25 src/hotspot/os_cpu/windows_x86 : hotspot/src/os_cpu/windows_x86/vm
26 src/hotspot : hotspot/src
27 src/utils/IdealGraphVisualizer : hotspot/src/share/tools/IdealGraphVisualizer
28 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/autoconf/basic_tools.m4 jdk21u-jdk-21.0.4-ga/make/autoconf/basic_tools.m4
29 --- jdk21u-jdk-21.0.4-ga.orig/make/autoconf/basic_tools.m4 2024-07-09 10:07:16.000000000 +0200
30 +++ jdk21u-jdk-21.0.4-ga/make/autoconf/basic_tools.m4 2024-08-17 19:13:01.362487697 +0200
31 @@ -289,6 +289,8 @@
32 TAR_TYPE="bsd"
33 elif test "x$($TAR --version | $GREP "busybox")" != "x"; then
34 TAR_TYPE="busybox"
35 + elif test "x$OPENJDK_BUILD_OS" = "xsolaris"; then
36 + TAR_TYPE="solaris"
37 elif test "x$OPENJDK_BUILD_OS" = "xaix"; then
38 TAR_TYPE="aix"
40 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/autoconf/build-aux/config.guess jdk21u-jdk-21.0.4-ga/make/autoconf/build-aux/config.guess
41 --- jdk21u-jdk-21.0.4-ga.orig/make/autoconf/build-aux/config.guess 2024-07-09 10:07:16.000000000 +0200
42 +++ jdk21u-jdk-21.0.4-ga/make/autoconf/build-aux/config.guess 2024-08-17 19:13:01.362946796 +0200
43 @@ -53,6 +53,14 @@
47 +# Test and fix solaris on x86_64
48 +echo $OUT | grep i386-pc-solaris > /dev/null 2> /dev/null
49 +if test $? = 0; then
50 + # isainfo -n returns either i386 or amd64
51 + REAL_CPU=`isainfo -n`
52 + OUT=$REAL_CPU`echo $OUT | sed -e 's/[^-]*//'`
53 +fi
55 # Test and fix cygwin on x86_64
56 echo $OUT | grep 86-pc-cygwin > /dev/null 2> /dev/null
57 if test $? != 0; then
58 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/autoconf/build-performance.m4 jdk21u-jdk-21.0.4-ga/make/autoconf/build-performance.m4
59 --- jdk21u-jdk-21.0.4-ga.orig/make/autoconf/build-performance.m4 2024-07-09 10:07:16.000000000 +0200
60 +++ jdk21u-jdk-21.0.4-ga/make/autoconf/build-performance.m4 2024-08-17 19:13:01.363465321 +0200
61 @@ -33,6 +33,9 @@
62 if test "$NUM_CORES" -eq "0"; then
63 NUM_CORES=`cat /proc/cpuinfo | grep -c ^CPU`
65 + elif test -x /usr/sbin/psrinfo; then
66 + # Looks like a Solaris system
67 + NUM_CORES=`/usr/sbin/psrinfo -v | grep -c on-line`
68 elif test -x /usr/sbin/sysctl; then
69 # Looks like a MacOSX system
70 NUM_CORES=`/usr/sbin/sysctl -n hw.ncpu`
71 @@ -65,7 +68,7 @@
72 MEMORY_SIZE=`expr $MEMORY_SIZE / 1024`
73 FOUND_MEM=yes
74 elif test -x /usr/sbin/prtconf; then
75 - # Looks like an AIX system
76 + # Looks like a Solaris or AIX system
77 MEMORY_SIZE=`/usr/sbin/prtconf 2> /dev/null | grep "^Memory [[Ss]]ize" | awk '{ print [$]3 }'`
78 FOUND_MEM=yes
79 elif test -x /usr/sbin/sysctl; then
80 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/autoconf/flags-cflags.m4 jdk21u-jdk-21.0.4-ga/make/autoconf/flags-cflags.m4
81 --- jdk21u-jdk-21.0.4-ga.orig/make/autoconf/flags-cflags.m4 2024-07-09 10:07:16.000000000 +0200
82 +++ jdk21u-jdk-21.0.4-ga/make/autoconf/flags-cflags.m4 2024-08-17 19:13:01.364198456 +0200
83 @@ -492,6 +492,9 @@
84 if test "x$OPENJDK_TARGET_OS" = xlinux; then
85 CFLAGS_OS_DEF_JVM="-DLINUX -D_FILE_OFFSET_BITS=64"
86 CFLAGS_OS_DEF_JDK="-D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE"
87 + elif test "x$OPENJDK_TARGET_OS" = xsolaris; then
88 + CFLAGS_OS_DEF_JVM="-DSOLARIS"
89 + CFLAGS_OS_DEF_JDK="-D__solaris__"
90 elif test "x$OPENJDK_TARGET_OS" = xmacosx; then
91 CFLAGS_OS_DEF_JVM="-D_ALLBSD_SOURCE -D_DARWIN_C_SOURCE -D_XOPEN_SOURCE"
92 CFLAGS_OS_DEF_JDK="-D_ALLBSD_SOURCE -D_DARWIN_UNLIMITED_SELECT"
93 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/autoconf/jdk-options.m4 jdk21u-jdk-21.0.4-ga/make/autoconf/jdk-options.m4
94 --- jdk21u-jdk-21.0.4-ga.orig/make/autoconf/jdk-options.m4 2024-07-09 10:07:16.000000000 +0200
95 +++ jdk21u-jdk-21.0.4-ga/make/autoconf/jdk-options.m4 2024-08-17 19:13:01.364840678 +0200
96 @@ -285,7 +285,7 @@
97 ZIP_EXTERNAL_DEBUG_SYMBOLS=false
98 elif test "x$with_native_debug_symbols" = xexternal; then
100 - if test "x$OPENJDK_TARGET_OS" = xlinux; then
101 + if test "x$OPENJDK_TARGET_OS" = xsolaris || test "x$OPENJDK_TARGET_OS" = xlinux; then
102 if test "x$OBJCOPY" = x; then
103 # enabling of enable-debug-symbols and can't find objcopy
104 # this is an error
105 @@ -298,7 +298,7 @@
106 ZIP_EXTERNAL_DEBUG_SYMBOLS=false
107 elif test "x$with_native_debug_symbols" = xzipped; then
109 - if test "x$OPENJDK_TARGET_OS" = xlinux; then
110 + if test "x$OPENJDK_TARGET_OS" = xsolaris || test "x$OPENJDK_TARGET_OS" = xlinux; then
111 if test "x$OBJCOPY" = x; then
112 # enabling of enable-debug-symbols and can't find objcopy
113 # this is an error
114 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/autoconf/lib-freetype.m4 jdk21u-jdk-21.0.4-ga/make/autoconf/lib-freetype.m4
115 --- jdk21u-jdk-21.0.4-ga.orig/make/autoconf/lib-freetype.m4 2024-07-09 10:07:16.000000000 +0200
116 +++ jdk21u-jdk-21.0.4-ga/make/autoconf/lib-freetype.m4 2024-08-17 19:13:01.365349653 +0200
117 @@ -53,6 +53,13 @@
118 if ! test -s "$POTENTIAL_FREETYPE_LIB_PATH/$FREETYPE_LIB_NAME"; then
119 AC_MSG_NOTICE([Could not find $POTENTIAL_FREETYPE_LIB_PATH/$FREETYPE_LIB_NAME. Ignoring location.])
120 FOUND_FREETYPE=no
121 + else
122 + if test "x$OPENJDK_TARGET_OS" = "xsolaris" \
123 + && test -s "$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR/$FREETYPE_LIB_NAME"; then
124 + # Found lib in isa dir, use that instead.
125 + POTENTIAL_FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR"
126 + AC_MSG_NOTICE([Rewriting to use $POTENTIAL_FREETYPE_LIB_PATH instead])
127 + fi
131 @@ -160,6 +167,15 @@
132 if test "x$PKG_CONFIG" != "x" ; then
133 PKG_CHECK_MODULES(FREETYPE, freetype2, [FOUND_FREETYPE=yes], [FOUND_FREETYPE=no])
134 if test "x$FOUND_FREETYPE" = "xyes" ; then
135 + # On solaris, pkg_check adds -lz to freetype libs, which isn't
136 + # necessary for us.
137 + FREETYPE_LIBS=`$ECHO $FREETYPE_LIBS | $SED 's/-lz//g'`
138 + # 64-bit libs for Solaris x86 are installed in the amd64
139 + # subdirectory, change lib to lib/amd64
140 + if test "x$OPENJDK_TARGET_OS" = "xsolaris" && \
141 + test "x$OPENJDK_TARGET_CPU" = "xx86_64" ; then
142 + FREETYPE_LIBS=`$ECHO $FREETYPE_LIBS | $SED 's?/lib?/lib/amd64?g'`
143 + fi
144 AC_MSG_CHECKING([for freetype])
145 AC_MSG_RESULT([yes (using pkg-config)])
147 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/autoconf/libraries.m4 jdk21u-jdk-21.0.4-ga/make/autoconf/libraries.m4
148 --- jdk21u-jdk-21.0.4-ga.orig/make/autoconf/libraries.m4 2024-07-09 10:07:16.000000000 +0200
149 +++ jdk21u-jdk-21.0.4-ga/make/autoconf/libraries.m4 2024-08-17 19:13:01.365869842 +0200
150 @@ -139,13 +139,15 @@
151 BASIC_JVM_LIBS="$LIBM"
153 # Dynamic loading library
154 - if test "x$OPENJDK_TARGET_OS" = xlinux || test "x$OPENJDK_TARGET_OS" = xaix; then
155 + if test "x$OPENJDK_TARGET_OS" = xlinux || test "x$OPENJDK_TARGET_OS" = xsolaris || test "x$OPENJDK_TARGET_OS" = xaix; then
156 BASIC_JVM_LIBS="$BASIC_JVM_LIBS $LIBDL"
159 # Threading library
160 if test "x$OPENJDK_TARGET_OS" = xlinux || test "x$OPENJDK_TARGET_OS" = xaix; then
161 BASIC_JVM_LIBS="$BASIC_JVM_LIBS -lpthread"
162 + elif test "x$OPENJDK_TARGET_OS" = xsolaris; then
163 + BASIC_JVM_LIBS="$BASIC_JVM_LIBS -lthread"
166 # librt for legacy clock_gettime
167 @@ -162,6 +164,12 @@
168 BASIC_JVM_LIBS="$BASIC_JVM_LIBS -lperfstat"
171 + if test "x$OPENJDK_TARGET_OS" = xsolaris; then
172 + BASIC_JVM_LIBS="$BASIC_JVM_LIBS -lsocket -lsched -ldoor -lnsl \
173 + -lrt -lkstat"
174 + BASIC_JVM_LIBS="$BASIC_JVM_LIBS $LIBCXX_JVM"
175 + fi
177 if test "x$OPENJDK_TARGET_OS" = xwindows; then
178 BASIC_JVM_LIBS="$BASIC_JVM_LIBS kernel32.lib user32.lib gdi32.lib winspool.lib \
179 comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib powrprof.lib uuid.lib \
180 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/autoconf/platform.m4 jdk21u-jdk-21.0.4-ga/make/autoconf/platform.m4
181 --- jdk21u-jdk-21.0.4-ga.orig/make/autoconf/platform.m4 2024-07-09 10:07:16.000000000 +0200
182 +++ jdk21u-jdk-21.0.4-ga/make/autoconf/platform.m4 2024-08-17 19:13:01.366505794 +0200
183 @@ -202,6 +202,10 @@
184 VAR_OS=linux
185 VAR_OS_TYPE=unix
187 + *solaris*)
188 + VAR_OS=solaris
189 + VAR_OS_TYPE=unix
190 + ;;
191 *darwin*)
192 VAR_OS=macosx
193 VAR_OS_TYPE=unix
194 @@ -472,6 +476,17 @@
196 AC_SUBST(OPENJDK_$1_CPU_LEGACY_LIB)
198 + # OPENJDK_$1_CPU_ISADIR is normally empty. On 64-bit Solaris systems, it is set to
199 + # /amd64 or /sparcv9. This string is appended to some library paths, like this:
200 + # /usr/lib${OPENJDK_$1_CPU_ISADIR}/libexample.so
201 + OPENJDK_$1_CPU_ISADIR=""
202 + if test "x$OPENJDK_$1_OS" = xsolaris; then
203 + if test "x$OPENJDK_$1_CPU" = xx86_64; then
204 + OPENJDK_$1_CPU_ISADIR="/amd64"
205 + fi
206 + fi
207 + AC_SUBST(OPENJDK_$1_CPU_ISADIR)
209 # Setup OPENJDK_$1_CPU_OSARCH, which is used to set the os.arch Java system property
210 OPENJDK_$1_CPU_OSARCH="$OPENJDK_$1_CPU"
211 if test "x$OPENJDK_$1_OS" = xlinux && test "x$OPENJDK_$1_CPU" = xx86; then
212 @@ -603,6 +618,9 @@
214 AC_DEFUN([PLATFORM_SET_RELEASE_FILE_OS_VALUES],
216 + if test "x$OPENJDK_TARGET_OS" = "xsolaris"; then
217 + RELEASE_FILE_OS_NAME=SunOS
218 + fi
219 if test "x$OPENJDK_TARGET_OS" = "xlinux"; then
220 RELEASE_FILE_OS_NAME=Linux
222 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/autoconf/spec.gmk.in jdk21u-jdk-21.0.4-ga/make/autoconf/spec.gmk.in
223 --- jdk21u-jdk-21.0.4-ga.orig/make/autoconf/spec.gmk.in 2024-07-09 10:07:16.000000000 +0200
224 +++ jdk21u-jdk-21.0.4-ga/make/autoconf/spec.gmk.in 2024-08-17 19:13:01.367079478 +0200
225 @@ -93,6 +93,7 @@
226 COMPILE_TYPE:=@COMPILE_TYPE@
228 # Legacy support
229 +OPENJDK_TARGET_CPU_ISADIR:=@OPENJDK_TARGET_CPU_ISADIR@
230 OPENJDK_TARGET_CPU_LEGACY:=@OPENJDK_TARGET_CPU_LEGACY@
231 OPENJDK_TARGET_CPU_LEGACY_LIB:=@OPENJDK_TARGET_CPU_LEGACY_LIB@
232 OPENJDK_TARGET_CPU_OSARCH:=@OPENJDK_TARGET_CPU_OSARCH@
233 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/autoconf/toolchain.m4 jdk21u-jdk-21.0.4-ga/make/autoconf/toolchain.m4
234 --- jdk21u-jdk-21.0.4-ga.orig/make/autoconf/toolchain.m4 2024-07-09 10:07:16.000000000 +0200
235 +++ jdk21u-jdk-21.0.4-ga/make/autoconf/toolchain.m4 2024-08-17 19:13:01.367721456 +0200
236 @@ -39,6 +39,7 @@
238 # These toolchains are valid on different platforms
239 VALID_TOOLCHAINS_linux="gcc clang"
240 +VALID_TOOLCHAINS_solaris="gcc"
241 VALID_TOOLCHAINS_macosx="clang"
242 VALID_TOOLCHAINS_aix="xlc clang"
243 VALID_TOOLCHAINS_windows="microsoft"
244 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/common/MakeBase.gmk jdk21u-jdk-21.0.4-ga/make/common/MakeBase.gmk
245 --- jdk21u-jdk-21.0.4-ga.orig/make/common/MakeBase.gmk 2024-07-09 10:07:16.000000000 +0200
246 +++ jdk21u-jdk-21.0.4-ga/make/common/MakeBase.gmk 2024-08-17 19:13:01.368317851 +0200
247 @@ -267,7 +267,33 @@
248 ################################################################################
249 # All install-file and related macros automatically call DecodeSpace when needed.
251 -ifeq ($(call isTargetOs, macosx), true)
252 +ifeq ($(call isTargetOs, solaris), true)
253 + # On Solaris, if the target is a symlink and exists, cp won't overwrite.
254 + # Cp has to operate in recursive mode to allow for -P flag, to preserve soft links. If the
255 + # name of the target file differs from the source file, rename after copy.
256 + # If the source and target parent directories are the same, recursive copy doesn't work
257 + # so we fall back on regular copy, which isn't preserving symlinks.
258 + define install-file
259 + $(call MakeTargetDir)
260 + $(RM) '$(call DecodeSpace, $@)'
261 + if [ '$(call DecodeSpace, $(dir $(call EncodeSpace, $@)))' != \
262 + '$(call DecodeSpace, $(dir $(call EncodeSpace, $<)))' ]; then \
263 + $(CP) -f -r -P '$(call DecodeSpace, $<)' \
264 + '$(call DecodeSpace, $(dir $(call EncodeSpace, $@)))'; \
265 + if [ '$(call DecodeSpace, $(notdir $(call EncodeSpace, $@)))' != \
266 + '$(call DecodeSpace, $(notdir $(call EncodeSpace, $(<))))' ]; then \
267 + $(MV) '$(call DecodeSpace, $(dir $(call EncodeSpace, $@))/$(notdir $(call EncodeSpace, $<)))' \
268 + '$(call DecodeSpace, $@)'; \
269 + fi; \
270 + else \
271 + if [ -L '$(call DecodeSpace, $<)' ]; then \
272 + $(ECHO) "Source file is a symlink and target is in the same directory: $< $@" ; \
273 + exit 1; \
274 + fi; \
275 + $(CP) -f '$(call DecodeSpace, $<)' '$(call DecodeSpace, $@)'; \
276 + fi
277 + endef
278 +else ifeq ($(call isTargetOs, macosx), true)
279 # On mac, extended attributes sometimes creep into the source files, which may later
280 # cause the creation of ._* files which confuses testing. Clear these with xattr if
281 # set. Some files get their write permissions removed after being copied to the
282 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/common/modules/LauncherCommon.gmk jdk21u-jdk-21.0.4-ga/make/common/modules/LauncherCommon.gmk
283 --- jdk21u-jdk-21.0.4-ga.orig/make/common/modules/LauncherCommon.gmk 2024-07-09 10:07:16.000000000 +0200
284 +++ jdk21u-jdk-21.0.4-ga/make/common/modules/LauncherCommon.gmk 2024-08-17 19:13:01.369625864 +0200
285 @@ -163,6 +163,7 @@
286 -DLAUNCHER_NAME='"$$(LAUNCHER_NAME)"' \
287 -DPROGNAME='"$1"' \
288 $$($1_CFLAGS), \
289 + CFLAGS_solaris := -fPIC, \
290 CFLAGS_windows := $$($1_CFLAGS_windows), \
291 DISABLED_WARNINGS_gcc := unused-function, \
292 LDFLAGS := $$(LDFLAGS_JDKEXE) \
293 @@ -172,11 +173,14 @@
294 -L$(call FindLibDirForModule, java.base), \
295 LDFLAGS_macosx := $$(call SET_EXECUTABLE_ORIGIN,/../lib) \
296 -L$(call FindLibDirForModule, java.base), \
297 + LDFLAGS_solaris := $$(call SET_EXECUTABLE_ORIGIN,/../lib) \
298 + -L$(call FindLibDirForModule, java.base), \
299 LDFLAGS_aix := -L$(SUPPORT_OUTPUTDIR)/native/java.base, \
300 LIBS := $(JDKEXE_LIBS) $$($1_LIBS), \
301 LIBS_linux := -ljli -lpthread $(LIBDL), \
302 LIBS_macosx := -ljli -framework Cocoa -framework Security \
303 -framework ApplicationServices, \
304 + LIBS_solaris := -ljli -lthread $(LIBDL), \
305 LIBS_aix := -ljli_static, \
306 LIBS_windows := $$($1_WINDOWS_JLI_LIB) \
307 $(SUPPORT_OUTPUTDIR)/native/java.base/libjava/java.lib, \
308 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/common/NativeCompilation.gmk jdk21u-jdk-21.0.4-ga/make/common/NativeCompilation.gmk
309 --- jdk21u-jdk-21.0.4-ga.orig/make/common/NativeCompilation.gmk 2024-07-09 10:07:16.000000000 +0200
310 +++ jdk21u-jdk-21.0.4-ga/make/common/NativeCompilation.gmk 2024-08-17 19:13:01.369080853 +0200
311 @@ -1058,7 +1058,7 @@
312 $1_DEBUGINFO_FILES := $$($1_SYMBOLS_DIR)/$$($1_BASENAME).pdb \
313 $$($1_SYMBOLS_DIR)/$$($1_BASENAME).map
315 - else ifeq ($(call isTargetOs, linux), true)
316 + else ifeq ($(call isTargetOs, linux solaris), true)
317 $1_DEBUGINFO_FILES := $$($1_SYMBOLS_DIR)/$$($1_NOSUFFIX).debuginfo
318 # Setup the command line creating debuginfo files, to be run after linking.
319 # It cannot be run separately since it updates the original target file
320 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/hotspot/gensrc/GensrcAdlc.gmk jdk21u-jdk-21.0.4-ga/make/hotspot/gensrc/GensrcAdlc.gmk
321 --- jdk21u-jdk-21.0.4-ga.orig/make/hotspot/gensrc/GensrcAdlc.gmk 2024-07-09 10:07:16.000000000 +0200
322 +++ jdk21u-jdk-21.0.4-ga/make/hotspot/gensrc/GensrcAdlc.gmk 2024-08-17 19:13:01.370177966 +0200
323 @@ -36,6 +36,9 @@
324 # NOTE: No optimization or debug flags set here
325 ifeq ($(call isBuildOs, linux), true)
326 ADLC_CFLAGS := -fno-exceptions -DLINUX
327 + else ifeq ($(call isBuildOs, solaris), true)
328 + ADLC_LDFLAGS := -m64
329 + ADLC_CFLAGS := -m64 -fpermissive
330 else ifeq ($(call isBuildOs, aix), true)
331 ifeq ($(TOOLCHAIN_TYPE), clang)
332 ADLC_LDFLAGS += -m64
333 @@ -95,6 +98,8 @@
334 # ADLC flags depending on target OS
335 ifeq ($(call isTargetOs, linux), true)
336 ADLCFLAGS += -DLINUX=1 -D_GNU_SOURCE=1
337 + else ifeq ($(call isTargetOs, solaris), true)
338 + ADLCFLAGS += -DSOLARIS=1
339 else ifeq ($(call isTargetOs, aix), true)
340 ADLCFLAGS += -DAIX=1
341 else ifeq ($(call isTargetOs, macosx), true)
342 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/hotspot/gensrc/GensrcDtrace.gmk jdk21u-jdk-21.0.4-ga/make/hotspot/gensrc/GensrcDtrace.gmk
343 --- jdk21u-jdk-21.0.4-ga.orig/make/hotspot/gensrc/GensrcDtrace.gmk 2024-07-09 10:07:16.000000000 +0200
344 +++ jdk21u-jdk-21.0.4-ga/make/hotspot/gensrc/GensrcDtrace.gmk 2024-08-17 19:13:01.370666622 +0200
345 @@ -28,7 +28,10 @@
347 ifeq ($(call check-jvm-feature, dtrace), true)
349 - ifeq ($(call isTargetOs, macosx), true)
350 + ifeq ($(call isTargetOs, solaris), true)
351 + DTRACE_FLAGS := -64
352 + DTRACE_CPP_FLAGS := -D_LP64 -x c
353 + else ifeq ($(call isTargetOs, macosx), true)
354 DTRACE_CPP_FLAGS := -D_LP64 -x c
355 else ifeq ($(call isTargetOs, linux), true)
356 DTRACE_CPP_FLAGS := -x c
357 @@ -51,4 +54,59 @@
358 TARGETS += $(patsubst $(DTRACE_SOURCE_DIR)/%.d, \
359 $(DTRACE_GENSRC_DIR)/%.h, $(wildcard $(DTRACE_SOURCE_DIR)/*.d))
361 + ifeq ($(call isTargetOs, solaris), true)
362 + ############################################################################
363 + # First we need to generate the dtraceGenOffsets tool. When run, this will
364 + # produce two header files and a C++ file. Note that generateJvmOffsets.cpp
365 + # is using the same JVM_CFLAGS as libjvm.so.
367 + # Include support files that will setup JVM compiler flags.
368 + include lib/JvmFeatures.gmk
369 + include lib/JvmFlags.gmk
371 + # We cannot compile until the JVMTI and JFR gensrc has finished.
372 + # JFR_FILES is defined in GensrcJfr.gmk.
373 + JVMTI_H := $(JVM_VARIANT_OUTPUTDIR)/gensrc/jvmtifiles/jvmti.h
375 + $(eval $(call SetupNativeCompilation, BUILD_DTRACE_GEN_OFFSETS, \
376 + NAME := dtraceGenOffsets, \
377 + TYPE := EXECUTABLE, \
378 + SRC := $(TOPDIR)/make/hotspot/src/native/dtrace, \
379 + TOOLCHAIN := $(TOOLCHAIN_BUILD), \
380 + LDFLAGS := -m64, \
381 + CFLAGS := -m64 $(JVM_CFLAGS), \
382 + EXTRA_DEPS := $(JVMTI_H) $(JFR_FILES), \
383 + OBJECT_DIR := $(JVM_VARIANT_OUTPUTDIR)/tools/dtrace-gen-offsets/objs, \
384 + OUTPUT_DIR := $(JVM_VARIANT_OUTPUTDIR)/tools/dtrace-gen-offsets, \
385 + ))
387 + DTRACE_GEN_OFFSETS_TOOL := $(BUILD_DTRACE_GEN_OFFSETS_TARGET)
389 + # Argument 1: Output filename
390 + # Argument 2: dtrace-gen-offset tool command line option
391 + define SetupDtraceOffsetsGeneration
392 + $$(eval $$(call SetupExecute, dtrace_offset_$$(strip $2), \
393 + INFO := Generating dtrace $2 file, \
394 + DEPS := $$(BUILD_DTRACE_GEN_OFFSETS), \
395 + OUTPUT_FILE := $1, \
396 + COMMAND := ( $$(DTRACE_GEN_OFFSETS_TOOL) -$$(strip $2) > $1 ), \
397 + ))
399 + TARGETS += $$(dtrace_offset_$$(strip $2)_TARGET)
400 + endef
402 + JVM_OFFSETS_H := $(DTRACE_GENSRC_DIR)/JvmOffsets.h
403 + JVM_OFFSETS_CPP := $(DTRACE_GENSRC_DIR)/JvmOffsets.cpp
404 + JVM_OFFSETS_INDEX_H := $(DTRACE_GENSRC_DIR)/JvmOffsetsIndex.h
406 + ############################################################################
407 + # Run the dtrace-gen-offset tool to generate these three files.
408 + # The generated JvmOffsets.cpp is compiled with the rest of libjvm.
409 + # The header files are used by libjvm_db and jhelper.d, respectively.
411 + $(eval $(call SetupDtraceOffsetsGeneration, $(JVM_OFFSETS_H), header))
412 + $(eval $(call SetupDtraceOffsetsGeneration, $(JVM_OFFSETS_INDEX_H), index))
413 + $(eval $(call SetupDtraceOffsetsGeneration, $(JVM_OFFSETS_CPP), table))
414 + endif
416 endif
417 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/hotspot/lib/CompileDtraceLibraries.gmk jdk21u-jdk-21.0.4-ga/make/hotspot/lib/CompileDtraceLibraries.gmk
418 --- jdk21u-jdk-21.0.4-ga.orig/make/hotspot/lib/CompileDtraceLibraries.gmk 1970-01-01 01:00:00.000000000 +0100
419 +++ jdk21u-jdk-21.0.4-ga/make/hotspot/lib/CompileDtraceLibraries.gmk 2024-08-17 19:13:01.440408944 +0200
420 @@ -0,0 +1,62 @@
422 +# Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
423 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
425 +# This code is free software; you can redistribute it and/or modify it
426 +# under the terms of the GNU General Public License version 2 only, as
427 +# published by the Free Software Foundation. Oracle designates this
428 +# particular file as subject to the "Classpath" exception as provided
429 +# by Oracle in the LICENSE file that accompanied this code.
431 +# This code is distributed in the hope that it will be useful, but WITHOUT
432 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
433 +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
434 +# version 2 for more details (a copy is included in the LICENSE file that
435 +# accompanied this code).
437 +# You should have received a copy of the GNU General Public License version
438 +# 2 along with this work; if not, write to the Free Software Foundation,
439 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
441 +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
442 +# or visit www.oracle.com if you need additional information or have any
443 +# questions.
446 +ifeq ($(call check-jvm-feature, dtrace), true)
447 + ifeq ($(call isTargetOs, solaris), true)
448 + JNI_INCLUDE_FLAGS := \
449 + -I$(SUPPORT_OUTPUTDIR)/modules_include/java.base \
450 + -I$(SUPPORT_OUTPUTDIR)/modules_include/java.base/$(OPENJDK_TARGET_OS_INCLUDE_SUBDIR) \
453 + ############################################################################
454 + # Build the stand-alone dtrace libraries.
456 + LIBJVM_DTRACE_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/libjvm_dtrace
457 + $(eval $(call SetupNativeCompilation, BUILD_LIBJVM_DTRACE, \
458 + NAME := jvm_dtrace, \
459 + OUTPUT_DIR := $(JVM_LIB_OUTPUTDIR), \
460 + SRC := $(TOPDIR)/src/java.base/solaris/native/libjvm_dtrace, \
461 + CFLAGS := $(JNI_INCLUDE_FLAGS) -m64 -G -mt -KPIC -xldscope=hidden, \
462 + LDFLAGS := -m64 -mt -xnolib $(SHARED_LIBRARY_FLAGS), \
463 + LIBS := $(LIBDL) -lthread -ldoor, \
464 + OBJECT_DIR := $(LIBJVM_DTRACE_OUTPUTDIR)/objs, \
465 + ))
467 + # Note that libjvm_db.c has tests for COMPILER2, but this was never set by
468 + # the old build.
469 + LIBJVM_DB_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/libjvm_db
470 + $(eval $(call SetupNativeCompilation, BUILD_LIBJVM_DB, \
471 + NAME := jvm_db, \
472 + OUTPUT_DIR := $(JVM_LIB_OUTPUTDIR), \
473 + SRC := $(TOPDIR)/src/java.base/solaris/native/libjvm_db, \
474 + CFLAGS := -I$(DTRACE_GENSRC_DIR) $(JNI_INCLUDE_FLAGS) -m64 -G -mt -KPIC -xldscope=hidden, \
475 + LDFLAGS := -m64 -mt -xnolib $(SHARED_LIBRARY_FLAGS), \
476 + OBJECT_DIR := $(LIBJVM_DB_OUTPUTDIR)/objs, \
477 + ))
479 + TARGETS += $(BUILD_LIBJVM_DTRACE) $(BUILD_LIBJVM_DB)
481 + endif
482 +endif
483 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/hotspot/lib/CompileJvm.gmk jdk21u-jdk-21.0.4-ga/make/hotspot/lib/CompileJvm.gmk
484 --- jdk21u-jdk-21.0.4-ga.orig/make/hotspot/lib/CompileJvm.gmk 2024-07-09 10:07:16.000000000 +0200
485 +++ jdk21u-jdk-21.0.4-ga/make/hotspot/lib/CompileJvm.gmk 2024-08-17 19:13:01.371194440 +0200
486 @@ -29,6 +29,9 @@
487 include lib/JvmOverrideFiles.gmk
488 include lib/JvmFlags.gmk
490 +# Include support files that will setup DTRACE_EXTRA_OBJECT_FILES.
491 +include lib/JvmDtraceObjects.gmk
493 ################################################################################
494 # Setup compilation of the main Hotspot native library (libjvm).
496 @@ -150,6 +153,7 @@
497 EXCLUDES := $(JVM_EXCLUDES), \
498 EXCLUDE_FILES := $(JVM_EXCLUDE_FILES), \
499 EXCLUDE_PATTERNS := $(JVM_EXCLUDE_PATTERNS), \
500 + EXTRA_OBJECT_FILES := $(DTRACE_EXTRA_OBJECT_FILES), \
501 CFLAGS := $(JVM_CFLAGS), \
502 abstract_vm_version.cpp_CXXFLAGS := $(CFLAGS_VM_VERSION), \
503 arguments.cpp_CXXFLAGS := $(CFLAGS_VM_VERSION), \
504 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/hotspot/lib/CompileLibraries.gmk jdk21u-jdk-21.0.4-ga/make/hotspot/lib/CompileLibraries.gmk
505 --- jdk21u-jdk-21.0.4-ga.orig/make/hotspot/lib/CompileLibraries.gmk 2024-07-09 10:07:16.000000000 +0200
506 +++ jdk21u-jdk-21.0.4-ga/make/hotspot/lib/CompileLibraries.gmk 2024-08-17 19:13:01.371587126 +0200
507 @@ -32,6 +32,7 @@
508 include HotspotCommon.gmk
510 include lib/CompileJvm.gmk
511 +include lib/CompileDtraceLibraries.gmk
513 ifneq ($(GTEST_FRAMEWORK_SRC), )
514 ifneq ($(CREATING_BUILDJDK), true)
515 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/hotspot/lib/JvmDtraceObjects.gmk jdk21u-jdk-21.0.4-ga/make/hotspot/lib/JvmDtraceObjects.gmk
516 --- jdk21u-jdk-21.0.4-ga.orig/make/hotspot/lib/JvmDtraceObjects.gmk 1970-01-01 01:00:00.000000000 +0100
517 +++ jdk21u-jdk-21.0.4-ga/make/hotspot/lib/JvmDtraceObjects.gmk 2024-08-17 19:13:01.440758158 +0200
518 @@ -0,0 +1,122 @@
520 +# Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
521 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
523 +# This code is free software; you can redistribute it and/or modify it
524 +# under the terms of the GNU General Public License version 2 only, as
525 +# published by the Free Software Foundation. Oracle designates this
526 +# particular file as subject to the "Classpath" exception as provided
527 +# by Oracle in the LICENSE file that accompanied this code.
529 +# This code is distributed in the hope that it will be useful, but WITHOUT
530 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
531 +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
532 +# version 2 for more details (a copy is included in the LICENSE file that
533 +# accompanied this code).
535 +# You should have received a copy of the GNU General Public License version
536 +# 2 along with this work; if not, write to the Free Software Foundation,
537 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
539 +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
540 +# or visit www.oracle.com if you need additional information or have any
541 +# questions.
544 +ifeq ($(call check-jvm-feature, dtrace), true)
545 + ifeq ($(call isTargetOs, solaris), true)
547 + ############################################################################
548 + # Integrate with libjvm. Here we generate two object files which are
549 + # linked with libjvm.so. This step is complicated from a dependency
550 + # perspective. We add these two files to the linking of libjvm using
551 + # EXTRA_OBJECT_FILES, but they need to be created outside the call to
552 + # SetupNativeCompilation. Also, one of the files is dependent on compiled
553 + # object files from the libjvm compilation, so this generation must happen
554 + # as a part of the libjvm compilation.
556 + DTRACE_OBJ := $(JVM_OUTPUTDIR)/objs/dtrace.o
557 + DTRACE_JHELPER_OBJ := $(JVM_OUTPUTDIR)/objs/dtrace_jhelper.o
559 + DTRACE_EXTRA_OBJECT_FILES := $(DTRACE_OBJ) $(DTRACE_JHELPER_OBJ)
561 + ############################################################################
562 + # Generate DTRACE_OBJ which is linked with libjvm.so. It depends on a set of
563 + # object files from the compilation.
565 + # Concatenate all *.d files into a single file
566 + DTRACE_SOURCE_FILES := $(addprefix $(TOPDIR)/src/hotspot/os/posix/dtrace/, \
567 + hotspot_jni.d \
568 + hotspot.d \
569 + hs_private.d \
572 + # *.d in the objs dir is used for generated make dependency files, so use
573 + # *.dt for dtrace files to avoid clashes.
574 + $(JVM_OUTPUTDIR)/objs/dtrace.dt: $(DTRACE_SOURCE_FILES)
575 + $(call LogInfo, Generating $(@F))
576 + $(call MakeDir, $(@D))
577 + $(CAT) $^ > $@
579 + DTRACE_INSTRUMENTED_OBJS := $(addprefix $(JVM_OUTPUTDIR)/objs/, \
580 + ciEnv.o \
581 + classLoadingService.o \
582 + compileBroker.o \
583 + gcVMOperations.o \
584 + hashtable.o \
585 + instanceKlass.o \
586 + java.o \
587 + jni.o \
588 + jvm.o \
589 + memoryManager.o \
590 + nmethod.o \
591 + objectMonitor.o \
592 + runtimeService.o \
593 + sharedRuntime.o \
594 + synchronizer.o \
595 + thread.o \
596 + unsafe.o \
597 + vmThread.o \
600 + ifeq ($(call check-jvm-feature, parallelgc), true)
601 + DTRACE_INSTRUMENTED_OBJS += $(addprefix $(JVM_OUTPUTDIR)/objs/, \
602 + psVMOperations.o \
604 + endif
606 + DTRACE_FLAGS := -64 -G
607 + DTRACE_CPP_FLAGS := -D_LP64
609 + # Make sure we run our selected compiler for preprocessing instead of letting
610 + # the dtrace tool pick it on it's own.
611 + $(DTRACE_OBJ): $(JVM_OUTPUTDIR)/objs/dtrace.dt $(DTRACE_INSTRUMENTED_OBJS)
612 + $(call LogInfo, Generating $(@F) from $(<F) and object files)
613 + $(call MakeDir, $(DTRACE_SUPPORT_DIR))
614 + $(call ExecuteWithLog, $(DTRACE_SUPPORT_DIR)/$(@F).dt, \
615 + ($(CPP) $(DTRACE_CPP_FLAGS) $< > $(DTRACE_SUPPORT_DIR)/$(@F).dt))
616 + $(call ExecuteWithLog, $@, $(DTRACE) $(DTRACE_FLAGS) -xlazyload -o $@ \
617 + -s $(DTRACE_SUPPORT_DIR)/$(@F).dt $(sort $(DTRACE_INSTRUMENTED_OBJS)))
619 + ############################################################################
620 + # Generate DTRACE_JHELPER_OBJ which is linked with libjvm.so.
622 + JHELPER_DTRACE_SRC := $(TOPDIR)/src/hotspot/os/solaris/dtrace/jhelper.d
624 + # jhelper.d includes JvmOffsetsIndex.h which was created by the gensrc step.
625 + DTRACE_GENSRC_DIR := $(JVM_VARIANT_OUTPUTDIR)/gensrc/dtracefiles
626 + JVM_OFFSETS_INDEX_H := $(DTRACE_GENSRC_DIR)/JvmOffsetsIndex.h
628 + # Make sure we run our selected compiler for preprocessing instead of letting
629 + # the dtrace tool pick it on it's own.
630 + $(DTRACE_JHELPER_OBJ): $(JHELPER_DTRACE_SRC) $(JVM_OFFSETS_INDEX_H)
631 + $(call LogInfo, Running dtrace for $(<F))
632 + $(call MakeDir, $(DTRACE_SUPPORT_DIR))
633 + $(call ExecuteWithLog, $(DTRACE_SUPPORT_DIR)/$(@F).dt, \
634 + ($(CPP) $(DTRACE_CPP_FLAGS) -I$(DTRACE_GENSRC_DIR) $^ \
635 + > $(DTRACE_SUPPORT_DIR)/$(@F).dt))
636 + $(call ExecuteWithLog, $@, $(DTRACE) $(DTRACE_FLAGS) -o $@ \
637 + -s $(DTRACE_SUPPORT_DIR)/$(@F).dt)
639 + endif
640 +endif
641 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/hotspot/lib/JvmMapfile.gmk jdk21u-jdk-21.0.4-ga/make/hotspot/lib/JvmMapfile.gmk
642 --- jdk21u-jdk-21.0.4-ga.orig/make/hotspot/lib/JvmMapfile.gmk 2024-07-09 10:07:16.000000000 +0200
643 +++ jdk21u-jdk-21.0.4-ga/make/hotspot/lib/JvmMapfile.gmk 2024-08-17 19:13:01.372076418 +0200
644 @@ -48,6 +48,18 @@
645 endif
646 endif
648 +ifeq ($(call isTargetOs, solaris), true)
649 + ifeq ($(call check-jvm-feature, dtrace), true)
650 + # Additional mapfiles that are only used when dtrace is enabled
651 + ifeq ($(call check-jvm-feature, compiler2), true)
652 + # This also covers the case of compiler1+compiler2.
653 + SYMBOLS_SRC += $(TOPDIR)/make/hotspot/symbols/symbols-solaris-dtrace-compiler2
654 + else ifeq ($(call check-jvm-feature, compiler1), true)
655 + SYMBOLS_SRC += $(TOPDIR)/make/hotspot/symbols/symbols-solaris-dtrace-compiler1
656 + endif
657 + endif
658 +endif
660 ################################################################################
661 # Create a dynamic list of symbols from the built object files. This is highly
662 # platform dependent.
663 @@ -64,6 +76,20 @@
664 if ($$3 ~ /$(FILTER_SYMBOLS_PATTERN)/) print $$3; \
667 +else ifeq ($(call isTargetOs, solaris), true)
668 + DUMP_SYMBOLS_CMD := $(NM) -p *.o
669 + ifneq ($(FILTER_SYMBOLS_PATTERN), )
670 + FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)|
671 + endif
672 + FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)^__1c.*__vtbl_$$|^gHotSpotVM
673 + FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)|^UseSharedSpaces$$
674 + FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)|^__1cJArgumentsRSharedArchivePath_$$
675 + FILTER_SYMBOLS_AWK_SCRIPT := \
676 + '{ \
677 + if ($$2 == "U") next; \
678 + if ($$3 ~ /$(FILTER_SYMBOLS_PATTERN)/) print $$3; \
679 + }'
681 else ifeq ($(call isTargetOs, macosx), true)
682 # nm on macosx prints out "warning: nm: no name list" to stderr for
683 # files without symbols. Hide this, even at the expense of hiding real errors.
684 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/hotspot/src/native/dtrace/generateJvmOffsets.cpp jdk21u-jdk-21.0.4-ga/make/hotspot/src/native/dtrace/generateJvmOffsets.cpp
685 --- jdk21u-jdk-21.0.4-ga.orig/make/hotspot/src/native/dtrace/generateJvmOffsets.cpp 1970-01-01 01:00:00.000000000 +0100
686 +++ jdk21u-jdk-21.0.4-ga/make/hotspot/src/native/dtrace/generateJvmOffsets.cpp 2024-08-17 19:13:01.441354035 +0200
687 @@ -0,0 +1,316 @@
689 + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
690 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
692 + * This code is free software; you can redistribute it and/or modify it
693 + * under the terms of the GNU General Public License version 2 only, as
694 + * published by the Free Software Foundation.
696 + * This code is distributed in the hope that it will be useful, but WITHOUT
697 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
698 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
699 + * version 2 for more details (a copy is included in the LICENSE file that
700 + * accompanied this code).
702 + * You should have received a copy of the GNU General Public License version
703 + * 2 along with this work; if not, write to the Free Software Foundation,
704 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
706 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
707 + * or visit www.oracle.com if you need additional information or have any
708 + * questions.
710 + */
713 + * This is to provide sanity check in jhelper.d which compares SCCS
714 + * versions of generateJvmOffsets.cpp used to create and extract
715 + * contents of __JvmOffsets[] table.
716 + * The __JvmOffsets[] table is located in generated JvmOffsets.cpp.
718 + * GENOFFS_SCCS_VER 34
719 + */
721 +#include <stdio.h>
722 +#include <strings.h>
724 +/* A workaround for private and protected fields */
725 +#define private public
726 +#define protected public
728 +#include <proc_service.h>
729 +#include "gc/shared/collectedHeap.hpp"
730 +#include "memory/heap.hpp"
731 +#include "oops/compressedOops.hpp"
732 +#include "runtime/vmStructs.hpp"
734 +typedef enum GEN_variant {
735 + GEN_OFFSET = 0,
736 + GEN_INDEX = 1,
737 + GEN_TABLE = 2
738 +} GEN_variant;
740 +#ifdef COMPILER1
741 +#ifdef ASSERT
744 + * To avoid the most part of potential link errors
745 + * we link this program with -z nodefs .
747 + * But for 'debug1' and 'fastdebug1' we still have to provide
748 + * a particular workaround for the following symbols below.
749 + * It will be good to find out a generic way in the future.
750 + */
752 +#pragma weak tty
754 +#if defined(i386) || defined(__i386) || defined(__amd64)
755 +#pragma weak noreg
756 +#endif /* i386 */
758 +LIR_Opr LIR_OprFact::illegalOpr = (LIR_Opr) 0;
760 +address StubRoutines::_call_stub_return_address = NULL;
762 +StubQueue* AbstractInterpreter::_code = NULL;
764 +#endif /* ASSERT */
765 +#endif /* COMPILER1 */
767 +#define GEN_OFFS_NAME(Type,Name,OutputType) \
768 + switch(gen_variant) { \
769 + case GEN_OFFSET: \
770 + printf("#define OFFSET_%-33s %ld\n", \
771 + #OutputType #Name, offset_of(Type, Name)); \
772 + break; \
773 + case GEN_INDEX: \
774 + printf("#define IDX_OFFSET_%-33s %d\n", \
775 + #OutputType #Name, index++); \
776 + break; \
777 + case GEN_TABLE: \
778 + printf("\tOFFSET_%s,\n", #OutputType #Name); \
779 + break; \
782 +#define GEN_OFFS(Type,Name) \
783 + GEN_OFFS_NAME(Type,Name,Type)
785 +#define GEN_SIZE(Type) \
786 + switch(gen_variant) { \
787 + case GEN_OFFSET: \
788 + printf("#define SIZE_%-35s %ld\n", \
789 + #Type, sizeof(Type)); \
790 + break; \
791 + case GEN_INDEX: \
792 + printf("#define IDX_SIZE_%-35s %d\n", \
793 + #Type, index++); \
794 + break; \
795 + case GEN_TABLE: \
796 + printf("\tSIZE_%s,\n", #Type); \
797 + break; \
800 +#define GEN_VALUE(String,Value) \
801 + switch(gen_variant) { \
802 + case GEN_OFFSET: \
803 + printf("#define %-40s %d\n", #String, Value); \
804 + break; \
805 + case GEN_INDEX: \
806 + printf("#define IDX_%-40s %d\n", #String, index++); \
807 + break; \
808 + case GEN_TABLE: \
809 + printf("\t" #String ",\n"); \
810 + break; \
813 +void gen_prologue(GEN_variant gen_variant) {
814 + const char *suffix = "Undefined-Suffix";
816 + switch(gen_variant) {
817 + case GEN_OFFSET: suffix = ".h"; break;
818 + case GEN_INDEX: suffix = "Index.h"; break;
819 + case GEN_TABLE: suffix = ".cpp"; break;
822 + printf("/*\n");
823 + printf(" * JvmOffsets%s !!!DO NOT EDIT!!! \n", suffix);
824 + printf(" * The generateJvmOffsets program generates this file!\n");
825 + printf(" */\n\n");
826 + switch(gen_variant) {
828 + case GEN_OFFSET:
829 + case GEN_INDEX:
830 + break;
832 + case GEN_TABLE:
833 + printf("#include \"JvmOffsets.h\"\n");
834 + printf("\n");
835 + printf("int __JvmOffsets[] = {\n");
836 + break;
840 +void gen_epilogue(GEN_variant gen_variant) {
841 + if (gen_variant != GEN_TABLE) {
842 + return;
844 + printf("};\n\n");
845 + return;
848 +int generateJvmOffsets(GEN_variant gen_variant) {
849 + int index = 0; /* It is used to generate JvmOffsetsIndex.h */
850 + int pointer_size = sizeof(void *);
851 + int data_model = (pointer_size == 4) ? PR_MODEL_ILP32 : PR_MODEL_LP64;
853 + gen_prologue(gen_variant);
855 + GEN_VALUE(DATA_MODEL, data_model);
856 + GEN_VALUE(POINTER_SIZE, pointer_size);
857 +#if COMPILER1_AND_COMPILER2
858 + GEN_VALUE(COMPILER, 3);
859 +#elif COMPILER1
860 + GEN_VALUE(COMPILER, 1);
861 +#elif COMPILER2
862 + GEN_VALUE(COMPILER, 2);
863 +#else
864 + GEN_VALUE(COMPILER, 0);
865 +#endif // COMPILER1 && COMPILER2
866 + printf("\n");
868 + GEN_OFFS(CollectedHeap, _reserved);
869 + GEN_OFFS(MemRegion, _start);
870 + GEN_OFFS(MemRegion, _word_size);
871 + GEN_SIZE(HeapWord);
872 + printf("\n");
874 + GEN_OFFS(VMStructEntry, typeName);
875 + GEN_OFFS(VMStructEntry, fieldName);
876 + GEN_OFFS(VMStructEntry, address);
877 + GEN_SIZE(VMStructEntry);
878 + printf("\n");
880 + GEN_VALUE(MAX_METHOD_CODE_SIZE, max_method_code_size);
881 +#if defined(i386) || defined(__i386) || defined(__amd64)
882 + GEN_VALUE(OFFSET_interpreter_frame_sender_sp, -1 * pointer_size);
883 + GEN_VALUE(OFFSET_interpreter_frame_method, -3 * pointer_size);
884 + GEN_VALUE(OFFSET_interpreter_frame_bcp_offset, -7 * pointer_size);
885 +#endif
887 + GEN_OFFS(Klass, _name);
888 + GEN_OFFS(ConstantPool, _pool_holder);
889 + printf("\n");
891 + GEN_VALUE(OFFSET_HeapBlockHeader_used, (int) offset_of(HeapBlock::Header, _used));
892 + GEN_OFFS(oopDesc, _metadata);
893 + printf("\n");
895 + GEN_VALUE(AccessFlags_NATIVE, JVM_ACC_NATIVE);
896 + GEN_VALUE(ConstMethod_has_linenumber_table, ConstMethod::_has_linenumber_table);
897 + GEN_OFFS(AccessFlags, _flags);
898 + GEN_OFFS(Symbol, _length);
899 + GEN_OFFS(Symbol, _body);
900 + printf("\n");
902 + GEN_OFFS(Method, _constMethod);
903 + GEN_OFFS(Method, _access_flags);
904 + printf("\n");
906 + GEN_OFFS(ConstMethod, _constants);
907 + GEN_OFFS(ConstMethod, _flags);
908 + GEN_OFFS(ConstMethod, _code_size);
909 + GEN_OFFS(ConstMethod, _name_index);
910 + GEN_OFFS(ConstMethod, _signature_index);
911 + printf("\n");
913 + GEN_OFFS(CodeHeap, _memory);
914 + GEN_OFFS(CodeHeap, _segmap);
915 + GEN_OFFS(CodeHeap, _log2_segment_size);
916 + printf("\n");
918 + GEN_OFFS(VirtualSpace, _low_boundary);
919 + GEN_OFFS(VirtualSpace, _high_boundary);
920 + GEN_OFFS(VirtualSpace, _low);
921 + GEN_OFFS(VirtualSpace, _high);
922 + printf("\n");
924 + /* We need to use different names here because of the template parameter */
925 + GEN_OFFS_NAME(GrowableArray<CodeHeap*>, _data, GrowableArray_CodeHeap);
926 + GEN_OFFS_NAME(GrowableArray<CodeHeap*>, _len, GrowableArray_CodeHeap);
927 + printf("\n");
929 + GEN_OFFS(CodeBlob, _name);
930 + GEN_OFFS(CodeBlob, _header_size);
931 + GEN_OFFS(CodeBlob, _content_begin);
932 + GEN_OFFS(CodeBlob, _code_begin);
933 + GEN_OFFS(CodeBlob, _code_end);
934 + GEN_OFFS(CodeBlob, _data_offset);
935 + GEN_OFFS(CodeBlob, _frame_size);
936 + printf("\n");
938 + GEN_OFFS(nmethod, _method);
939 + GEN_OFFS(nmethod, _dependencies_offset);
940 + GEN_OFFS(nmethod, _metadata_offset);
941 + GEN_OFFS(nmethod, _scopes_data_begin);
942 + GEN_OFFS(nmethod, _scopes_pcs_offset);
943 + GEN_OFFS(nmethod, _handler_table_offset);
944 + GEN_OFFS(nmethod, _deopt_handler_begin);
945 + GEN_OFFS(nmethod, _orig_pc_offset);
947 + GEN_OFFS(PcDesc, _pc_offset);
948 + GEN_OFFS(PcDesc, _scope_decode_offset);
950 + printf("\n");
952 + GEN_OFFS(NarrowPtrStruct, _base);
953 + GEN_OFFS(NarrowPtrStruct, _shift);
954 + printf("\n");
956 + GEN_VALUE(SIZE_HeapBlockHeader, (int) sizeof(HeapBlock::Header));
957 + GEN_SIZE(oopDesc);
958 + GEN_SIZE(ConstantPool);
959 + printf("\n");
961 + GEN_SIZE(PcDesc);
962 + GEN_SIZE(Method);
963 + GEN_SIZE(ConstMethod);
964 + GEN_SIZE(nmethod);
965 + GEN_SIZE(CodeBlob);
966 + GEN_SIZE(BufferBlob);
967 + GEN_SIZE(SingletonBlob);
968 + GEN_SIZE(RuntimeStub);
969 + GEN_SIZE(SafepointBlob);
971 + gen_epilogue(gen_variant);
972 + printf("\n");
974 + fflush(stdout);
975 + return 0;
978 +const char *HELP =
979 + "HELP: generateJvmOffsets {-header | -index | -table} \n";
981 +int main(int argc, const char *argv[]) {
982 + GEN_variant gen_var;
984 + if (argc != 2) {
985 + printf("%s", HELP);
986 + return 1;
989 + if (0 == strcmp(argv[1], "-header")) {
990 + gen_var = GEN_OFFSET;
992 + else if (0 == strcmp(argv[1], "-index")) {
993 + gen_var = GEN_INDEX;
995 + else if (0 == strcmp(argv[1], "-table")) {
996 + gen_var = GEN_TABLE;
998 + else {
999 + printf("%s", HELP);
1000 + return 1;
1002 + return generateJvmOffsets(gen_var);
1004 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/hotspot/symbols/symbols-solaris jdk21u-jdk-21.0.4-ga/make/hotspot/symbols/symbols-solaris
1005 --- jdk21u-jdk-21.0.4-ga.orig/make/hotspot/symbols/symbols-solaris 1970-01-01 01:00:00.000000000 +0100
1006 +++ jdk21u-jdk-21.0.4-ga/make/hotspot/symbols/symbols-solaris 2024-08-17 19:13:01.441705304 +0200
1007 @@ -0,0 +1,25 @@
1009 +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
1010 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1012 +# This code is free software; you can redistribute it and/or modify it
1013 +# under the terms of the GNU General Public License version 2 only, as
1014 +# published by the Free Software Foundation.
1016 +# This code is distributed in the hope that it will be useful, but WITHOUT
1017 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1018 +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1019 +# version 2 for more details (a copy is included in the LICENSE file that
1020 +# accompanied this code).
1022 +# You should have received a copy of the GNU General Public License version
1023 +# 2 along with this work; if not, write to the Free Software Foundation,
1024 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1026 +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1027 +# or visit www.oracle.com if you need additional information or have any
1028 +# questions.
1031 +JVM_handle_solaris_signal
1032 +sysThreadAvailableStackWithSlack
1033 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/hotspot/symbols/symbols-solaris-dtrace-compiler1 jdk21u-jdk-21.0.4-ga/make/hotspot/symbols/symbols-solaris-dtrace-compiler1
1034 --- jdk21u-jdk-21.0.4-ga.orig/make/hotspot/symbols/symbols-solaris-dtrace-compiler1 1970-01-01 01:00:00.000000000 +0100
1035 +++ jdk21u-jdk-21.0.4-ga/make/hotspot/symbols/symbols-solaris-dtrace-compiler1 2024-08-17 19:13:01.441996288 +0200
1036 @@ -0,0 +1,34 @@
1038 +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
1039 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1041 +# This code is free software; you can redistribute it and/or modify it
1042 +# under the terms of the GNU General Public License version 2 only, as
1043 +# published by the Free Software Foundation.
1045 +# This code is distributed in the hope that it will be useful, but WITHOUT
1046 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1047 +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1048 +# version 2 for more details (a copy is included in the LICENSE file that
1049 +# accompanied this code).
1051 +# You should have received a copy of the GNU General Public License version
1052 +# 2 along with this work; if not, write to the Free Software Foundation,
1053 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1055 +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1056 +# or visit www.oracle.com if you need additional information or have any
1057 +# questions.
1060 +__1cGMethodG__vtbl_
1061 +__1cHnmethodG__vtbl_
1062 +__1cICodeBlobG__vtbl_
1063 +__1cIUniverseO_collectedHeap_
1064 +__1cJCodeCacheG_heaps_
1065 +__1cKBufferBlobG__vtbl_
1066 +__1cLRuntimeStubG__vtbl_
1067 +__1cNSafepointBlobG__vtbl_
1068 +__1cSDeoptimizationBlobG__vtbl_
1070 +__JvmOffsets
1071 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/hotspot/symbols/symbols-solaris-dtrace-compiler2 jdk21u-jdk-21.0.4-ga/make/hotspot/symbols/symbols-solaris-dtrace-compiler2
1072 --- jdk21u-jdk-21.0.4-ga.orig/make/hotspot/symbols/symbols-solaris-dtrace-compiler2 1970-01-01 01:00:00.000000000 +0100
1073 +++ jdk21u-jdk-21.0.4-ga/make/hotspot/symbols/symbols-solaris-dtrace-compiler2 2024-08-17 19:13:01.442281749 +0200
1074 @@ -0,0 +1,36 @@
1076 +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
1077 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1079 +# This code is free software; you can redistribute it and/or modify it
1080 +# under the terms of the GNU General Public License version 2 only, as
1081 +# published by the Free Software Foundation.
1083 +# This code is distributed in the hope that it will be useful, but WITHOUT
1084 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1085 +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1086 +# version 2 for more details (a copy is included in the LICENSE file that
1087 +# accompanied this code).
1089 +# You should have received a copy of the GNU General Public License version
1090 +# 2 along with this work; if not, write to the Free Software Foundation,
1091 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1093 +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1094 +# or visit www.oracle.com if you need additional information or have any
1095 +# questions.
1098 +__1cGMethodG__vtbl_
1099 +__1cHnmethodG__vtbl_
1100 +__1cICodeBlobG__vtbl_
1101 +__1cIUniverseO_collectedHeap_
1102 +__1cJCodeCacheG_heaps_
1103 +__1cKBufferBlobG__vtbl_
1104 +__1cLRuntimeStubG__vtbl_
1105 +__1cNSafepointBlobG__vtbl_
1106 +__1cSDeoptimizationBlobG__vtbl_
1107 +__1cNExceptionBlobG__vtbl_
1108 +__1cQUncommonTrapBlobG__vtbl_
1110 +__JvmOffsets
1111 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/ide/visualstudio/hotspot/CreateVSProject.gmk jdk21u-jdk-21.0.4-ga/make/ide/visualstudio/hotspot/CreateVSProject.gmk
1112 --- jdk21u-jdk-21.0.4-ga.orig/make/ide/visualstudio/hotspot/CreateVSProject.gmk 2024-07-09 10:07:16.000000000 +0200
1113 +++ jdk21u-jdk-21.0.4-ga/make/ide/visualstudio/hotspot/CreateVSProject.gmk 2024-08-17 19:13:01.372556758 +0200
1114 @@ -76,6 +76,7 @@
1115 -ignorePath linux \
1116 -ignorePath posix \
1117 -ignorePath ppc \
1118 + -ignorePath solaris \
1119 -ignorePath x86_32 \
1120 -ignorePath zero \
1122 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/langtools/build.xml jdk21u-jdk-21.0.4-ga/make/langtools/build.xml
1123 --- jdk21u-jdk-21.0.4-ga.orig/make/langtools/build.xml 2024-07-09 10:07:16.000000000 +0200
1124 +++ jdk21u-jdk-21.0.4-ga/make/langtools/build.xml 2024-08-17 19:13:01.373083341 +0200
1125 @@ -100,7 +100,7 @@
1126 <property name="xpatch.noquotes.cmd" value="--patch-module=${xpatch.noquotes.rest}"/>
1128 <!-- java.marker is set to a marker file to check for within a Java install dir.
1129 - The best file to check for across Linux/Windows/MacOS is one of the
1130 + The best file to check for across Solaris/Linux/Windows/MacOS is one of the
1131 executables; regrettably, that is OS-specific. -->
1132 <condition property="java.marker" value="bin/java">
1133 <os family="unix"/>
1134 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/modules/java.base/Copy.gmk jdk21u-jdk-21.0.4-ga/make/modules/java.base/Copy.gmk
1135 --- jdk21u-jdk-21.0.4-ga.orig/make/modules/java.base/Copy.gmk 2024-07-09 10:07:16.000000000 +0200
1136 +++ jdk21u-jdk-21.0.4-ga/make/modules/java.base/Copy.gmk 2024-08-17 19:13:01.373537891 +0200
1137 @@ -190,7 +190,7 @@
1139 TARGETS += $(NET_PROPERTIES_DST)
1141 -ifeq ($(call isTargetOs, linux), true)
1142 +ifeq ($(call isTargetOs, solaris linux), true)
1143 $(eval $(call SetupCopyFiles, COPY_SDP_CONF, \
1144 FILES := $(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/conf/sdp/sdp.conf.template, \
1145 DEST := $(CONF_DST_DIR)/sdp, \
1146 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/modules/java.base/gensrc/GensrcMisc.gmk jdk21u-jdk-21.0.4-ga/make/modules/java.base/gensrc/GensrcMisc.gmk
1147 --- jdk21u-jdk-21.0.4-ga.orig/make/modules/java.base/gensrc/GensrcMisc.gmk 2024-07-09 10:07:16.000000000 +0200
1148 +++ jdk21u-jdk-21.0.4-ga/make/modules/java.base/gensrc/GensrcMisc.gmk 2024-08-17 19:13:01.374994375 +0200
1149 @@ -136,6 +136,21 @@
1151 endif
1153 +################################################################################
1155 +ifeq ($(call isTargetOs, solaris), true)
1157 + GENSRC_SC_FILE := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/fs/SolarisConstants.java
1159 + $(GENSRC_SC_FILE): \
1160 + $(TOPDIR)/src/java.base/solaris/classes/sun/nio/fs/SolarisConstants.java.template
1161 + $(generate-preproc-src)
1163 + TARGETS += $(GENSRC_SC_FILE)
1165 +endif
1167 +################################################################################
1168 # Create the javax/crypto/JceSecurity.class, using the build default.
1170 ifeq ($(UNLIMITED_CRYPTO), true)
1171 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/modules/java.base/Launcher.gmk jdk21u-jdk-21.0.4-ga/make/modules/java.base/Launcher.gmk
1172 --- jdk21u-jdk-21.0.4-ga.orig/make/modules/java.base/Launcher.gmk 2024-07-09 10:07:16.000000000 +0200
1173 +++ jdk21u-jdk-21.0.4-ga/make/modules/java.base/Launcher.gmk 2024-08-17 19:13:01.373994540 +0200
1174 @@ -64,6 +64,7 @@
1175 CFLAGS := $(CFLAGS_JDKEXE) \
1176 -I$(TOPDIR)/src/$(MODULE)/share/native/libjli, \
1177 CFLAGS_linux := -fPIC, \
1178 + CFLAGS_solaris := -KPIC, \
1179 LDFLAGS := $(LDFLAGS_JDKEXE), \
1180 OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/modules_libs/$(MODULE), \
1182 @@ -73,7 +74,7 @@
1184 ################################################################################
1186 -ifeq ($(call isTargetOs, macosx aix linux), true)
1187 +ifeq ($(call isTargetOs, macosx solaris aix linux), true)
1188 $(eval $(call SetupJdkExecutable, BUILD_JSPAWNHELPER, \
1189 NAME := jspawnhelper, \
1190 SRC := $(TOPDIR)/src/$(MODULE)/unix/native/jspawnhelper, \
1191 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/modules/java.base/lib/CoreLibraries.gmk jdk21u-jdk-21.0.4-ga/make/modules/java.base/lib/CoreLibraries.gmk
1192 --- jdk21u-jdk-21.0.4-ga.orig/make/modules/java.base/lib/CoreLibraries.gmk 2024-07-09 10:07:16.000000000 +0200
1193 +++ jdk21u-jdk-21.0.4-ga/make/modules/java.base/lib/CoreLibraries.gmk 2024-08-17 19:13:01.375549227 +0200
1194 @@ -26,7 +26,7 @@
1195 ##########################################################################################
1197 LIBVERIFY_OPTIMIZATION := HIGH
1198 -ifeq ($(call isTargetOs, linux), true)
1199 +ifeq ($(call isTargetOs, solaris linux), true)
1200 ifeq ($(COMPILE_WITH_DEBUG_SYMBOLS), true)
1201 LIBVERIFY_OPTIMIZATION := LOW
1202 endif
1203 @@ -68,6 +68,7 @@
1204 LDFLAGS_windows := -delayload:shell32.dll, \
1205 LIBS_unix := -ljvm, \
1206 LIBS_linux := $(LIBDL), \
1207 + LIBS_solaris := -lsocket -lnsl -lscf $(LIBDL), \
1208 LIBS_aix := $(LIBDL) $(LIBM),\
1209 LIBS_macosx := -framework CoreFoundation \
1210 -framework Foundation \
1211 @@ -178,6 +179,7 @@
1212 $(call SET_SHARED_LIBRARY_ORIGIN), \
1213 LIBS_unix := $(LIBZ_LIBS), \
1214 LIBS_linux := $(LIBDL) -lpthread, \
1215 + LIBS_solaris := $(LIBDL), \
1216 LIBS_aix := $(LIBDL),\
1217 LIBS_macosx := -framework Cocoa -framework Security -framework ApplicationServices, \
1218 LIBS_windows := advapi32.lib comctl32.lib user32.lib, \
1219 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/modules/java.base/Lib.gmk jdk21u-jdk-21.0.4-ga/make/modules/java.base/Lib.gmk
1220 --- jdk21u-jdk-21.0.4-ga.orig/make/modules/java.base/Lib.gmk 2024-07-09 10:07:16.000000000 +0200
1221 +++ jdk21u-jdk-21.0.4-ga/make/modules/java.base/Lib.gmk 2024-08-17 19:13:01.374508351 +0200
1222 @@ -55,6 +55,7 @@
1223 LDFLAGS_windows := -delayload:secur32.dll -delayload:iphlpapi.dll, \
1224 LIBS_unix := -ljvm -ljava, \
1225 LIBS_linux := $(LIBDL), \
1226 + LIBS_solaris := -lnsl -lsocket $(LIBDL), \
1227 LIBS_aix := $(LIBDL),\
1228 LIBS_windows := ws2_32.lib jvm.lib secur32.lib iphlpapi.lib winhttp.lib \
1229 delayimp.lib $(WIN_JAVA_LIB) advapi32.lib, \
1230 @@ -81,6 +82,8 @@
1231 $(call SET_SHARED_LIBRARY_ORIGIN), \
1232 LIBS_unix := -ljava -lnet, \
1233 LIBS_linux := -lpthread $(LIBDL), \
1234 + LIBS_solaris := -ljvm -lsocket -lposix4 $(LIBDL) \
1235 + -lsendfile, \
1236 LIBS_aix := $(LIBDL), \
1237 LIBS_macosx := \
1238 -framework CoreFoundation -framework CoreServices, \
1239 @@ -133,6 +136,7 @@
1240 LDFLAGS := $(LDFLAGS_JDKLIB) \
1241 $(call SET_SHARED_LIBRARY_ORIGIN), \
1242 LIBS_linux := $(LIBDL), \
1243 + LIBS_solaris := $(LIBDL), \
1244 LIBS_aix := $(LIBDL), \
1247 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/modules/java.desktop/Gensrc.gmk jdk21u-jdk-21.0.4-ga/make/modules/java.desktop/Gensrc.gmk
1248 --- jdk21u-jdk-21.0.4-ga.orig/make/modules/java.desktop/Gensrc.gmk 2024-07-09 10:07:16.000000000 +0200
1249 +++ jdk21u-jdk-21.0.4-ga/make/modules/java.desktop/Gensrc.gmk 2024-08-17 19:13:01.375987280 +0200
1250 @@ -32,7 +32,7 @@
1251 include gensrc/GensrcIcons.gmk
1252 endif
1254 -ifeq ($(call isTargetOs, linux aix), true)
1255 +ifeq ($(call isTargetOs, linux solaris aix), true)
1256 include gensrc/GensrcX11Wrappers.gmk
1257 endif
1259 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/modules/java.desktop/lib/Awt2dLibraries.gmk jdk21u-jdk-21.0.4-ga/make/modules/java.desktop/lib/Awt2dLibraries.gmk
1260 --- jdk21u-jdk-21.0.4-ga.orig/make/modules/java.desktop/lib/Awt2dLibraries.gmk 2024-07-09 10:07:16.000000000 +0200
1261 +++ jdk21u-jdk-21.0.4-ga/make/modules/java.desktop/lib/Awt2dLibraries.gmk 2024-08-17 19:13:01.377263959 +0200
1262 @@ -77,7 +77,7 @@
1264 endif
1266 -ifeq ($(call isTargetOs, linux macosx aix), true)
1267 +ifeq ($(call isTargetOs, solaris linux macosx aix), true)
1268 LIBAWT_EXFILES += awt_Font.c CUPSfuncs.c fontpath.c X11Color.c
1269 endif
1271 @@ -154,6 +154,7 @@
1272 -delayload:comctl32.dll -delayload:shlwapi.dll, \
1273 LIBS_unix := -ljvm -ljava $(LIBM), \
1274 LIBS_linux := $(LIBDL), \
1275 + LIBS_solaris := $(LIBDL), \
1276 LIBS_aix := $(LIBDL),\
1277 LIBS_macosx := -lmlib_image \
1278 -framework Cocoa \
1279 @@ -395,6 +396,7 @@
1280 LDFLAGS_unix := -L$(INSTALL_LIBRARIES_HERE), \
1281 LIBS_unix := -lawt -ljvm -ljava, \
1282 LIBS_linux := $(LIBM) $(LIBDL), \
1283 + LIBS_solaris := $(LIBM) $(LIBDL) $(LIBCXX), \
1286 $(BUILD_LIBAWT_HEADLESS): $(BUILD_LIBAWT)
1287 @@ -452,7 +454,7 @@
1288 -DHAVE_SYSCONF -DHAVE_SYS_MMAN_H -DHAVE_UNISTD_H \
1289 -DHB_NO_PRAGMA_GCC_DIAGNOSTIC
1290 endif
1291 - ifeq ($(call isTargetOs, linux macosx), true)
1292 + ifeq ($(call isTargetOs, solaris linux macosx), true)
1293 HARFBUZZ_CFLAGS += -DHAVE_INTEL_ATOMIC_PRIMITIVES -DHB_NO_VISIBILITY
1294 endif
1296 @@ -623,7 +625,10 @@
1297 ifeq ($(call isTargetOs, macosx), true)
1298 JAWT_LIBS := -lawt_lwawt
1299 else
1300 - JAWT_LIBS := -lawt
1301 + JAWT_LIBS :=
1302 + ifeq ($(call isTargetOs, solaris), false)
1303 + JAWT_LIBS += -lawt
1304 + endif
1305 ifeq ($(ENABLE_HEADLESS_ONLY), false)
1306 JAWT_LIBS += -lawt_xawt
1307 else
1308 @@ -650,6 +655,7 @@
1309 LDFLAGS_unix := -L$(INSTALL_LIBRARIES_HERE), \
1310 LDFLAGS_macosx := -Wl$(COMMA)-rpath$(COMMA)@loader_path, \
1311 LIBS_unix := $(JAWT_LIBS) $(JDKLIB_LIBS), \
1312 + LIBS_solaris := $(X_LIBS) -lXrender, \
1313 LIBS_macosx := -framework Cocoa, \
1316 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/modules/java.desktop/Lib.gmk jdk21u-jdk-21.0.4-ga/make/modules/java.desktop/Lib.gmk
1317 --- jdk21u-jdk-21.0.4-ga.orig/make/modules/java.desktop/Lib.gmk 2024-07-09 10:07:16.000000000 +0200
1318 +++ jdk21u-jdk-21.0.4-ga/make/modules/java.desktop/Lib.gmk 2024-08-17 19:13:01.376399889 +0200
1319 @@ -47,10 +47,15 @@
1320 -DX_PLATFORM=X_$(OPENJDK_TARGET_OS_UPPERCASE) \
1321 -DUSE_PORTS=TRUE \
1322 -DUSE_DAUDIO=TRUE \
1323 - -DUSE_PLATFORM_MIDI_OUT=TRUE \
1324 - -DUSE_PLATFORM_MIDI_IN=TRUE \
1327 + ifeq ($(call isTargetOs, solaris), false)
1328 + LIBJSOUND_CFLAGS += \
1329 + -DUSE_PLATFORM_MIDI_OUT=TRUE \
1330 + -DUSE_PLATFORM_MIDI_IN=TRUE \
1332 + endif
1334 ifeq ($(call isTargetOs, macosx), true)
1335 LIBJSOUND_TOOLCHAIN := TOOLCHAIN_LINK_CXX
1336 endif
1337 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/modules/java.instrument/Lib.gmk jdk21u-jdk-21.0.4-ga/make/modules/java.instrument/Lib.gmk
1338 --- jdk21u-jdk-21.0.4-ga.orig/make/modules/java.instrument/Lib.gmk 2024-07-09 10:07:16.000000000 +0200
1339 +++ jdk21u-jdk-21.0.4-ga/make/modules/java.instrument/Lib.gmk 2024-08-17 19:13:01.377687443 +0200
1340 @@ -44,11 +44,13 @@
1341 $(call SET_SHARED_LIBRARY_ORIGIN) \
1342 $(LIBINSTRUMENT_LDFLAGS), \
1343 LDFLAGS_linux := -L$(call FindLibDirForModule, java.base), \
1344 + LDFLAGS_solaris := -L$(call FindLibDirForModule, java.base), \
1345 LDFLAGS_macosx := -L$(call FindLibDirForModule, java.base), \
1346 LDFLAGS_aix := -L$(SUPPORT_OUTPUTDIR)/native/java.base, \
1347 LIBS := $(JDKLIB_LIBS), \
1348 LIBS_unix := -ljava -ljvm $(LIBZ_LIBS), \
1349 LIBS_linux := -ljli $(LIBDL), \
1350 + LIBS_solaris := -ljli $(LIBDL), \
1351 LIBS_aix := -liconv -ljli_static $(LIBDL), \
1352 LIBS_macosx := -ljli -liconv -framework Cocoa -framework Security \
1353 -framework ApplicationServices, \
1354 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/modules/java.management/Lib.gmk jdk21u-jdk-21.0.4-ga/make/modules/java.management/Lib.gmk
1355 --- jdk21u-jdk-21.0.4-ga.orig/make/modules/java.management/Lib.gmk 2024-07-09 10:07:16.000000000 +0200
1356 +++ jdk21u-jdk-21.0.4-ga/make/modules/java.management/Lib.gmk 2024-08-17 19:13:01.378170399 +0200
1357 @@ -28,7 +28,7 @@
1358 ################################################################################
1360 LIBMANAGEMENT_OPTIMIZATION := HIGH
1361 -ifeq ($(call isTargetOs, linux), true)
1362 +ifeq ($(call isTargetOs, solaris linux), true)
1363 ifeq ($(COMPILE_WITH_DEBUG_SYMBOLS), true)
1364 LIBMANAGEMENT_OPTIMIZATION := LOW
1365 endif
1366 @@ -41,6 +41,7 @@
1367 LDFLAGS := $(LDFLAGS_JDKLIB) \
1368 $(call SET_SHARED_LIBRARY_ORIGIN), \
1369 LIBS := $(JDKLIB_LIBS), \
1370 + LIBS_solaris := -lkstat, \
1371 LIBS_aix := -lperfstat,\
1372 LIBS_windows := jvm.lib psapi.lib $(WIN_JAVA_LIB) advapi32.lib, \
1374 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/modules/java.prefs/Lib.gmk jdk21u-jdk-21.0.4-ga/make/modules/java.prefs/Lib.gmk
1375 --- jdk21u-jdk-21.0.4-ga.orig/make/modules/java.prefs/Lib.gmk 2024-07-09 10:07:16.000000000 +0200
1376 +++ jdk21u-jdk-21.0.4-ga/make/modules/java.prefs/Lib.gmk 2024-08-17 19:13:01.378602060 +0200
1377 @@ -41,6 +41,7 @@
1378 $(call SET_SHARED_LIBRARY_ORIGIN), \
1379 LIBS_unix := -ljvm, \
1380 LIBS_linux := -ljava, \
1381 + LIBS_solaris := -ljava, \
1382 LIBS_aix := -ljava, \
1383 LIBS_macosx := -framework CoreFoundation -framework Foundation, \
1384 LIBS_windows := advapi32.lib jvm.lib $(WIN_JAVA_LIB), \
1385 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/modules/jdk.attach/Lib.gmk jdk21u-jdk-21.0.4-ga/make/modules/jdk.attach/Lib.gmk
1386 --- jdk21u-jdk-21.0.4-ga.orig/make/modules/jdk.attach/Lib.gmk 2024-07-09 10:07:16.000000000 +0200
1387 +++ jdk21u-jdk-21.0.4-ga/make/modules/jdk.attach/Lib.gmk 2024-08-17 19:13:01.379002692 +0200
1388 @@ -42,6 +42,7 @@
1389 LDFLAGS := $(LDFLAGS_JDKLIB) \
1390 $(call SET_SHARED_LIBRARY_ORIGIN), \
1391 LIBS := $(JDKLIB_LIBS), \
1392 + LIBS_solaris := -ldoor, \
1393 LIBS_windows := $(WIN_JAVA_LIB) advapi32.lib psapi.lib, \
1396 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/modules/jdk.crypto.cryptoki/Copy.gmk jdk21u-jdk-21.0.4-ga/make/modules/jdk.crypto.cryptoki/Copy.gmk
1397 --- jdk21u-jdk-21.0.4-ga.orig/make/modules/jdk.crypto.cryptoki/Copy.gmk 1970-01-01 01:00:00.000000000 +0100
1398 +++ jdk21u-jdk-21.0.4-ga/make/modules/jdk.crypto.cryptoki/Copy.gmk 2024-08-17 19:13:01.442625553 +0200
1399 @@ -0,0 +1,45 @@
1401 +# Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
1402 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1404 +# This code is free software; you can redistribute it and/or modify it
1405 +# under the terms of the GNU General Public License version 2 only, as
1406 +# published by the Free Software Foundation. Oracle designates this
1407 +# particular file as subject to the "Classpath" exception as provided
1408 +# by Oracle in the LICENSE file that accompanied this code.
1410 +# This code is distributed in the hope that it will be useful, but WITHOUT
1411 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1412 +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1413 +# version 2 for more details (a copy is included in the LICENSE file that
1414 +# accompanied this code).
1416 +# You should have received a copy of the GNU General Public License version
1417 +# 2 along with this work; if not, write to the Free Software Foundation,
1418 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1420 +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1421 +# or visit www.oracle.com if you need additional information or have any
1422 +# questions.
1425 +include CopyCommon.gmk
1427 +################################################################################
1429 +ifeq ($(call isTargetOs, solaris), true)
1431 + SUNPKCS11_CFG_SRC := \
1432 + $(TOPDIR)/src/jdk.crypto.cryptoki/solaris/conf/security/sunpkcs11-solaris.cfg
1433 + SUNPKCS11_CFG_DST := $(CONF_DST_DIR)/security/sunpkcs11-solaris.cfg
1435 + $(SUNPKCS11_CFG_DST): $(SUNPKCS11_CFG_SRC)
1436 + $(call install-file)
1438 + SECURITY_PKCS11_CONF_FILES += $(SUNPKCS11_CFG_DST)
1440 + TARGETS := $(SUNPKCS11_CFG_DST)
1442 +endif
1444 +################################################################################
1445 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/modules/jdk.hotspot.agent/Lib.gmk jdk21u-jdk-21.0.4-ga/make/modules/jdk.hotspot.agent/Lib.gmk
1446 --- jdk21u-jdk-21.0.4-ga.orig/make/modules/jdk.hotspot.agent/Lib.gmk 2024-07-09 10:07:16.000000000 +0200
1447 +++ jdk21u-jdk-21.0.4-ga/make/modules/jdk.hotspot.agent/Lib.gmk 2024-08-17 19:13:01.379470424 +0200
1448 @@ -67,10 +67,11 @@
1449 CFLAGS := $(CFLAGS_JDKLIB) $(SA_CFLAGS), \
1450 CXXFLAGS := $(CXXFLAGS_JDKLIB) $(SA_CFLAGS) $(SA_CXXFLAGS), \
1451 EXTRA_SRC := $(LIBSA_EXTRA_SRC), \
1452 - LDFLAGS := $(LDFLAGS_JDKLIB) $(call SET_SHARED_LIBRARY_ORIGIN), \
1453 + LDFLAGS := $(LDFLAGS_JDKLIB) $(SA_LDFLAGS) $(call SET_SHARED_LIBRARY_ORIGIN), \
1454 LIBS := $(LIBCXX), \
1455 LIBS_unix := -ljava, \
1456 LIBS_linux := $(LIBDL), \
1457 + LIBS_solaris := -ldl -lstdc++ -lthread -lproc, \
1458 LIBS_macosx := -framework Foundation \
1459 -framework JavaRuntimeSupport -framework Security -framework CoreFoundation, \
1460 LIBS_windows := dbgeng.lib $(WIN_JAVA_LIB), \
1461 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/modules/jdk.jdwp.agent/Lib.gmk jdk21u-jdk-21.0.4-ga/make/modules/jdk.jdwp.agent/Lib.gmk
1462 --- jdk21u-jdk-21.0.4-ga.orig/make/modules/jdk.jdwp.agent/Lib.gmk 2024-07-09 10:07:16.000000000 +0200
1463 +++ jdk21u-jdk-21.0.4-ga/make/modules/jdk.jdwp.agent/Lib.gmk 2024-08-17 19:13:01.379970857 +0200
1464 @@ -38,6 +38,7 @@
1465 LDFLAGS := $(LDFLAGS_JDKLIB) \
1466 $(call SET_SHARED_LIBRARY_ORIGIN), \
1467 LIBS_linux := -lpthread, \
1468 + LIBS_solaris := -lnsl -lsocket, \
1469 LIBS_windows := $(JDKLIB_LIBS) ws2_32.lib iphlpapi.lib, \
1472 @@ -65,6 +66,7 @@
1473 $(call SET_SHARED_LIBRARY_ORIGIN), \
1474 LIBS := $(JDKLIB_LIBS), \
1475 LIBS_linux := $(LIBDL), \
1476 + LIBS_solaris := $(LIBDL), \
1477 LIBS_macosx := -liconv, \
1478 LIBS_aix := -liconv, \
1480 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/modules/jdk.management/Lib.gmk jdk21u-jdk-21.0.4-ga/make/modules/jdk.management/Lib.gmk
1481 --- jdk21u-jdk-21.0.4-ga.orig/make/modules/jdk.management/Lib.gmk 2024-07-09 10:07:16.000000000 +0200
1482 +++ jdk21u-jdk-21.0.4-ga/make/modules/jdk.management/Lib.gmk 2024-08-17 19:13:01.380454497 +0200
1483 @@ -35,7 +35,7 @@
1484 endif
1486 LIBMANAGEMENT_EXT_OPTIMIZATION := HIGH
1487 -ifeq ($(call isTargetOs, linux), true)
1488 +ifeq ($(call isTargetOs, solaris linux), true)
1489 ifeq ($(COMPILE_WITH_DEBUG_SYMBOLS), true)
1490 LIBMANAGEMENT_EXT_OPTIMIZATION := LOW
1491 endif
1492 @@ -48,6 +48,7 @@
1493 LDFLAGS := $(LDFLAGS_JDKLIB) \
1494 $(call SET_SHARED_LIBRARY_ORIGIN), \
1495 LIBS := $(JDKLIB_LIBS), \
1496 + LIBS_solaris := -lkstat, \
1497 LIBS_aix := -lperfstat,\
1498 LIBS_windows := jvm.lib psapi.lib $(WIN_JAVA_LIB) advapi32.lib, \
1500 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/modules/jdk.net/Lib.gmk jdk21u-jdk-21.0.4-ga/make/modules/jdk.net/Lib.gmk
1501 --- jdk21u-jdk-21.0.4-ga.orig/make/modules/jdk.net/Lib.gmk 2024-07-09 10:07:16.000000000 +0200
1502 +++ jdk21u-jdk-21.0.4-ga/make/modules/jdk.net/Lib.gmk 2024-08-17 19:13:01.380883314 +0200
1503 @@ -36,6 +36,7 @@
1504 LDFLAGS := $(LDFLAGS_JDKLIB) \
1505 $(call SET_SHARED_LIBRARY_ORIGIN), \
1506 LIBS_unix := -ljava, \
1507 + LIBS_solaris := -lsocket, \
1508 LIBS_linux := -ljvm, \
1509 LIBS_windows := jvm.lib ws2_32.lib $(WIN_JAVA_LIB), \
1511 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/modules/jdk.sctp/Lib.gmk jdk21u-jdk-21.0.4-ga/make/modules/jdk.sctp/Lib.gmk
1512 --- jdk21u-jdk-21.0.4-ga.orig/make/modules/jdk.sctp/Lib.gmk 2024-07-09 10:07:16.000000000 +0200
1513 +++ jdk21u-jdk-21.0.4-ga/make/modules/jdk.sctp/Lib.gmk 2024-08-17 19:13:01.381279620 +0200
1514 @@ -42,6 +42,7 @@
1515 $(call SET_SHARED_LIBRARY_ORIGIN), \
1516 LIBS_unix := -lnio -lnet -ljava -ljvm, \
1517 LIBS_linux := -lpthread $(LIBDL), \
1518 + LIBS_solaris := -lsocket, \
1521 TARGETS += $(BUILD_LIBSCTP)
1522 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/RunTestsPrebuilt.gmk jdk21u-jdk-21.0.4-ga/make/RunTestsPrebuilt.gmk
1523 --- jdk21u-jdk-21.0.4-ga.orig/make/RunTestsPrebuilt.gmk 2024-07-09 10:07:16.000000000 +0200
1524 +++ jdk21u-jdk-21.0.4-ga/make/RunTestsPrebuilt.gmk 2024-08-17 19:13:01.361418188 +0200
1525 @@ -168,6 +168,8 @@
1526 OPENJDK_TARGET_OS := linux
1527 else ifeq ($(UNAME_OS), Darwin)
1528 OPENJDK_TARGET_OS := macosx
1529 + else ifeq ($(UNAME_OS), SunOS)
1530 + OPENJDK_TARGET_OS := solaris
1531 else
1532 OPENJDK_TARGET_OS := $(UNAME_OS)
1533 endif
1534 @@ -180,15 +182,28 @@
1535 # Assume little endian unless otherwise specified
1536 OPENJDK_TARGET_CPU_ENDIAN := little
1538 -UNAME_CPU := $(shell $(UNAME) -m)
1539 -ifeq ($(UNAME_CPU), i686)
1540 - OPENJDK_TARGET_CPU := x86
1541 - OPENJDK_TARGET_CPU_BITS := 32
1542 -else
1543 - # Assume all others are 64-bit. We use the same CPU name as uname for
1544 - # at least x86_64 and aarch64.
1545 - OPENJDK_TARGET_CPU := $(UNAME_CPU)
1546 +ifeq ($(OPENJDK_TARGET_OS), solaris)
1547 + # On solaris, use uname -p
1548 + UNAME_CPU := $(shell $(UNAME) -p)
1549 + # Assume 64-bit platform
1550 OPENJDK_TARGET_CPU_BITS := 64
1551 + ifeq ($(UNAME_CPU), i386)
1552 + OPENJDK_TARGET_CPU := x86_64
1553 + else
1554 + OPENJDK_TARGET_CPU := $(UNAME_CPU)
1555 + endif
1556 +else
1557 + # ... all others use uname -m
1558 + UNAME_CPU := $(shell $(UNAME) -m)
1559 + ifeq ($(UNAME_CPU), i686)
1560 + OPENJDK_TARGET_CPU := x86
1561 + OPENJDK_TARGET_CPU_BITS := 32
1562 + else
1563 + # Assume all others are 64-bit. We use the same CPU name as uname for
1564 + # at least x86_64 and aarch64.
1565 + OPENJDK_TARGET_CPU := $(UNAME_CPU)
1566 + OPENJDK_TARGET_CPU_BITS := 64
1567 + endif
1568 endif
1570 OPENJDK_TARGET_CPU_ARCH := $(OPENJDK_TARGET_CPU)
1571 @@ -213,6 +228,11 @@
1572 else ifeq ($(OPENJDK_TARGET_OS), macosx)
1573 NUM_CORES := $(shell /usr/sbin/sysctl -n hw.ncpu)
1574 MEMORY_SIZE := $(shell $(EXPR) `/usr/sbin/sysctl -n hw.memsize` / 1024 / 1024)
1575 +else ifeq ($(OPENJDK_TARGET_OS), solaris)
1576 + NUM_CORES := $(shell /usr/sbin/psrinfo -v | $(GREP) -c on-line)
1577 + MEMORY_SIZE := $(shell \
1578 + /usr/sbin/prtconf 2> /dev/null | $(GREP) "^Memory [Ss]ize" | $(AWK) '{print $$3}' \
1580 else ifeq ($(OPENJDK_TARGET_OS), windows)
1581 NUM_CORES := $(NUMBER_OF_PROCESSORS)
1582 MEMORY_SIZE := $(shell \
1583 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/RunTestsPrebuiltSpec.gmk jdk21u-jdk-21.0.4-ga/make/RunTestsPrebuiltSpec.gmk
1584 --- jdk21u-jdk-21.0.4-ga.orig/make/RunTestsPrebuiltSpec.gmk 2024-07-09 10:07:16.000000000 +0200
1585 +++ jdk21u-jdk-21.0.4-ga/make/RunTestsPrebuiltSpec.gmk 2024-08-17 19:13:01.361862381 +0200
1586 @@ -173,6 +173,16 @@
1587 FILE := file
1588 ULIMIT := ulimit
1590 +# On Solaris gnu versions of some tools are required.
1591 +ifeq ($(OPENJDK_BUILD_OS), solaris)
1592 + AWK := gawk
1593 + GREP := ggrep
1594 + EGREP := ggrep -E
1595 + FGREP := grep -F
1596 + SED := gsed
1597 + TAR := gtar
1598 +endif
1600 ifeq ($(OPENJDK_BUILD_OS), windows)
1601 PATHTOOL := cygpath
1602 endif
1603 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/scripts/compare_exceptions.sh.incl jdk21u-jdk-21.0.4-ga/make/scripts/compare_exceptions.sh.incl
1604 --- jdk21u-jdk-21.0.4-ga.orig/make/scripts/compare_exceptions.sh.incl 2024-07-09 10:07:16.000000000 +0200
1605 +++ jdk21u-jdk-21.0.4-ga/make/scripts/compare_exceptions.sh.incl 2024-08-17 19:13:01.382582562 +0200
1606 @@ -45,6 +45,20 @@
1607 ./hotspot/gtest/server/libjvm.so
1610 +elif [ "$OPENJDK_TARGET_OS" = "solaris" ]; then
1611 + SKIP_BIN_DIFF="true"
1612 + SKIP_FULLDUMP_DIFF="true"
1613 + MAX_KNOWN_DIS_DIFF_SIZE="3000"
1614 + SORT_SYMBOLS="
1615 + ./lib/libfontmanager.so
1616 + ./lib/libjimage.so
1617 + ./lib/server/libjvm.so
1618 + ./hotspot/gtest/server/libjvm.so
1620 + KNOWN_DIS_DIFF="
1621 + ./lib/libfontmanager.so
1623 + STRIP_TESTS_BEFORE_COMPARE="true"
1624 elif [ "$OPENJDK_TARGET_OS" = "windows" ]; then
1625 SKIP_BIN_DIFF="true"
1626 SKIP_FULLDUMP_DIFF="true"
1627 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/scripts/compare.sh jdk21u-jdk-21.0.4-ga/make/scripts/compare.sh
1628 --- jdk21u-jdk-21.0.4-ga.orig/make/scripts/compare.sh 2024-07-09 10:07:16.000000000 +0200
1629 +++ jdk21u-jdk-21.0.4-ga/make/scripts/compare.sh 2024-08-17 19:13:01.382159080 +0200
1630 @@ -73,7 +73,14 @@
1631 # Disassembly diff filters. These filters try to filter out ephemeral parts of the
1632 # disassembly, such as hard-coded addresses, to be able to catch "actual" differences.
1634 -if [ "$OPENJDK_TARGET_OS" = "windows" ]; then
1635 +if [ "$OPENJDK_TARGET_OS" = "solaris" ]; then
1636 + if [ "$OPENJDK_TARGET_CPU" = "x86_64" ]; then
1637 + # Random strings looking like this differ: <.XAKoKoPIac2W0OA.
1638 + DIS_DIFF_FILTER="$SED \
1639 + -e 's/<\.[A-Za-z0-9]\{\15}\./<.SYM./' \
1641 + fi
1642 +elif [ "$OPENJDK_TARGET_OS" = "windows" ]; then
1643 if [ "$OPENJDK_TARGET_CPU" = "x86" ]; then
1644 DIS_DIFF_FILTER="$SED -r \
1645 -e 's/^ [0-9A-F]{16}: //' \
1646 @@ -440,7 +447,14 @@
1649 CONTENTS_DIFF_FILE=$WORK_DIR/$ZIP_FILE.diff
1650 - $DIFF -rq $OTHER_UNZIPDIR $THIS_UNZIPDIR > $CONTENTS_DIFF_FILE
1651 + # On solaris, there is no -q option.
1652 + if [ "$OPENJDK_TARGET_OS" = "solaris" ]; then
1653 + $DIFF -r $OTHER_UNZIPDIR $THIS_UNZIPDIR \
1654 + | $GREP -v -e "^<" -e "^>" -e "^Common subdirectories:" \
1655 + > $CONTENTS_DIFF_FILE
1656 + else
1657 + $DIFF -rq $OTHER_UNZIPDIR $THIS_UNZIPDIR > $CONTENTS_DIFF_FILE
1658 + fi
1660 ONLY_OTHER=$($GREP "^Only in $OTHER_UNZIPDIR" $CONTENTS_DIFF_FILE)
1661 ONLY_THIS=$($GREP "^Only in $THIS_UNZIPDIR" $CONTENTS_DIFF_FILE)
1662 @@ -460,8 +474,14 @@
1665 if [ "$CMP_ZIPS_CONTENTS" = "true" ]; then
1666 - DIFFING_FILES=$($GREP -e "differ$" $CONTENTS_DIFF_FILE \
1667 - | $CUT -f 2 -d ' ' | $SED "s|$OTHER_UNZIPDIR/||g")
1668 + if [ "$OPENJDK_TARGET_OS" = "solaris" ]; then
1669 + DIFFING_FILES=$($GREP -e 'differ$' -e '^diff ' $CONTENTS_DIFF_FILE \
1670 + | $SED -e 's/^Files //g' -e 's/diff -r //g' | $CUT -f 1 -d ' ' \
1671 + | $SED "s|$OTHER_UNZIPDIR/||g")
1672 + else
1673 + DIFFING_FILES=$($GREP -e "differ$" $CONTENTS_DIFF_FILE \
1674 + | $CUT -f 2 -d ' ' | $SED "s|$OTHER_UNZIPDIR/||g")
1675 + fi
1677 # Separate executable/library files from other files in zip.
1678 DIFFING_TEXT_FILES=
1679 @@ -806,6 +826,10 @@
1680 # to filter out that extra information.
1681 $DUMPBIN -exports $OTHER_FILE | $GREP -E '^ +[0-9A-F]+ +[0-9A-F]+ [0-9A-F]+' | sed 's/ = .*//g' | cut -c27- | $SYM_SORT_CMD > $WORK_FILE_BASE.symbols.other
1682 $DUMPBIN -exports $THIS_FILE | $GREP -E '^ +[0-9A-F]+ +[0-9A-F]+ [0-9A-F]+' | sed 's/ = .*//g' | cut -c27- | $SYM_SORT_CMD > $WORK_FILE_BASE.symbols.this
1683 + elif [ "$OPENJDK_TARGET_OS" = "solaris" ]; then
1684 + # Some symbols get seemingly random 15 character prefixes. Filter them out.
1685 + $NM -a $ORIG_OTHER_FILE 2> /dev/null | $GREP -v $NAME | $AWK '{print $2, $3, $4, $5}' | $SED 's/^\([a-zA-Z] [\.\$]\)[a-zA-Z0-9_\$]\{15,15\}\./\1./g' | $SYM_SORT_CMD > $WORK_FILE_BASE.symbols.other
1686 + $NM -a $ORIG_THIS_FILE 2> /dev/null | $GREP -v $NAME | $AWK '{print $2, $3, $4, $5}' | $SED 's/^\([a-zA-Z] [\.\$]\)[a-zA-Z0-9_\$]\{15,15\}\./\1./g' | $SYM_SORT_CMD > $WORK_FILE_BASE.symbols.this
1687 elif [ "$OPENJDK_TARGET_OS" = "aix" ]; then
1688 $OBJDUMP -T $ORIG_OTHER_FILE 2> /dev/null | $GREP -v $NAME | $AWK '{print $2, $3, $4, $5}' | $SYM_SORT_CMD > $WORK_FILE_BASE.symbols.other
1689 $OBJDUMP -T $ORIG_THIS_FILE 2> /dev/null | $GREP -v $NAME | $AWK '{print $2, $3, $4, $5}' | $SYM_SORT_CMD > $WORK_FILE_BASE.symbols.this
1690 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/scripts/hide_important_warnings_from_javac.sh jdk21u-jdk-21.0.4-ga/make/scripts/hide_important_warnings_from_javac.sh
1691 --- jdk21u-jdk-21.0.4-ga.orig/make/scripts/hide_important_warnings_from_javac.sh 2024-07-09 10:07:16.000000000 +0200
1692 +++ jdk21u-jdk-21.0.4-ga/make/scripts/hide_important_warnings_from_javac.sh 2024-08-17 19:13:01.382988601 +0200
1693 @@ -22,8 +22,13 @@
1694 # questions.
1697 -GREP=grep
1699 +if [ -x /usr/bin/ggrep ] ; then
1700 + # Gnu grep on Solaris
1701 + # (reference configure and build/solaris-i586-clientANDserver-release/spec.gmk
1702 + GREP=/usr/bin/ggrep
1703 +else
1704 + GREP=grep
1707 EXP="Note: Some input files use or override a deprecated API."
1708 EXP="${EXP}|Note: Recompile with -Xlint:deprecation for details."
1709 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/test/JtregNativeHotspot.gmk jdk21u-jdk-21.0.4-ga/make/test/JtregNativeHotspot.gmk
1710 --- jdk21u-jdk-21.0.4-ga.orig/make/test/JtregNativeHotspot.gmk 2024-07-09 10:07:16.000000000 +0200
1711 +++ jdk21u-jdk-21.0.4-ga/make/test/JtregNativeHotspot.gmk 2024-08-17 19:13:01.383912636 +0200
1712 @@ -865,6 +865,10 @@
1714 BUILD_HOTSPOT_JTREG_EXECUTABLES_LIBS_exesigtest := -ljvm
1716 +ifeq ($(call isTargetOs, solaris), true)
1717 + BUILD_HOTSPOT_JTREG_EXCLUDE += libterminatedThread.c
1718 +endif
1720 ifeq ($(call isTargetOs, windows), true)
1721 BUILD_HOTSPOT_JTREG_EXECUTABLES_CFLAGS_exeFPRegs := -MT
1722 BUILD_HOTSPOT_JTREG_EXCLUDE += exesigtest.c libterminatedThread.c libTestJNI.c libCompleteExit.c libMonitorWithDeadObjectTest.c libTestPsig.c libnativeStack.c exeGetCreatedJavaVMs.c
1723 diff -Nru jdk21u-jdk-21.0.4-ga.orig/make/test/JtregNativeJdk.gmk jdk21u-jdk-21.0.4-ga/make/test/JtregNativeJdk.gmk
1724 --- jdk21u-jdk-21.0.4-ga.orig/make/test/JtregNativeJdk.gmk 2024-07-09 10:07:16.000000000 +0200
1725 +++ jdk21u-jdk-21.0.4-ga/make/test/JtregNativeJdk.gmk 2024-08-17 19:13:01.384367219 +0200
1726 @@ -107,6 +107,9 @@
1727 ifeq ($(call isTargetOs, linux), true)
1728 BUILD_JDK_JTREG_LIBRARIES_LIBS_libInheritedChannel := -ljava
1729 BUILD_JDK_JTREG_EXECUTABLES_LIBS_exelauncher := -ldl
1730 + else ifeq ($(call isTargetOs, solaris), true)
1731 + BUILD_JDK_JTREG_LIBRARIES_LIBS_libInheritedChannel := -ljava -lsocket -lnsl
1732 + BUILD_JDK_JTREG_EXECUTABLES_LIBS_exelauncher := -lthread -ldl
1733 endif
1734 BUILD_JDK_JTREG_EXECUTABLES_LIBS_exeJliLaunchTest := -ljli
1735 BUILD_JDK_JTREG_EXECUTABLES_LIBS_exeCallerAccessTest := -ljvm
1736 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/cpu/x86/globalDefinitions_x86.hpp jdk21u-jdk-21.0.4-ga/src/hotspot/cpu/x86/globalDefinitions_x86.hpp
1737 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/cpu/x86/globalDefinitions_x86.hpp 2024-07-09 10:07:16.000000000 +0200
1738 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/cpu/x86/globalDefinitions_x86.hpp 2024-08-17 19:13:01.385127522 +0200
1739 @@ -68,7 +68,7 @@
1740 #define INCLUDE_RTM_OPT 1
1741 #endif
1743 -#if defined(LINUX) || defined(__APPLE__)
1744 +#if defined(LINUX) || defined(SOLARIS) || defined(__APPLE__)
1745 #define SUPPORT_RESERVED_STACK_AREA
1746 #endif
1748 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os/posix/include/jvm_md.h jdk21u-jdk-21.0.4-ga/src/hotspot/os/posix/include/jvm_md.h
1749 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os/posix/include/jvm_md.h 2024-07-09 10:07:16.000000000 +0200
1750 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/os/posix/include/jvm_md.h 2024-08-17 19:13:01.385699895 +0200
1751 @@ -54,7 +54,7 @@
1752 #endif
1753 #define JNI_LIB_NAME(NAME) JNI_LIB_PREFIX NAME JNI_LIB_SUFFIX
1755 -#if defined(AIX)
1756 +#if defined(AIX) || defined(SOLARIS)
1757 #define JVM_MAXPATHLEN MAXPATHLEN
1758 #else
1759 // Hack: MAXPATHLEN is 4095 on some Linux and 4096 on others. This may
1760 @@ -87,8 +87,14 @@
1761 #define JVM_SIGTERM SIGTERM
1763 #define BREAK_SIGNAL SIGQUIT /* Thread dumping support. */
1764 +#ifdef SOLARIS
1765 +#define ASYNC_SIGNAL SIGJVM2 /* Event-based suspend/resume support */
1766 +#endif // SOLARIS
1767 #define SHUTDOWN1_SIGNAL SIGHUP /* Shutdown Hooks support. */
1768 #define SHUTDOWN2_SIGNAL SIGINT
1769 #define SHUTDOWN3_SIGNAL SIGTERM
1771 +/* With 1.4.1 libjsig added versioning: used in os_solaris.cpp and jsig.c */
1772 +#define JSIG_VERSION_1_4_1 0x30140100
1774 #endif /* !_JAVASOFT_JVM_MD_H_ */
1775 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os/posix/os_posix.cpp jdk21u-jdk-21.0.4-ga/src/hotspot/os/posix/os_posix.cpp
1776 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os/posix/os_posix.cpp 2024-07-09 10:07:16.000000000 +0200
1777 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/os/posix/os_posix.cpp 2024-08-17 19:13:01.386527392 +0200
1778 @@ -517,7 +517,7 @@
1779 st->print("%d", sysconf(_SC_CHILD_MAX));
1781 print_rlimit(st, ", THREADS", RLIMIT_THREADS);
1782 -#else
1783 +#elif !defined(SOLARIS)
1784 print_rlimit(st, ", NPROC", RLIMIT_NPROC);
1785 #endif
1787 @@ -535,6 +535,12 @@
1788 print_rlimit(st, ", MEMLOCK", RLIMIT_MEMLOCK, true);
1789 #endif
1791 +#if defined(SOLARIS)
1792 + // maximum size of mapped address space of a process in bytes;
1793 + // if the limit is exceeded, mmap and brk fail
1794 + print_rlimit(st, ", VMEM", RLIMIT_VMEM, true);
1795 +#endif
1797 // MacOS; The maximum size (in bytes) to which a process's resident set size may grow.
1798 #if defined(__APPLE__)
1799 print_rlimit(st, ", RSS", RLIMIT_RSS, true);
1800 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os/posix/os_posix.inline.hpp jdk21u-jdk-21.0.4-ga/src/hotspot/os/posix/os_posix.inline.hpp
1801 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os/posix/os_posix.inline.hpp 2024-07-09 10:07:16.000000000 +0200
1802 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/os/posix/os_posix.inline.hpp 2024-08-17 19:13:01.386924446 +0200
1803 @@ -34,8 +34,10 @@
1804 #include <sys/socket.h>
1805 #include <netdb.h>
1807 +#ifndef SOLARIS
1808 // Aix does not have NUMA support but need these for compilation.
1809 inline bool os::numa_has_group_homing() { AIX_ONLY(ShouldNotReachHere();) return false; }
1810 +#endif // !SOLARIS
1812 // Platform Mutex/Monitor implementation
1814 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os/posix/vmError_posix.cpp jdk21u-jdk-21.0.4-ga/src/hotspot/os/posix/vmError_posix.cpp
1815 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os/posix/vmError_posix.cpp 2024-07-09 10:07:16.000000000 +0200
1816 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/os/posix/vmError_posix.cpp 2024-08-17 19:13:01.387332318 +0200
1817 @@ -40,6 +40,9 @@
1818 #include <sys/syscall.h>
1819 #include <unistd.h>
1820 #endif
1821 +#ifdef SOLARIS
1822 +#include <thread.h>
1823 +#endif
1824 #ifdef AIX
1825 #include <unistd.h>
1826 #endif
1827 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os/solaris/attachListener_solaris.cpp jdk21u-jdk-21.0.4-ga/src/hotspot/os/solaris/attachListener_solaris.cpp
1828 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os/solaris/attachListener_solaris.cpp 1970-01-01 01:00:00.000000000 +0100
1829 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/os/solaris/attachListener_solaris.cpp 2024-08-17 19:13:01.443364152 +0200
1830 @@ -0,0 +1,749 @@
1832 + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
1833 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1835 + * This code is free software; you can redistribute it and/or modify it
1836 + * under the terms of the GNU General Public License version 2 only, as
1837 + * published by the Free Software Foundation.
1839 + * This code is distributed in the hope that it will be useful, but WITHOUT
1840 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1841 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1842 + * version 2 for more details (a copy is included in the LICENSE file that
1843 + * accompanied this code).
1845 + * You should have received a copy of the GNU General Public License version
1846 + * 2 along with this work; if not, write to the Free Software Foundation,
1847 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1849 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1850 + * or visit www.oracle.com if you need additional information or have any
1851 + * questions.
1853 + */
1855 +#include "precompiled.hpp"
1856 +#include "logging/log.hpp"
1857 +#include "runtime/interfaceSupport.inline.hpp"
1858 +#include "runtime/os.inline.hpp"
1859 +#include "services/attachListener.hpp"
1860 +#include "services/dtraceAttacher.hpp"
1861 +#include "utilities/vmError.hpp"
1863 +#include <door.h>
1864 +#include <limits.h>
1865 +#include <string.h>
1866 +#include <signal.h>
1867 +#include <sys/types.h>
1868 +#include <sys/socket.h>
1869 +#include <sys/stat.h>
1871 +// stropts.h uses STR in stream ioctl defines
1872 +#undef STR
1873 +#include <stropts.h>
1874 +#undef STR
1875 +#define STR(a) #a
1877 +// The attach mechanism on Solaris is implemented using the Doors IPC
1878 +// mechanism. The first tool to attempt to attach causes the attach
1879 +// listener thread to startup. This thread creats a door that is
1880 +// associated with a function that enqueues an operation to the attach
1881 +// listener. The door is attached to a file in the file system so that
1882 +// client (tools) can locate it. To enqueue an operation to the VM the
1883 +// client calls through the door which invokes the enqueue function in
1884 +// this process. The credentials of the client are checked and if the
1885 +// effective uid matches this process then the operation is enqueued.
1886 +// When an operation completes the attach listener is required to send the
1887 +// operation result and any result data to the client. In this implementation
1888 +// the result is returned via a UNIX domain socket. A pair of connected
1889 +// sockets (socketpair) is created in the enqueue function and the file
1890 +// descriptor for one of the sockets is returned to the client as the
1891 +// return from the door call. The other end is retained in this process.
1892 +// When the operation completes the result is sent to the client and
1893 +// the socket is closed.
1895 +// forward reference
1896 +class SolarisAttachOperation;
1898 +class SolarisAttachListener: AllStatic {
1899 + private:
1901 + // the path to which we attach the door file descriptor
1902 + static char _door_path[PATH_MAX+1];
1903 + static volatile bool _has_door_path;
1905 + // door descriptor returned by door_create
1906 + static int _door_descriptor;
1908 + static bool _atexit_registered;
1910 + // mutex to protect operation list
1911 + static pthread_mutex_t _mutex;
1913 + // semaphore to wakeup listener thread
1914 + static sema_t _wakeup;
1916 + static pthread_mutex_t* mutex() { return &_mutex; }
1917 + static sema_t* wakeup() { return &_wakeup; }
1919 + // enqueued operation list
1920 + static SolarisAttachOperation* _head;
1921 + static SolarisAttachOperation* _tail;
1923 + static SolarisAttachOperation* head() { return _head; }
1924 + static void set_head(SolarisAttachOperation* head) { _head = head; }
1926 + static SolarisAttachOperation* tail() { return _tail; }
1927 + static void set_tail(SolarisAttachOperation* tail) { _tail = tail; }
1929 + // create the door
1930 + static int create_door();
1932 + public:
1933 + enum {
1934 + ATTACH_PROTOCOL_VER = 1 // protocol version
1935 + };
1936 + enum {
1937 + ATTACH_ERROR_BADREQUEST = 100, // error code returned by
1938 + ATTACH_ERROR_BADVERSION = 101, // the door call
1939 + ATTACH_ERROR_RESOURCE = 102,
1940 + ATTACH_ERROR_INTERNAL = 103,
1941 + ATTACH_ERROR_DENIED = 104
1942 + };
1944 + static void set_door_path(char* path) {
1945 + if (path == NULL) {
1946 + _door_path[0] = '\0';
1947 + _has_door_path = false;
1948 + } else {
1949 + strncpy(_door_path, path, PATH_MAX);
1950 + _door_path[PATH_MAX] = '\0'; // ensure it's nul terminated
1951 + _has_door_path = true;
1955 + static void set_door_descriptor(int dd) { _door_descriptor = dd; }
1957 + // initialize the listener
1958 + static int init();
1960 + static bool has_door_path() { return _has_door_path; }
1961 + static char* door_path() { return _door_path; }
1962 + static int door_descriptor() { return _door_descriptor; }
1964 + // enqueue an operation
1965 + static void enqueue(SolarisAttachOperation* op);
1967 + // dequeue an operation
1968 + static SolarisAttachOperation* dequeue();
1972 +// SolarisAttachOperation is an AttachOperation that additionally encapsulates
1973 +// a socket connection to the requesting client/tool. SolarisAttachOperation
1974 +// can additionally be held in a linked list.
1976 +class SolarisAttachOperation: public AttachOperation {
1977 + private:
1978 + friend class SolarisAttachListener;
1980 + // connection to client
1981 + int _socket;
1983 + // linked list support
1984 + SolarisAttachOperation* _next;
1986 + SolarisAttachOperation* next() { return _next; }
1987 + void set_next(SolarisAttachOperation* next) { _next = next; }
1989 + public:
1990 + void complete(jint res, bufferedStream* st);
1992 + int socket() const { return _socket; }
1993 + void set_socket(int s) { _socket = s; }
1995 + SolarisAttachOperation(char* name) : AttachOperation(name) {
1996 + set_socket(-1);
1997 + set_next(NULL);
2001 +// statics
2002 +char SolarisAttachListener::_door_path[PATH_MAX+1];
2003 +volatile bool SolarisAttachListener::_has_door_path;
2004 +int SolarisAttachListener::_door_descriptor = -1;
2005 +bool SolarisAttachListener::_atexit_registered = false;
2006 +pthread_mutex_t SolarisAttachListener::_mutex;
2007 +sema_t SolarisAttachListener::_wakeup;
2008 +SolarisAttachOperation* SolarisAttachListener::_head = NULL;
2009 +SolarisAttachOperation* SolarisAttachListener::_tail = NULL;
2011 +// Supporting class to help split a buffer into individual components
2012 +class ArgumentIterator : public StackObj {
2013 + private:
2014 + char* _pos;
2015 + char* _end;
2016 + public:
2017 + ArgumentIterator(char* arg_buffer, size_t arg_size) {
2018 + _pos = arg_buffer;
2019 + _end = _pos + arg_size - 1;
2021 + char* next() {
2022 + if (*_pos == '\0') {
2023 + // advance the iterator if possible (null arguments)
2024 + if (_pos < _end) {
2025 + _pos += 1;
2027 + return NULL;
2029 + char* res = _pos;
2030 + char* next_pos = strchr(_pos, '\0');
2031 + if (next_pos < _end) {
2032 + next_pos++;
2034 + _pos = next_pos;
2035 + return res;
2039 +// Calls from the door function to check that the client credentials
2040 +// match this process. Returns 0 if credentials okay, otherwise -1.
2041 +static int check_credentials() {
2042 + ucred_t *cred_info = NULL;
2043 + int ret = -1; // deny by default
2045 + // get client credentials
2046 + if (door_ucred(&cred_info) == -1) {
2047 + return -1; // unable to get them, deny
2050 + // get euid/egid from ucred_free
2051 + uid_t ucred_euid = ucred_geteuid(cred_info);
2052 + gid_t ucred_egid = ucred_getegid(cred_info);
2054 + // check that the effective uid/gid matches
2055 + if (os::Posix::matches_effective_uid_and_gid_or_root(ucred_euid, ucred_egid)) {
2056 + ret = 0; // allow
2059 + ucred_free(cred_info);
2060 + return ret;
2064 +// Parses the argument buffer to create an AttachOperation that we should
2065 +// enqueue to the attach listener.
2066 +// The buffer is expected to be formatted as follows:
2067 +// <ver>0<cmd>0<arg>0<arg>0<arg>0
2068 +// where <ver> is the version number (must be "1"), <cmd> is the command
2069 +// name ("load, "datadump", ...) and <arg> is an argument.
2071 +static SolarisAttachOperation* create_operation(char* argp, size_t arg_size, int* err) {
2072 + // assume bad request until parsed
2073 + *err = SolarisAttachListener::ATTACH_ERROR_BADREQUEST;
2075 + if (arg_size < 2 || argp[arg_size-1] != '\0') {
2076 + return NULL; // no ver or not null terminated
2079 + // Use supporting class to iterate over the buffer
2080 + ArgumentIterator args(argp, arg_size);
2082 + // First check the protocol version
2083 + char* ver = args.next();
2084 + if (ver == NULL) {
2085 + return NULL;
2087 + if (atoi(ver) != SolarisAttachListener::ATTACH_PROTOCOL_VER) {
2088 + *err = SolarisAttachListener::ATTACH_ERROR_BADVERSION;
2089 + return NULL;
2092 + // Get command name and create the operation
2093 + char* name = args.next();
2094 + if (name == NULL || strlen(name) > AttachOperation::name_length_max) {
2095 + return NULL;
2097 + SolarisAttachOperation* op = new SolarisAttachOperation(name);
2099 + // Iterate over the arguments
2100 + for (int i=0; i<AttachOperation::arg_count_max; i++) {
2101 + char* arg = args.next();
2102 + if (arg == NULL) {
2103 + op->set_arg(i, NULL);
2104 + } else {
2105 + if (strlen(arg) > AttachOperation::arg_length_max) {
2106 + delete op;
2107 + return NULL;
2109 + op->set_arg(i, arg);
2113 + // return operation
2114 + *err = 0;
2115 + return op;
2118 +// This is door function which the client executes via a door_call.
2119 +extern "C" {
2120 + static void enqueue_proc(void* cookie, char* argp, size_t arg_size,
2121 + door_desc_t* dt, uint_t n_desc)
2123 + int return_fd = -1;
2124 + SolarisAttachOperation* op = NULL;
2126 + // wait up to 10 seconds for listener to be up and running
2127 + jint res = 0;
2128 + int sleep_count = 0;
2129 + while (!AttachListener::is_initialized()) {
2130 + sleep(1); // 1 second
2131 + sleep_count++;
2132 + if (sleep_count > 10) { // try for 10 seconds
2133 + debug_only(warning("door_call when not enabled"));
2134 + res = (jint)SolarisAttachListener::ATTACH_ERROR_INTERNAL;
2135 + break;
2139 + // check client credentials
2140 + if (res == 0) {
2141 + if (check_credentials() != 0) {
2142 + res = (jint)SolarisAttachListener::ATTACH_ERROR_DENIED;
2146 + // if we are stopped at ShowMessageBoxOnError then maybe we can
2147 + // load a diagnostic library
2148 + if (res == 0 && VMError::is_error_reported()) {
2149 + if (ShowMessageBoxOnError) {
2150 + // TBD - support loading of diagnostic library here
2153 + // can't enqueue operation after fatal error
2154 + res = (jint)SolarisAttachListener::ATTACH_ERROR_RESOURCE;
2157 + // create the operation
2158 + if (res == 0) {
2159 + int err;
2160 + op = create_operation(argp, arg_size, &err);
2161 + res = (op == NULL) ? (jint)err : 0;
2164 + // create a pair of connected sockets. Store the file descriptor
2165 + // for one end in the operation and enqueue the operation. The
2166 + // file descriptor for the other end wil be returned to the client.
2167 + if (res == 0) {
2168 + int s[2];
2169 + if (socketpair(PF_UNIX, SOCK_STREAM, 0, s) < 0) {
2170 + delete op;
2171 + res = (jint)SolarisAttachListener::ATTACH_ERROR_RESOURCE;
2172 + } else {
2173 + op->set_socket(s[0]);
2174 + return_fd = s[1];
2175 + SolarisAttachListener::enqueue(op);
2179 + // Return 0 (success) + file descriptor, or non-0 (error)
2180 + if (res == 0) {
2181 + door_desc_t desc;
2182 + // DOOR_RELEASE flag makes sure fd is closed after passing it to
2183 + // the client. See door_return(3DOOR) man page.
2184 + desc.d_attributes = DOOR_DESCRIPTOR | DOOR_RELEASE;
2185 + desc.d_data.d_desc.d_descriptor = return_fd;
2186 + door_return((char*)&res, sizeof(res), &desc, 1);
2187 + } else {
2188 + door_return((char*)&res, sizeof(res), NULL, 0);
2193 +// atexit hook to detach the door and remove the file
2194 +extern "C" {
2195 + static void listener_cleanup() {
2196 + int dd = SolarisAttachListener::door_descriptor();
2197 + if (dd >= 0) {
2198 + SolarisAttachListener::set_door_descriptor(-1);
2199 + ::close(dd);
2201 + if (SolarisAttachListener::has_door_path()) {
2202 + char* path = SolarisAttachListener::door_path();
2203 + ::fdetach(path);
2204 + ::unlink(path);
2205 + SolarisAttachListener::set_door_path(NULL);
2210 +// Create the door
2211 +int SolarisAttachListener::create_door() {
2212 + char door_path[PATH_MAX+1];
2213 + char initial_path[PATH_MAX+1];
2214 + int fd, res;
2216 + // register exit function
2217 + if (!_atexit_registered) {
2218 + _atexit_registered = true;
2219 + ::atexit(listener_cleanup);
2222 + // create the door descriptor
2223 + int dd = ::door_create(enqueue_proc, NULL, 0);
2224 + if (dd < 0) {
2225 + return -1;
2228 + // create initial file to attach door descriptor
2229 + snprintf(door_path, sizeof(door_path), "%s/.java_pid%d",
2230 + os::get_temp_directory(), os::current_process_id());
2231 + snprintf(initial_path, sizeof(initial_path), "%s.tmp", door_path);
2232 + RESTARTABLE(::creat(initial_path, S_IRUSR | S_IWUSR), fd);
2233 + if (fd == -1) {
2234 + log_debug(attach)("attempt to create door file %s failed (%d)", initial_path, errno);
2235 + ::door_revoke(dd);
2236 + return -1;
2238 + assert(fd >= 0, "bad file descriptor");
2239 + ::close(fd);
2241 + // attach the door descriptor to the file
2242 + if ((res = ::fattach(dd, initial_path)) == -1) {
2243 + // if busy then detach and try again
2244 + if (errno == EBUSY) {
2245 + ::fdetach(initial_path);
2246 + res = ::fattach(dd, initial_path);
2248 + if (res == -1) {
2249 + log_debug(attach)("unable to create door - fattach failed (%d)", errno);
2250 + ::door_revoke(dd);
2251 + dd = -1;
2255 + // rename file so that clients can attach
2256 + if (dd >= 0) {
2257 + if (::rename(initial_path, door_path) == -1) {
2258 + ::close(dd);
2259 + ::fdetach(initial_path);
2260 + log_debug(attach)("unable to create door - rename %s to %s failed (%d)", initial_path, door_path, errno);
2261 + dd = -1;
2264 + if (dd >= 0) {
2265 + set_door_descriptor(dd);
2266 + set_door_path(door_path);
2267 + log_trace(attach)("door file %s created succesfully", door_path);
2268 + } else {
2269 + // unable to create door, attach it to file, or rename file into place
2270 + ::unlink(initial_path);
2271 + return -1;
2274 + return 0;
2277 +// Initialization - create the door, locks, and other initialization
2278 +int SolarisAttachListener::init() {
2279 + if (create_door()) {
2280 + return -1;
2283 + int status = pthread_mutex_init(&_mutex, NULL);
2284 + assert_status(status==0, status, "mutex_init");
2286 + status = ::sema_init(&_wakeup, 0, NULL, NULL);
2287 + assert_status(status==0, status, "sema_init");
2289 + set_head(NULL);
2290 + set_tail(NULL);
2292 + return 0;
2295 +// Dequeue an operation
2296 +SolarisAttachOperation* SolarisAttachListener::dequeue() {
2297 + for (;;) {
2298 + int res;
2300 + // wait for somebody to enqueue something
2301 + while ((res = ::sema_wait(wakeup())) == EINTR)
2303 + if (res) {
2304 + warning("sema_wait failed: %s", os::strerror(res));
2305 + return NULL;
2308 + // lock the list
2309 + res = pthread_mutex_lock(mutex());
2310 + assert(res == 0, "mutex_lock failed");
2312 + // remove the head of the list
2313 + SolarisAttachOperation* op = head();
2314 + if (op != NULL) {
2315 + set_head(op->next());
2316 + if (head() == NULL) {
2317 + set_tail(NULL);
2321 + // unlock
2322 + pthread_mutex_unlock(mutex());
2324 + // if we got an operation when return it.
2325 + if (op != NULL) {
2326 + return op;
2331 +// Enqueue an operation
2332 +void SolarisAttachListener::enqueue(SolarisAttachOperation* op) {
2333 + // lock list
2334 + int res = pthread_mutex_lock(mutex());
2335 + assert(res == 0, "mutex_lock failed");
2337 + // enqueue at tail
2338 + op->set_next(NULL);
2339 + if (head() == NULL) {
2340 + set_head(op);
2341 + } else {
2342 + tail()->set_next(op);
2344 + set_tail(op);
2346 + // wakeup the attach listener
2347 + RESTARTABLE(::sema_post(wakeup()), res);
2348 + assert(res == 0, "sema_post failed");
2350 + // unlock
2351 + pthread_mutex_unlock(mutex());
2355 +// support function - writes the (entire) buffer to a socket
2356 +static int write_fully(int s, char* buf, int len) {
2357 + do {
2358 + int n = ::write(s, buf, len);
2359 + if (n == -1) {
2360 + if (errno != EINTR) return -1;
2361 + } else {
2362 + buf += n;
2363 + len -= n;
2366 + while (len > 0);
2367 + return 0;
2370 +// Complete an operation by sending the operation result and any result
2371 +// output to the client. At this time the socket is in blocking mode so
2372 +// potentially we can block if there is a lot of data and the client is
2373 +// non-responsive. For most operations this is a non-issue because the
2374 +// default send buffer is sufficient to buffer everything. In the future
2375 +// if there are operations that involves a very big reply then it the
2376 +// socket could be made non-blocking and a timeout could be used.
2378 +void SolarisAttachOperation::complete(jint res, bufferedStream* st) {
2379 + if (this->socket() >= 0) {
2380 + JavaThread* thread = JavaThread::current();
2381 + ThreadBlockInVM tbivm(thread);
2383 + // write operation result
2384 + char msg[32];
2385 + sprintf(msg, "%d\n", res);
2386 + int rc = write_fully(this->socket(), msg, strlen(msg));
2388 + // write any result data
2389 + if (rc == 0) {
2390 + write_fully(this->socket(), (char*) st->base(), st->size());
2391 + ::shutdown(this->socket(), 2);
2394 + // close socket and we're done
2395 + ::close(this->socket());
2397 + delete this;
2401 +// AttachListener functions
2403 +AttachOperation* AttachListener::dequeue() {
2404 + JavaThread* thread = JavaThread::current();
2405 + ThreadBlockInVM tbivm(thread);
2407 + AttachOperation* op = SolarisAttachListener::dequeue();
2409 + return op;
2413 +// Performs initialization at vm startup
2414 +// For Solaris we remove any stale .java_pid file which could cause
2415 +// an attaching process to think we are ready to receive a door_call
2416 +// before we are properly initialized
2418 +void AttachListener::vm_start() {
2419 + char fn[PATH_MAX+1];
2420 + struct stat64 st;
2421 + int ret;
2423 + int n = snprintf(fn, sizeof(fn), "%s/.java_pid%d",
2424 + os::get_temp_directory(), os::current_process_id());
2425 + assert(n < sizeof(fn), "java_pid file name buffer overflow");
2427 + RESTARTABLE(::stat64(fn, &st), ret);
2428 + if (ret == 0) {
2429 + ret = ::unlink(fn);
2430 + if (ret == -1) {
2431 + log_debug(attach)("Failed to remove stale attach pid file at %s", fn);
2436 +int AttachListener::pd_init() {
2437 + JavaThread* thread = JavaThread::current();
2438 + ThreadBlockInVM tbivm(thread);
2440 + int ret_code = SolarisAttachListener::init();
2442 + return ret_code;
2445 +// Attach Listener is started lazily except in the case when
2446 +// +ReduseSignalUsage is used
2447 +bool AttachListener::init_at_startup() {
2448 + if (ReduceSignalUsage) {
2449 + return true;
2450 + } else {
2451 + return false;
2455 +bool AttachListener::check_socket_file() {
2456 + int ret;
2457 + struct stat64 st;
2458 + ret = stat64(SolarisAttachListener::door_path(), &st);
2459 + if (ret == -1) { // need to restart attach listener.
2460 + log_debug(attach)("Door file %s does not exist - Restart Attach Listener",
2461 + SolarisAttachListener::door_path());
2463 + listener_cleanup();
2465 + // wait to terminate current attach listener instance...
2466 + while (AttachListener::transit_state(AL_INITIALIZING,
2467 + AL_NOT_INITIALIZED) != AL_NOT_INITIALIZED) {
2468 + os::naked_yield();
2470 + return is_init_trigger();
2472 + return false;
2475 +// If the file .attach_pid<pid> exists in the working directory
2476 +// or /tmp then this is the trigger to start the attach mechanism
2477 +bool AttachListener::is_init_trigger() {
2478 + if (init_at_startup() || is_initialized()) {
2479 + return false; // initialized at startup or already initialized
2481 + char fn[PATH_MAX + 1];
2482 + int ret;
2483 + struct stat64 st;
2484 + sprintf(fn, ".attach_pid%d", os::current_process_id());
2485 + RESTARTABLE(::stat64(fn, &st), ret);
2486 + if (ret == -1) {
2487 + log_trace(attach)("Failed to find attach file: %s, trying alternate", fn);
2488 + snprintf(fn, sizeof(fn), "%s/.attach_pid%d",
2489 + os::get_temp_directory(), os::current_process_id());
2490 + RESTARTABLE(::stat64(fn, &st), ret);
2491 + if (ret == -1) {
2492 + log_debug(attach)("Failed to find attach file: %s", fn);
2495 + if (ret == 0) {
2496 + // simple check to avoid starting the attach mechanism when
2497 + // a bogus non-root user creates the file
2498 + if (os::Posix::matches_effective_uid_or_root(st.st_uid)) {
2499 + init();
2500 + log_trace(attach)("Attach triggered by %s", fn);
2501 + return true;
2502 + } else {
2503 + log_debug(attach)("File %s has wrong user id %d (vs %d). Attach is not triggered", fn, st.st_uid, geteuid());
2506 + return false;
2509 +// if VM aborts then detach/cleanup
2510 +void AttachListener::abort() {
2511 + listener_cleanup();
2514 +void AttachListener::pd_data_dump() {
2515 + os::signal_notify(SIGQUIT);
2518 +static jint enable_dprobes(AttachOperation* op, outputStream* out) {
2519 + const char* probe = op->arg(0);
2520 + if (probe == NULL || probe[0] == '\0') {
2521 + out->print_cr("No probe specified");
2522 + return JNI_ERR;
2523 + } else {
2524 + char *end;
2525 + long val = strtol(probe, &end, 10);
2526 + if (end == probe || val < 0 || val > INT_MAX) {
2527 + out->print_cr("invalid probe type");
2528 + return JNI_ERR;
2529 + } else {
2530 + int probe_typess = (int) val;
2531 + DTrace::enable_dprobes(probe_typess);
2532 + return JNI_OK;
2537 +// platform specific operations table
2538 +static AttachOperationFunctionInfo funcs[] = {
2539 + { "enabledprobes", enable_dprobes },
2540 + { NULL, NULL }
2543 +AttachOperationFunctionInfo* AttachListener::pd_find_operation(const char* name) {
2544 + int i;
2545 + for (i = 0; funcs[i].name != NULL; i++) {
2546 + if (strcmp(funcs[i].name, name) == 0) {
2547 + return &funcs[i];
2550 + return NULL;
2553 +// Solaris specific global flag set.
2554 +jint AttachListener::pd_set_flag(AttachOperation* op, outputStream* out) {
2555 + const char* name = op->arg(0);
2556 + assert(name != NULL, "flag name should not be null");
2557 + bool flag = true;
2558 + const char* arg1;
2559 + if ((arg1 = op->arg(1)) != NULL) {
2560 + char *end;
2561 + flag = (strtol(arg1, &end, 10) != 0);
2562 + if (arg1 == end) {
2563 + out->print_cr("flag value has to be an integer");
2564 + return JNI_ERR;
2568 + if (strcmp(name, "DTraceMonitorProbes") == 0) {
2569 + DTrace::set_monitor_dprobes(flag);
2570 + return JNI_OK;
2573 + out->print_cr("flag '%s' cannot be changed", name);
2574 + return JNI_ERR;
2577 +void AttachListener::pd_detachall() {
2578 + DTrace::detach_all_clients();
2580 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os/solaris/c1_globals_solaris.hpp jdk21u-jdk-21.0.4-ga/src/hotspot/os/solaris/c1_globals_solaris.hpp
2581 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os/solaris/c1_globals_solaris.hpp 1970-01-01 01:00:00.000000000 +0100
2582 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/os/solaris/c1_globals_solaris.hpp 2024-08-17 19:13:01.443664996 +0200
2583 @@ -0,0 +1,36 @@
2585 + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
2586 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
2588 + * This code is free software; you can redistribute it and/or modify it
2589 + * under the terms of the GNU General Public License version 2 only, as
2590 + * published by the Free Software Foundation.
2592 + * This code is distributed in the hope that it will be useful, but WITHOUT
2593 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
2594 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
2595 + * version 2 for more details (a copy is included in the LICENSE file that
2596 + * accompanied this code).
2598 + * You should have received a copy of the GNU General Public License version
2599 + * 2 along with this work; if not, write to the Free Software Foundation,
2600 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2602 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2603 + * or visit www.oracle.com if you need additional information or have any
2604 + * questions.
2606 + */
2608 +#ifndef OS_SOLARIS_C1_GLOBALS_SOLARIS_HPP
2609 +#define OS_SOLARIS_C1_GLOBALS_SOLARIS_HPP
2611 +#include "utilities/globalDefinitions.hpp"
2612 +#include "utilities/macros.hpp"
2615 +// Sets the default values for operating system dependent flags used by the
2616 +// client compiler. (see c1_globals.hpp)
2619 +#endif // OS_SOLARIS_C1_GLOBALS_SOLARIS_HPP
2620 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os/solaris/c2_globals_solaris.hpp jdk21u-jdk-21.0.4-ga/src/hotspot/os/solaris/c2_globals_solaris.hpp
2621 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os/solaris/c2_globals_solaris.hpp 1970-01-01 01:00:00.000000000 +0100
2622 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/os/solaris/c2_globals_solaris.hpp 2024-08-17 19:13:01.443950919 +0200
2623 @@ -0,0 +1,36 @@
2625 + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
2626 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
2628 + * This code is free software; you can redistribute it and/or modify it
2629 + * under the terms of the GNU General Public License version 2 only, as
2630 + * published by the Free Software Foundation.
2632 + * This code is distributed in the hope that it will be useful, but WITHOUT
2633 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
2634 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
2635 + * version 2 for more details (a copy is included in the LICENSE file that
2636 + * accompanied this code).
2638 + * You should have received a copy of the GNU General Public License version
2639 + * 2 along with this work; if not, write to the Free Software Foundation,
2640 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2642 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2643 + * or visit www.oracle.com if you need additional information or have any
2644 + * questions.
2646 + */
2648 +#ifndef OS_SOLARIS_C2_GLOBALS_SOLARIS_HPP
2649 +#define OS_SOLARIS_C2_GLOBALS_SOLARIS_HPP
2651 +#include "utilities/globalDefinitions.hpp"
2652 +#include "utilities/macros.hpp"
2655 +// Sets the default values for operating system dependent flags used by the
2656 +// server compiler. (see c2_globals.hpp)
2659 +#endif // OS_SOLARIS_C2_GLOBALS_SOLARIS_HPP
2660 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os/solaris/decoder_solaris.cpp jdk21u-jdk-21.0.4-ga/src/hotspot/os/solaris/decoder_solaris.cpp
2661 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os/solaris/decoder_solaris.cpp 1970-01-01 01:00:00.000000000 +0100
2662 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/os/solaris/decoder_solaris.cpp 2024-08-17 19:13:01.444243782 +0200
2663 @@ -0,0 +1,32 @@
2665 + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
2666 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
2668 + * This code is free software; you can redistribute it and/or modify it
2669 + * under the terms of the GNU General Public License version 2 only, as
2670 + * published by the Free Software Foundation.
2672 + * This code is distributed in the hope that it will be useful, but WITHOUT
2673 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
2674 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
2675 + * version 2 for more details (a copy is included in the LICENSE file that
2676 + * accompanied this code).
2678 + * You should have received a copy of the GNU General Public License version
2679 + * 2 along with this work; if not, write to the Free Software Foundation,
2680 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2682 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2683 + * or visit www.oracle.com if you need additional information or have any
2684 + * questions.
2686 + */
2688 +#include "utilities/decoder_elf.hpp"
2690 +#include <demangle.h>
2692 +bool ElfDecoder::demangle(const char* symbol, char *buf, int buflen) {
2693 + return !cplus_demangle(symbol, buf, (size_t)buflen);
2696 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os/solaris/dtrace/jhelper.d jdk21u-jdk-21.0.4-ga/src/hotspot/os/solaris/dtrace/jhelper.d
2697 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os/solaris/dtrace/jhelper.d 1970-01-01 01:00:00.000000000 +0100
2698 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/os/solaris/dtrace/jhelper.d 2024-08-17 19:13:01.445278194 +0200
2699 @@ -0,0 +1,540 @@
2701 + * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
2702 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
2704 + * This code is free software; you can redistribute it and/or modify it
2705 + * under the terms of the GNU General Public License version 2 only, as
2706 + * published by the Free Software Foundation.
2708 + * This code is distributed in the hope that it will be useful, but WITHOUT
2709 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
2710 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
2711 + * version 2 for more details (a copy is included in the LICENSE file that
2712 + * accompanied this code).
2714 + * You should have received a copy of the GNU General Public License version
2715 + * 2 along with this work; if not, write to the Free Software Foundation,
2716 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2718 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2719 + * or visit www.oracle.com if you need additional information or have any
2720 + * questions.
2722 + */
2724 +/* This file is auto-generated */
2725 +#include "JvmOffsetsIndex.h"
2727 +#define DEBUG
2729 +#ifdef DEBUG
2730 +#define MARK_LINE this->line = __LINE__
2731 +#else
2732 +#define MARK_LINE
2733 +#endif
2735 +#ifdef _LP64
2736 +#define STACK_BIAS 0x7ff
2737 +#define pointer uint64_t
2738 +#else
2739 +#define STACK_BIAS 0
2740 +#define pointer uint32_t
2741 +#endif
2743 +extern pointer __JvmOffsets;
2745 +/* GrowableArray<CodeHeaps*>* */
2746 +extern pointer __1cJCodeCacheG_heaps_;
2748 +extern pointer __1cIUniverseO_collectedHeap_;
2750 +extern pointer __1cHnmethodG__vtbl_;
2751 +extern pointer __1cGMethodG__vtbl_;
2752 +extern pointer __1cKBufferBlobG__vtbl_;
2754 +#define copyin_ptr(ADDR) *(pointer*) copyin((pointer) (ADDR), sizeof(pointer))
2755 +#define copyin_uchar(ADDR) *(uchar_t*) copyin((pointer) (ADDR), sizeof(uchar_t))
2756 +#define copyin_uint16(ADDR) *(uint16_t*) copyin((pointer) (ADDR), sizeof(uint16_t))
2757 +#define copyin_uint32(ADDR) *(uint32_t*) copyin((pointer) (ADDR), sizeof(uint32_t))
2758 +#define copyin_int32(ADDR) *(int32_t*) copyin((pointer) (ADDR), sizeof(int32_t))
2759 +#define copyin_uint8(ADDR) *(uint8_t*) copyin((pointer) (ADDR), sizeof(uint8_t))
2761 +#define copyin_offset(JVM_CONST) JVM_CONST = \
2762 + copyin_int32(JvmOffsetsPtr + IDX_##JVM_CONST * sizeof(int32_t))
2764 +int init_done;
2766 +dtrace:helper:ustack:
2768 + MARK_LINE;
2769 + this->done = 0;
2770 + /*
2771 + * TBD:
2772 + * Here we initialize init_done, otherwise jhelper does not work.
2773 + * Therefore, copyin_offset() statements work multiple times now.
2774 + * There is a hope we could avoid it in the future, and so,
2775 + * this initialization can be removed.
2776 + */
2777 + init_done = 0;
2778 + this->error = (char *) NULL;
2779 + this->result = (char *) NULL;
2780 + this->isMethod = 0;
2781 + this->codecache = 0;
2782 + this->klass = (pointer) NULL;
2783 + this->vtbl = (pointer) NULL;
2784 + this->suffix = '\0';
2787 +dtrace:helper:ustack:
2789 + MARK_LINE;
2790 + /* Initialization of JvmOffsets constants */
2791 + JvmOffsetsPtr = (pointer) &``__JvmOffsets;
2794 +dtrace:helper:ustack:
2795 +/!init_done && !this->done/
2797 + MARK_LINE;
2799 + copyin_offset(POINTER_SIZE);
2800 + copyin_offset(COMPILER);
2801 + copyin_offset(OFFSET_CollectedHeap_reserved);
2802 + copyin_offset(OFFSET_MemRegion_start);
2803 + copyin_offset(OFFSET_MemRegion_word_size);
2804 + copyin_offset(SIZE_HeapWord);
2806 + copyin_offset(OFFSET_interpreter_frame_method);
2807 + copyin_offset(OFFSET_Klass_name);
2808 + copyin_offset(OFFSET_ConstantPool_pool_holder);
2810 + copyin_offset(OFFSET_HeapBlockHeader_used);
2811 + copyin_offset(OFFSET_oopDesc_metadata);
2813 + copyin_offset(OFFSET_Symbol_length);
2814 + copyin_offset(OFFSET_Symbol_body);
2816 + copyin_offset(OFFSET_Method_constMethod);
2817 + copyin_offset(OFFSET_ConstMethod_constants);
2818 + copyin_offset(OFFSET_ConstMethod_name_index);
2819 + copyin_offset(OFFSET_ConstMethod_signature_index);
2821 + copyin_offset(OFFSET_CodeHeap_memory);
2822 + copyin_offset(OFFSET_CodeHeap_segmap);
2823 + copyin_offset(OFFSET_CodeHeap_log2_segment_size);
2825 + copyin_offset(OFFSET_GrowableArray_CodeHeap_data);
2826 + copyin_offset(OFFSET_GrowableArray_CodeHeap_len);
2828 + copyin_offset(OFFSET_VirtualSpace_low);
2829 + copyin_offset(OFFSET_VirtualSpace_high);
2831 + copyin_offset(OFFSET_CodeBlob_name);
2833 + copyin_offset(OFFSET_nmethod_method);
2834 + copyin_offset(SIZE_HeapBlockHeader);
2835 + copyin_offset(SIZE_oopDesc);
2836 + copyin_offset(SIZE_ConstantPool);
2838 + copyin_offset(OFFSET_NarrowPtrStruct_base);
2839 + copyin_offset(OFFSET_NarrowPtrStruct_shift);
2841 + /*
2842 + * The PC to translate is in arg0.
2843 + */
2844 + this->pc = arg0;
2846 +#if defined(__i386) || defined(__amd64)
2847 + this->methodPtr = copyin_ptr(arg1 + OFFSET_interpreter_frame_method);
2848 +#else
2849 +#error "Don't know architecture"
2850 +#endif
2852 + /* Read address of GrowableArray<CodeHeaps*> */
2853 + // this->code_heaps_address = copyin_ptr(&``__1cJCodeCacheG_heaps_);
2854 + this->code_heaps_address = * ( uint64_t * ) copyin ( ( uint64_t ) ( &``__1cJCodeCacheG_heaps_ ) , sizeof ( uint64_t ) );
2856 + /* Read address of _data array field in GrowableArray */
2857 + this->code_heaps_array_address = copyin_ptr(this->code_heaps_address + OFFSET_GrowableArray_CodeHeap_data);
2858 + this->number_of_heaps = copyin_uint32(this->code_heaps_address + OFFSET_GrowableArray_CodeHeap_len);
2860 + this->Method_vtbl = (pointer) &``__1cGMethodG__vtbl_;
2862 + /*
2863 + * Get Java heap bounds
2864 + */
2865 + // this->Universe_collectedHeap = copyin_ptr(&``__1cIUniverseO_collectedHeap_);
2866 + this->Universe_collectedHeap = * ( uint64_t * ) copyin ( ( uint64_t ) ( &``__1cIUniverseO_collectedHeap_ ) , sizeof ( uint64_t ) );
2868 + this->heap_start = copyin_ptr(this->Universe_collectedHeap +
2869 + OFFSET_CollectedHeap_reserved +
2870 + OFFSET_MemRegion_start);
2871 + this->heap_size = SIZE_HeapWord *
2872 + copyin_ptr(this->Universe_collectedHeap +
2873 + OFFSET_CollectedHeap_reserved +
2874 + OFFSET_MemRegion_word_size
2875 + );
2876 + this->heap_end = this->heap_start + this->heap_size;
2880 + * IMPORTANT: At the moment the ustack helper supports up to 5 code heaps in
2881 + * the code cache. If more code heaps are added the following probes have to
2882 + * be extended. This is done by simply adding a probe to get the heap bounds
2883 + * and another probe to set the code heap address of the newly created heap.
2884 + */
2887 + * ----- BEGIN: Get bounds of code heaps -----
2888 + */
2889 +dtrace:helper:ustack:
2890 +/init_done < 1 && this->number_of_heaps >= 1 && !this->done/
2892 + MARK_LINE;
2893 + /* CodeHeap 1 */
2894 + init_done = 1;
2895 + this->code_heap1_address = copyin_ptr(this->code_heaps_array_address);
2896 + this->code_heap1_low = copyin_ptr(this->code_heap1_address +
2897 + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low);
2898 + this->code_heap1_high = copyin_ptr(this->code_heap1_address +
2899 + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_high);
2902 +dtrace:helper:ustack:
2903 +/init_done < 2 && this->number_of_heaps >= 2 && !this->done/
2905 + MARK_LINE;
2906 + /* CodeHeap 2 */
2907 + init_done = 2;
2908 + this->code_heaps_array_address = this->code_heaps_array_address + POINTER_SIZE;
2909 + this->code_heap2_address = copyin_ptr(this->code_heaps_array_address);
2910 + this->code_heap2_low = copyin_ptr(this->code_heap2_address +
2911 + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low);
2912 + this->code_heap2_high = copyin_ptr(this->code_heap2_address +
2913 + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_high);
2916 +dtrace:helper:ustack:
2917 +/init_done < 3 && this->number_of_heaps >= 3 && !this->done/
2919 + /* CodeHeap 3 */
2920 + init_done = 3;
2921 + this->code_heaps_array_address = this->code_heaps_array_address + POINTER_SIZE;
2922 + this->code_heap3_address = copyin_ptr(this->code_heaps_array_address);
2923 + this->code_heap3_low = copyin_ptr(this->code_heap3_address +
2924 + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low);
2925 + this->code_heap3_high = copyin_ptr(this->code_heap3_address +
2926 + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_high);
2929 +dtrace:helper:ustack:
2930 +/init_done < 4 && this->number_of_heaps >= 4 && !this->done/
2932 + /* CodeHeap 4 */
2933 + init_done = 4;
2934 + this->code_heaps_array_address = this->code_heaps_array_address + POINTER_SIZE;
2935 + this->code_heap4_address = copyin_ptr(this->code_heaps_array_address);
2936 + this->code_heap4_low = copyin_ptr(this->code_heap4_address +
2937 + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low);
2938 + this->code_heap4_high = copyin_ptr(this->code_heap4_address +
2939 + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_high);
2942 +dtrace:helper:ustack:
2943 +/init_done < 5 && this->number_of_heaps >= 5 && !this->done/
2945 + /* CodeHeap 5 */
2946 + init_done = 5;
2947 + this->code_heaps_array_address = this->code_heaps_array_address + POINTER_SIZE;
2948 + this->code_heap5_address = copyin_ptr(this->code_heaps_array_address);
2949 + this->code_heap5_low = copyin_ptr(this->code_heap5_address +
2950 + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low);
2951 + this->code_heap5_high = copyin_ptr(this->code_heap5_address +
2952 + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_high);
2955 + * ----- END: Get bounds of code heaps -----
2956 + */
2959 + * ----- BEGIN: Get address of the code heap pc points to -----
2960 + */
2961 +dtrace:helper:ustack:
2962 +/!this->done && this->number_of_heaps >= 1 && this->code_heap1_low <= this->pc && this->pc < this->code_heap1_high/
2964 + MARK_LINE;
2965 + this->codecache = 1;
2966 + this->code_heap_address = this->code_heap1_address;
2969 +dtrace:helper:ustack:
2970 +/!this->done && this->number_of_heaps >= 2 && this->code_heap2_low <= this->pc && this->pc < this->code_heap2_high/
2972 + MARK_LINE;
2973 + this->codecache = 1;
2974 + this->code_heap_address = this->code_heap2_address;
2977 +dtrace:helper:ustack:
2978 +/!this->done && this->number_of_heaps >= 3 && this->code_heap3_low <= this->pc && this->pc < this->code_heap3_high/
2980 + MARK_LINE;
2981 + this->codecache = 1;
2982 + this->code_heap_address = this->code_heap3_address;
2985 +dtrace:helper:ustack:
2986 +/!this->done && this->number_of_heaps >= 4 && this->code_heap4_low <= this->pc && this->pc < this->code_heap4_high/
2988 + MARK_LINE;
2989 + this->codecache = 1;
2990 + this->code_heap_address = this->code_heap4_address;
2993 +dtrace:helper:ustack:
2994 +/!this->done && this->number_of_heaps >= 5 && this->code_heap5_low <= this->pc && this->pc < this->code_heap5_high/
2996 + MARK_LINE;
2997 + this->codecache = 1;
2998 + this->code_heap_address = this->code_heap5_address;
3001 + * ----- END: Get address of the code heap pc points to -----
3002 + */
3004 +dtrace:helper:ustack:
3005 +/!this->done && this->codecache/
3007 + MARK_LINE;
3008 + /*
3009 + * Get code heap configuration
3010 + */
3011 + this->code_heap_low = copyin_ptr(this->code_heap_address +
3012 + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low);
3013 + this->code_heap_segmap_low = copyin_ptr(this->code_heap_address +
3014 + OFFSET_CodeHeap_segmap + OFFSET_VirtualSpace_low);
3015 + this->code_heap_log2_segment_size = copyin_uint32(
3016 + this->code_heap_address + OFFSET_CodeHeap_log2_segment_size);
3018 + /*
3019 + * Find start
3020 + */
3021 + this->segment = (this->pc - this->code_heap_low) >>
3022 + this->code_heap_log2_segment_size;
3023 + this->block = this->code_heap_segmap_low;
3024 + this->tag = copyin_uchar(this->block + this->segment);
3027 +dtrace:helper:ustack:
3028 +/!this->done && this->codecache && this->tag > 0/
3030 + MARK_LINE;
3031 + this->tag = copyin_uchar(this->block + this->segment);
3032 + this->segment = this->segment - this->tag;
3035 +dtrace:helper:ustack:
3036 +/!this->done && this->codecache && this->tag > 0/
3038 + MARK_LINE;
3039 + this->tag = copyin_uchar(this->block + this->segment);
3040 + this->segment = this->segment - this->tag;
3043 +dtrace:helper:ustack:
3044 +/!this->done && this->codecache && this->tag > 0/
3046 + MARK_LINE;
3047 + this->tag = copyin_uchar(this->block + this->segment);
3048 + this->segment = this->segment - this->tag;
3051 +dtrace:helper:ustack:
3052 +/!this->done && this->codecache && this->tag > 0/
3054 + MARK_LINE;
3055 + this->tag = copyin_uchar(this->block + this->segment);
3056 + this->segment = this->segment - this->tag;
3059 +dtrace:helper:ustack:
3060 +/!this->done && this->codecache && this->tag > 0/
3062 + MARK_LINE;
3063 + this->tag = copyin_uchar(this->block + this->segment);
3064 + this->segment = this->segment - this->tag;
3067 +dtrace:helper:ustack:
3068 +/!this->done && this->codecache && this->tag > 0/
3070 + MARK_LINE;
3071 + this->error = "<couldn't find start>";
3072 + this->done = 1;
3075 +dtrace:helper:ustack:
3076 +/!this->done && this->codecache/
3078 + MARK_LINE;
3079 + this->block = this->code_heap_low +
3080 + (this->segment << this->code_heap_log2_segment_size);
3081 + this->used = copyin_uint32(this->block + OFFSET_HeapBlockHeader_used);
3084 +dtrace:helper:ustack:
3085 +/!this->done && this->codecache && !this->used/
3087 + MARK_LINE;
3088 + this->error = "<block not in use>";
3089 + this->done = 1;
3092 +dtrace:helper:ustack:
3093 +/!this->done && this->codecache/
3095 + MARK_LINE;
3096 + this->start = this->block + SIZE_HeapBlockHeader;
3097 + this->vtbl = copyin_ptr(this->start);
3099 + this->nmethod_vtbl = (pointer) &``__1cHnmethodG__vtbl_;
3100 + this->BufferBlob_vtbl = (pointer) &``__1cKBufferBlobG__vtbl_;
3103 +dtrace:helper:ustack:
3104 +/!this->done && this->vtbl == this->nmethod_vtbl/
3106 + MARK_LINE;
3107 + this->methodPtr = copyin_ptr(this->start + OFFSET_nmethod_method);
3108 + this->suffix = '*';
3109 + this->isMethod = 1;
3112 +dtrace:helper:ustack:
3113 +/!this->done && this->vtbl == this->BufferBlob_vtbl/
3115 + MARK_LINE;
3116 + this->name = copyin_ptr(this->start + OFFSET_CodeBlob_name);
3120 +dtrace:helper:ustack:
3121 +/!this->done && this->vtbl == this->BufferBlob_vtbl && this->methodPtr != 0/
3123 + MARK_LINE;
3124 + this->klass = copyin_ptr(this->methodPtr);
3125 + this->isMethod = this->klass == this->Method_vtbl;
3126 + this->done = !this->isMethod;
3129 +dtrace:helper:ustack:
3130 +/!this->done && !this->isMethod/
3132 + MARK_LINE;
3133 + this->name = copyin_ptr(this->start + OFFSET_CodeBlob_name);
3134 + this->result = this->name != 0 ? copyinstr(this->name) : "<CodeBlob>";
3135 + this->done = 1;
3138 +dtrace:helper:ustack:
3139 +/!this->done && this->isMethod/
3141 + MARK_LINE;
3142 + this->constMethod = copyin_ptr(this->methodPtr +
3143 + OFFSET_Method_constMethod);
3145 + this->nameIndex = copyin_uint16(this->constMethod +
3146 + OFFSET_ConstMethod_name_index);
3148 + this->signatureIndex = copyin_uint16(this->constMethod +
3149 + OFFSET_ConstMethod_signature_index);
3151 + this->constantPool = copyin_ptr(this->constMethod +
3152 + OFFSET_ConstMethod_constants);
3154 + this->nameSymbol = copyin_ptr(this->constantPool +
3155 + this->nameIndex * sizeof (pointer) + SIZE_ConstantPool);
3156 + /* The symbol is a CPSlot and has lower bit set to indicate metadata */
3157 + this->nameSymbol &= (~1); /* remove metadata lsb */
3159 + this->nameSymbolLength = copyin_uint16(this->nameSymbol +
3160 + OFFSET_Symbol_length);
3162 + this->signatureSymbol = copyin_ptr(this->constantPool +
3163 + this->signatureIndex * sizeof (pointer) + SIZE_ConstantPool);
3164 + this->signatureSymbol &= (~1); /* remove metadata lsb */
3166 + this->signatureSymbolLength = copyin_uint16(this->signatureSymbol +
3167 + OFFSET_Symbol_length);
3169 + this->klassPtr = copyin_ptr(this->constantPool +
3170 + OFFSET_ConstantPool_pool_holder);
3172 + this->klassSymbol = copyin_ptr(this->klassPtr +
3173 + OFFSET_Klass_name);
3175 + this->klassSymbolLength = copyin_uint16(this->klassSymbol +
3176 + OFFSET_Symbol_length);
3178 + /*
3179 + * Enough for three strings, plus the '.', plus the trailing '\0'.
3180 + */
3181 + this->result = (char *) alloca(this->klassSymbolLength +
3182 + this->nameSymbolLength +
3183 + this->signatureSymbolLength + 2 + 1);
3185 + copyinto(this->klassSymbol + OFFSET_Symbol_body,
3186 + this->klassSymbolLength, this->result);
3188 + /*
3189 + * Add the '.' between the class and the name.
3190 + */
3191 + this->result[this->klassSymbolLength] = '.';
3193 + copyinto(this->nameSymbol + OFFSET_Symbol_body,
3194 + this->nameSymbolLength,
3195 + this->result + this->klassSymbolLength + 1);
3197 + copyinto(this->signatureSymbol + OFFSET_Symbol_body,
3198 + this->signatureSymbolLength,
3199 + this->result + this->klassSymbolLength +
3200 + this->nameSymbolLength + 1);
3202 + /*
3203 + * Now we need to add a trailing '\0' and possibly a tag character.
3204 + */
3205 + this->result[this->klassSymbolLength + 1 +
3206 + this->nameSymbolLength +
3207 + this->signatureSymbolLength] = this->suffix;
3208 + this->result[this->klassSymbolLength + 2 +
3209 + this->nameSymbolLength +
3210 + this->signatureSymbolLength] = '\0';
3212 + this->done = 1;
3215 +dtrace:helper:ustack:
3216 +/this->done && this->error == (char *) NULL/
3218 + this->result;
3221 +dtrace:helper:ustack:
3222 +/this->done && this->error != (char *) NULL/
3224 + this->error;
3227 +dtrace:helper:ustack:
3228 +/!this->done && this->codecache/
3230 + this->done = 1;
3231 + "error";
3235 +dtrace:helper:ustack:
3236 +/!this->done/
3238 + NULL;
3240 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os/solaris/globals_solaris.hpp jdk21u-jdk-21.0.4-ga/src/hotspot/os/solaris/globals_solaris.hpp
3241 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os/solaris/globals_solaris.hpp 1970-01-01 01:00:00.000000000 +0100
3242 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/os/solaris/globals_solaris.hpp 2024-08-17 19:13:01.445593926 +0200
3243 @@ -0,0 +1,49 @@
3245 + * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved.
3246 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3248 + * This code is free software; you can redistribute it and/or modify it
3249 + * under the terms of the GNU General Public License version 2 only, as
3250 + * published by the Free Software Foundation.
3252 + * This code is distributed in the hope that it will be useful, but WITHOUT
3253 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
3254 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
3255 + * version 2 for more details (a copy is included in the LICENSE file that
3256 + * accompanied this code).
3258 + * You should have received a copy of the GNU General Public License version
3259 + * 2 along with this work; if not, write to the Free Software Foundation,
3260 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
3262 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
3263 + * or visit www.oracle.com if you need additional information or have any
3264 + * questions.
3266 + */
3268 +#ifndef OS_SOLARIS_GLOBALS_SOLARIS_HPP
3269 +#define OS_SOLARIS_GLOBALS_SOLARIS_HPP
3272 +// Defines Solaris specific flags. They are not available on other platforms.
3274 +#define RUNTIME_OS_FLAGS(develop, \
3275 + develop_pd, \
3276 + product, \
3277 + product_pd, \
3278 + notproduct, \
3279 + range, \
3280 + constraint)
3283 +// Defines Solaris-specific default values. The flags are available on all
3284 +// platforms, but they may have different default values on other platforms.
3286 +define_pd_global(size_t, PreTouchParallelChunkSize, 1 * G);
3287 +define_pd_global(bool, UseLargePages, true);
3288 +define_pd_global(bool, UseLargePagesIndividualAllocation, false);
3289 +define_pd_global(bool, UseOSErrorReporting, false);
3290 +define_pd_global(bool, UseThreadPriorities, false);
3292 +#endif // OS_SOLARIS_GLOBALS_SOLARIS_HPP
3293 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os/solaris/os_perf_solaris.cpp jdk21u-jdk-21.0.4-ga/src/hotspot/os/solaris/os_perf_solaris.cpp
3294 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os/solaris/os_perf_solaris.cpp 1970-01-01 01:00:00.000000000 +0100
3295 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/os/solaris/os_perf_solaris.cpp 2024-08-17 19:13:01.446868288 +0200
3296 @@ -0,0 +1,808 @@
3298 + * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
3299 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3301 + * This code is free software; you can redistribute it and/or modify it
3302 + * under the terms of the GNU General Public License version 2 only, as
3303 + * published by the Free Software Foundation.
3305 + * This code is distributed in the hope that it will be useful, but WITHOUT
3306 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
3307 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
3308 + * version 2 for more details (a copy is included in the LICENSE file that
3309 + * accompanied this code).
3311 + * You should have received a copy of the GNU General Public License version
3312 + * 2 along with this work; if not, write to the Free Software Foundation,
3313 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
3315 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
3316 + * or visit www.oracle.com if you need additional information or have any
3317 + * questions.
3319 + */
3321 +#include "precompiled.hpp"
3322 +#include "jvm.h"
3323 +#include "memory/allocation.inline.hpp"
3324 +#include "runtime/os.hpp"
3325 +#include "runtime/os_perf.hpp"
3326 +#include "runtime/vm_version.hpp"
3327 +#include "os_solaris.inline.hpp"
3328 +#include "utilities/globalDefinitions.hpp"
3329 +#include "utilities/macros.hpp"
3331 +#include <sys/types.h>
3332 +#include <procfs.h>
3333 +#include <dirent.h>
3334 +#include <errno.h>
3335 +#include <stdio.h>
3336 +#include <stdlib.h>
3337 +#include <strings.h>
3338 +#include <unistd.h>
3339 +#include <fcntl.h>
3340 +#include <kstat.h>
3341 +#include <unistd.h>
3342 +#include <string.h>
3343 +#include <sys/sysinfo.h>
3344 +#include <sys/lwp.h>
3345 +#include <pthread.h>
3346 +#include <time.h>
3347 +#include <utmpx.h>
3348 +#include <dlfcn.h>
3349 +#include <sys/loadavg.h>
3350 +#include <limits.h>
3352 +static const double NANOS_PER_SEC = 1000000000.0;
3354 +struct CPUPerfTicks {
3355 + kstat_t* kstat;
3356 + uint64_t last_idle;
3357 + uint64_t last_total;
3358 + double last_ratio;
3361 +struct CPUPerfCounters {
3362 + int nProcs;
3363 + CPUPerfTicks* jvmTicks;
3364 + kstat_ctl_t* kstat_ctrl;
3367 +static int get_info(const char* path, void* info, size_t s, off_t o) {
3368 + assert(path != NULL, "path is NULL!");
3369 + assert(info != NULL, "info is NULL!");
3371 + int fd = -1;
3373 + if ((fd = os::open(path, O_RDONLY, 0)) < 0) {
3374 + return OS_ERR;
3376 + if (pread(fd, info, s, o) != s) {
3377 + close(fd);
3378 + return OS_ERR;
3380 + close(fd);
3381 + return OS_OK;
3384 +static int get_psinfo2(void* info, size_t s, off_t o) {
3385 + return get_info("/proc/self/psinfo", info, s, o);
3388 +static int get_psinfo(psinfo_t* info) {
3389 + return get_psinfo2(info, sizeof(*info), 0);
3392 +static int read_cpustat(kstat_ctl_t* kstat_ctrl, CPUPerfTicks* load, cpu_stat_t* cpu_stat) {
3393 + assert(kstat_ctrl != NULL, "kstat_ctrl pointer is NULL!");
3394 + assert(load != NULL, "load pointer is NULL!");
3395 + assert(cpu_stat != NULL, "cpu_stat pointer is NULL!");
3397 + if (load->kstat == NULL) {
3398 + // no handle.
3399 + return OS_ERR;
3401 + if (kstat_read(kstat_ctrl, load->kstat, cpu_stat) == OS_ERR) {
3402 + // disable handle for this CPU
3403 + load->kstat = NULL;
3404 + return OS_ERR;
3406 + return OS_OK;
3409 +static double get_cpu_load(int which_logical_cpu, CPUPerfCounters* counters) {
3410 + assert(counters != NULL, "counters pointer is NULL!");
3412 + cpu_stat_t cpu_stat = {0};
3414 + if (which_logical_cpu >= counters->nProcs) {
3415 + return .0;
3418 + CPUPerfTicks load = counters->jvmTicks[which_logical_cpu];
3419 + if (read_cpustat(counters->kstat_ctrl, &load, &cpu_stat) != OS_OK) {
3420 + return .0;
3423 + uint_t* usage = cpu_stat.cpu_sysinfo.cpu;
3424 + if (usage == NULL) {
3425 + return .0;
3428 + uint64_t c_idle = usage[CPU_IDLE];
3429 + uint64_t c_total = 0;
3431 + for (int i = 0; i < CPU_STATES; i++) {
3432 + c_total += usage[i];
3435 + // Calculate diff against previous snapshot
3436 + uint64_t d_idle = c_idle - load.last_idle;
3437 + uint64_t d_total = c_total - load.last_total;
3439 + /** update if weve moved */
3440 + if (d_total > 0) {
3441 + // Save current values for next time around
3442 + load.last_idle = c_idle;
3443 + load.last_total = c_total;
3444 + load.last_ratio = (double) (d_total - d_idle) / d_total;
3447 + return load.last_ratio;
3450 +static int get_boot_time(uint64_t* time) {
3451 + assert(time != NULL, "time pointer is NULL!");
3452 + setutxent();
3453 + for(;;) {
3454 + struct utmpx* u;
3455 + if ((u = getutxent()) == NULL) {
3456 + break;
3458 + if (u->ut_type == BOOT_TIME) {
3459 + *time = u->ut_xtime;
3460 + endutxent();
3461 + return OS_OK;
3464 + endutxent();
3465 + return OS_ERR;
3468 +static int get_noof_context_switches(CPUPerfCounters* counters, uint64_t* switches) {
3469 + assert(switches != NULL, "switches pointer is NULL!");
3470 + assert(counters != NULL, "counter pointer is NULL!");
3471 + *switches = 0;
3472 + uint64_t s = 0;
3474 + // Collect data from all CPUs
3475 + for (int i = 0; i < counters->nProcs; i++) {
3476 + cpu_stat_t cpu_stat = {0};
3477 + CPUPerfTicks load = counters->jvmTicks[i];
3479 + if (read_cpustat(counters->kstat_ctrl, &load, &cpu_stat) == OS_OK) {
3480 + s += cpu_stat.cpu_sysinfo.pswitch;
3481 + } else {
3482 + //fail fast...
3483 + return OS_ERR;
3486 + *switches = s;
3487 + return OS_OK;
3490 +static int perf_context_switch_rate(CPUPerfCounters* counters, double* rate) {
3491 + assert(counters != NULL, "counters is NULL!");
3492 + assert(rate != NULL, "rate pointer is NULL!");
3493 + static pthread_mutex_t contextSwitchLock = PTHREAD_MUTEX_INITIALIZER;
3494 + static uint64_t lastTime = 0;
3495 + static uint64_t lastSwitches = 0;
3496 + static double lastRate = 0.0;
3498 + uint64_t lt = 0;
3499 + int res = 0;
3501 + if (lastTime == 0) {
3502 + uint64_t tmp;
3503 + if (get_boot_time(&tmp) < 0) {
3504 + return OS_ERR;
3506 + lt = tmp * 1000;
3509 + res = OS_OK;
3511 + pthread_mutex_lock(&contextSwitchLock);
3514 + uint64_t sw = 0;
3515 + clock_t t, d;
3517 + if (lastTime == 0) {
3518 + lastTime = lt;
3521 + t = clock();
3522 + d = t - lastTime;
3524 + if (d == 0) {
3525 + *rate = lastRate;
3526 + } else if (get_noof_context_switches(counters, &sw)== OS_OK) {
3527 + *rate = ((double)(sw - lastSwitches) / d) * 1000;
3528 + lastRate = *rate;
3529 + lastSwitches = sw;
3530 + lastTime = t;
3531 + } else {
3532 + *rate = 0.0;
3533 + res = OS_ERR;
3535 + if (*rate < 0.0) {
3536 + *rate = 0.0;
3537 + lastRate = 0.0;
3540 + pthread_mutex_unlock(&contextSwitchLock);
3541 + return res;
3546 +class CPUPerformanceInterface::CPUPerformance : public CHeapObj<mtInternal> {
3547 + friend class CPUPerformanceInterface;
3548 + private:
3549 + CPUPerfCounters _counters;
3550 + int cpu_load(int which_logical_cpu, double* cpu_load);
3551 + int context_switch_rate(double* rate);
3552 + int cpu_load_total_process(double* cpu_load);
3553 + int cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad);
3555 + CPUPerformance();
3556 + ~CPUPerformance();
3557 + bool initialize();
3560 +CPUPerformanceInterface::CPUPerformance::CPUPerformance() {
3561 + _counters.nProcs = 0;
3562 + _counters.jvmTicks = NULL;
3563 + _counters.kstat_ctrl = NULL;
3566 +bool CPUPerformanceInterface::CPUPerformance::initialize() {
3567 + // initialize kstat control structure,
3568 + _counters.kstat_ctrl = kstat_open();
3569 + assert(_counters.kstat_ctrl != NULL, "error initializing kstat control structure!");
3571 + if (NULL == _counters.kstat_ctrl) {
3572 + return false;
3575 + // Get number of CPU(s)
3576 + if ((_counters.nProcs = sysconf(_SC_NPROCESSORS_ONLN)) == OS_ERR) {
3577 + // ignore error?
3578 + _counters.nProcs = 1;
3581 + assert(_counters.nProcs > 0, "no CPUs detected in sysconf call!");
3582 + if (_counters.nProcs == 0) {
3583 + return false;
3586 + // Data structure(s) for saving CPU load (one per CPU)
3587 + size_t array_entry_count = _counters.nProcs;
3588 + _counters.jvmTicks = NEW_C_HEAP_ARRAY(CPUPerfTicks, array_entry_count, mtInternal);
3589 + memset(_counters.jvmTicks, 0, array_entry_count * sizeof(*_counters.jvmTicks));
3591 + // Get kstat cpu_stat counters for every CPU
3592 + // loop over kstat to find our cpu_stat(s)
3593 + int i = 0;
3594 + for (kstat_t* kstat = _counters.kstat_ctrl->kc_chain; kstat != NULL; kstat = kstat->ks_next) {
3595 + if (strncmp(kstat->ks_module, "cpu_stat", 8) == 0) {
3596 + if (kstat_read(_counters.kstat_ctrl, kstat, NULL) == OS_ERR) {
3597 + continue;
3599 + if (i == _counters.nProcs) {
3600 + // more cpu_stats than reported CPUs
3601 + break;
3603 + _counters.jvmTicks[i++].kstat = kstat;
3606 + return true;
3609 +CPUPerformanceInterface::CPUPerformance::~CPUPerformance() {
3610 + FREE_C_HEAP_ARRAY(char, _counters.jvmTicks);
3611 + if (_counters.kstat_ctrl != NULL) {
3612 + kstat_close(_counters.kstat_ctrl);
3616 +int CPUPerformanceInterface::CPUPerformance::cpu_load(int which_logical_cpu, double* cpu_load) {
3617 + assert(cpu_load != NULL, "cpu_load pointer is NULL!");
3618 + double t = .0;
3619 + if (-1 == which_logical_cpu) {
3620 + for (int i = 0; i < _counters.nProcs; i++) {
3621 + t += get_cpu_load(i, &_counters);
3623 + // Cap total systemload to 1.0
3624 + t = MIN2<double>((t / _counters.nProcs), 1.0);
3625 + } else {
3626 + t = MIN2<double>(get_cpu_load(which_logical_cpu, &_counters), 1.0);
3629 + *cpu_load = t;
3630 + return OS_OK;
3633 +int CPUPerformanceInterface::CPUPerformance::cpu_load_total_process(double* cpu_load) {
3634 + assert(cpu_load != NULL, "cpu_load pointer is NULL!");
3636 + psinfo_t info;
3638 + // Get the percentage of "recent cpu usage" from all the lwp:s in the JVM:s
3639 + // process. This is returned as a value between 0.0 and 1.0 multiplied by 0x8000.
3640 + if (get_psinfo2(&info.pr_pctcpu, sizeof(info.pr_pctcpu), offsetof(psinfo_t, pr_pctcpu)) != 0) {
3641 + *cpu_load = 0.0;
3642 + return OS_ERR;
3644 + *cpu_load = (double) info.pr_pctcpu / 0x8000;
3645 + return OS_OK;
3648 +int CPUPerformanceInterface::CPUPerformance::cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad) {
3649 + assert(pjvmUserLoad != NULL, "pjvmUserLoad not inited");
3650 + assert(pjvmKernelLoad != NULL, "pjvmKernelLoad not inited");
3651 + assert(psystemTotalLoad != NULL, "psystemTotalLoad not inited");
3653 + static uint64_t lastTime;
3654 + static uint64_t lastUser, lastKernel;
3655 + static double lastUserRes, lastKernelRes;
3657 + pstatus_t pss;
3658 + psinfo_t info;
3660 + *pjvmKernelLoad = *pjvmUserLoad = *psystemTotalLoad = 0;
3661 + if (get_info("/proc/self/status", &pss.pr_utime, sizeof(timestruc_t)*2, offsetof(pstatus_t, pr_utime)) != 0) {
3662 + return OS_ERR;
3665 + if (get_psinfo(&info) != 0) {
3666 + return OS_ERR;
3669 + // get the total time in user, kernel and total time
3670 + // check ratios for 'lately' and multiply the 'recent load'.
3671 + uint64_t time = (info.pr_time.tv_sec * NANOS_PER_SEC) + info.pr_time.tv_nsec;
3672 + uint64_t user = (pss.pr_utime.tv_sec * NANOS_PER_SEC) + pss.pr_utime.tv_nsec;
3673 + uint64_t kernel = (pss.pr_stime.tv_sec * NANOS_PER_SEC) + pss.pr_stime.tv_nsec;
3674 + uint64_t diff = time - lastTime;
3675 + double load = (double) info.pr_pctcpu / 0x8000;
3677 + if (diff > 0) {
3678 + lastUserRes = (load * (user - lastUser)) / diff;
3679 + lastKernelRes = (load * (kernel - lastKernel)) / diff;
3681 + // BUG9182835 - patch for clamping these values to sane ones.
3682 + lastUserRes = MIN2<double>(1, lastUserRes);
3683 + lastUserRes = MAX2<double>(0, lastUserRes);
3684 + lastKernelRes = MIN2<double>(1, lastKernelRes);
3685 + lastKernelRes = MAX2<double>(0, lastKernelRes);
3688 + double t = .0;
3689 + cpu_load(-1, &t);
3690 + // clamp at user+system and 1.0
3691 + if (lastUserRes + lastKernelRes > t) {
3692 + t = MIN2<double>(lastUserRes + lastKernelRes, 1.0);
3695 + *pjvmUserLoad = lastUserRes;
3696 + *pjvmKernelLoad = lastKernelRes;
3697 + *psystemTotalLoad = t;
3699 + lastTime = time;
3700 + lastUser = user;
3701 + lastKernel = kernel;
3703 + return OS_OK;
3706 +int CPUPerformanceInterface::CPUPerformance::context_switch_rate(double* rate) {
3707 + return perf_context_switch_rate(&_counters, rate);
3710 +CPUPerformanceInterface::CPUPerformanceInterface() {
3711 + _impl = NULL;
3714 +bool CPUPerformanceInterface::initialize() {
3715 + _impl = new CPUPerformanceInterface::CPUPerformance();
3716 + return _impl->initialize();
3719 +CPUPerformanceInterface::~CPUPerformanceInterface(void) {
3720 + if (_impl != NULL) {
3721 + delete _impl;
3725 +int CPUPerformanceInterface::cpu_load(int which_logical_cpu, double* cpu_load) const {
3726 + return _impl->cpu_load(which_logical_cpu, cpu_load);
3729 +int CPUPerformanceInterface::cpu_load_total_process(double* cpu_load) const {
3730 + return _impl->cpu_load_total_process(cpu_load);
3733 +int CPUPerformanceInterface::cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad) const {
3734 + return _impl->cpu_loads_process(pjvmUserLoad, pjvmKernelLoad, psystemTotalLoad);
3737 +int CPUPerformanceInterface::context_switch_rate(double* rate) const {
3738 + return _impl->context_switch_rate(rate);
3741 +class SystemProcessInterface::SystemProcesses : public CHeapObj<mtInternal> {
3742 + friend class SystemProcessInterface;
3743 + private:
3744 + class ProcessIterator : public CHeapObj<mtInternal> {
3745 + friend class SystemProcessInterface::SystemProcesses;
3746 + private:
3747 + DIR* _dir;
3748 + struct dirent* _entry;
3749 + bool _valid;
3751 + ProcessIterator();
3752 + ~ProcessIterator();
3753 + bool initialize();
3755 + bool is_valid() const { return _valid; }
3756 + bool is_valid_entry(struct dirent* const entry) const;
3757 + bool is_dir(const char* const name) const;
3758 + char* allocate_string(const char* const str) const;
3759 + int current(SystemProcess* const process_info);
3760 + int next_process();
3761 + };
3763 + ProcessIterator* _iterator;
3764 + SystemProcesses();
3765 + bool initialize();
3766 + ~SystemProcesses();
3768 + //information about system processes
3769 + int system_processes(SystemProcess** system_processes, int* no_of_sys_processes) const;
3772 +bool SystemProcessInterface::SystemProcesses::ProcessIterator::is_dir(const char* name) const {
3773 + struct stat64 mystat;
3774 + int ret_val = 0;
3776 + ret_val = ::stat64(name, &mystat);
3778 + if (ret_val < 0) {
3779 + return false;
3781 + ret_val = S_ISDIR(mystat.st_mode);
3782 + return ret_val > 0;
3785 +// if it has a numeric name, is a directory and has a 'psinfo' file in it
3786 +bool SystemProcessInterface::SystemProcesses::ProcessIterator::is_valid_entry(struct dirent* entry) const {
3787 + // ignore the "." and ".." directories
3788 + if ((strcmp(entry->d_name, ".") == 0) ||
3789 + (strcmp(entry->d_name, "..") == 0)) {
3790 + return false;
3793 + char buffer[PATH_MAX] = {0};
3794 + uint64_t size = 0;
3795 + bool result = false;
3796 + FILE *fp = NULL;
3798 + if (atoi(entry->d_name) != 0) {
3799 + jio_snprintf(buffer, PATH_MAX, "/proc/%s", entry->d_name);
3801 + if (is_dir(buffer)) {
3802 + memset(buffer, 0, PATH_MAX);
3803 + jio_snprintf(buffer, PATH_MAX, "/proc/%s/psinfo", entry->d_name);
3804 + if ((fp = fopen(buffer, "r")) != NULL) {
3805 + int nread = 0;
3806 + psinfo_t psinfo_data;
3807 + if ((nread = fread(&psinfo_data, 1, sizeof(psinfo_t), fp)) != -1) {
3808 + // only considering system process owned by root
3809 + if (psinfo_data.pr_uid == 0) {
3810 + result = true;
3817 + if (fp != NULL) {
3818 + fclose(fp);
3821 + return result;
3824 +char* SystemProcessInterface::SystemProcesses::ProcessIterator::allocate_string(const char* str) const {
3825 + if (str != NULL) {
3826 + return os::strdup_check_oom(str, mtInternal);
3828 + return NULL;
3831 +int SystemProcessInterface::SystemProcesses::ProcessIterator::current(SystemProcess* process_info) {
3832 + if (!is_valid()) {
3833 + return OS_ERR;
3836 + char psinfo_path[PATH_MAX] = {0};
3837 + jio_snprintf(psinfo_path, PATH_MAX, "/proc/%s/psinfo", _entry->d_name);
3839 + FILE *fp = NULL;
3840 + if ((fp = fopen(psinfo_path, "r")) == NULL) {
3841 + return OS_ERR;
3844 + int nread = 0;
3845 + psinfo_t psinfo_data;
3846 + if ((nread = fread(&psinfo_data, 1, sizeof(psinfo_t), fp)) == -1) {
3847 + fclose(fp);
3848 + return OS_ERR;
3851 + char *exe_path = NULL;
3852 + if ((psinfo_data.pr_fname != NULL) &&
3853 + (psinfo_data.pr_psargs != NULL)) {
3854 + char *path_substring = strstr(psinfo_data.pr_psargs, psinfo_data.pr_fname);
3855 + if (path_substring != NULL) {
3856 + int len = path_substring - psinfo_data.pr_psargs;
3857 + exe_path = NEW_C_HEAP_ARRAY(char, len+1, mtInternal);
3858 + jio_snprintf(exe_path, len, "%s", psinfo_data.pr_psargs);
3859 + exe_path[len] = '\0';
3863 + process_info->set_pid(atoi(_entry->d_name));
3864 + process_info->set_name(allocate_string(psinfo_data.pr_fname));
3865 + process_info->set_path(allocate_string(exe_path));
3866 + process_info->set_command_line(allocate_string(psinfo_data.pr_psargs));
3868 + if (exe_path != NULL) {
3869 + FREE_C_HEAP_ARRAY(char, exe_path);
3872 + if (fp != NULL) {
3873 + fclose(fp);
3876 + return OS_OK;
3879 +int SystemProcessInterface::SystemProcesses::ProcessIterator::next_process() {
3880 + if (!is_valid()) {
3881 + return OS_ERR;
3884 + do {
3885 + _entry = os::readdir(_dir);
3886 + if (_entry == NULL) {
3887 + // Error or reached end. Could use errno to distinguish those cases.
3888 + _valid = false;
3889 + return OS_ERR;
3891 + } while(!is_valid_entry(_entry));
3893 + _valid = true;
3894 + return OS_OK;
3897 +SystemProcessInterface::SystemProcesses::ProcessIterator::ProcessIterator() {
3898 + _dir = NULL;
3899 + _entry = NULL;
3900 + _valid = false;
3903 +bool SystemProcessInterface::SystemProcesses::ProcessIterator::initialize() {
3904 + _dir = os::opendir("/proc");
3905 + _entry = NULL;
3906 + _valid = true;
3907 + next_process();
3909 + return true;
3912 +SystemProcessInterface::SystemProcesses::ProcessIterator::~ProcessIterator() {
3913 + if (_dir != NULL) {
3914 + os::closedir(_dir);
3918 +SystemProcessInterface::SystemProcesses::SystemProcesses() {
3919 + _iterator = NULL;
3922 +bool SystemProcessInterface::SystemProcesses::initialize() {
3923 + _iterator = new SystemProcessInterface::SystemProcesses::ProcessIterator();
3924 + return _iterator->initialize();
3927 +SystemProcessInterface::SystemProcesses::~SystemProcesses() {
3928 + if (_iterator != NULL) {
3929 + delete _iterator;
3933 +int SystemProcessInterface::SystemProcesses::system_processes(SystemProcess** system_processes, int* no_of_sys_processes) const {
3934 + assert(system_processes != NULL, "system_processes pointer is NULL!");
3935 + assert(no_of_sys_processes != NULL, "system_processes counter pointer is NULL!");
3936 + assert(_iterator != NULL, "iterator is NULL!");
3938 + // initialize pointers
3939 + *no_of_sys_processes = 0;
3940 + *system_processes = NULL;
3942 + while (_iterator->is_valid()) {
3943 + SystemProcess* tmp = new SystemProcess();
3944 + _iterator->current(tmp);
3946 + //if already existing head
3947 + if (*system_processes != NULL) {
3948 + //move "first to second"
3949 + tmp->set_next(*system_processes);
3951 + // new head
3952 + *system_processes = tmp;
3953 + // increment
3954 + (*no_of_sys_processes)++;
3955 + // step forward
3956 + _iterator->next_process();
3958 + return OS_OK;
3961 +int SystemProcessInterface::system_processes(SystemProcess** system_procs, int* no_of_sys_processes) const {
3962 + return _impl->system_processes(system_procs, no_of_sys_processes);
3965 +SystemProcessInterface::SystemProcessInterface() {
3966 + _impl = NULL;
3969 +bool SystemProcessInterface::initialize() {
3970 + _impl = new SystemProcessInterface::SystemProcesses();
3971 + return _impl->initialize();
3975 +SystemProcessInterface::~SystemProcessInterface() {
3976 + if (_impl != NULL) {
3977 + delete _impl;
3981 +CPUInformationInterface::CPUInformationInterface() {
3982 + _cpu_info = NULL;
3985 +bool CPUInformationInterface::initialize() {
3986 + _cpu_info = new CPUInformation();
3987 + VM_Version::initialize_cpu_information();
3988 + _cpu_info->set_number_of_hardware_threads(VM_Version::number_of_threads());
3989 + _cpu_info->set_number_of_cores(VM_Version::number_of_cores());
3990 + _cpu_info->set_number_of_sockets(VM_Version::number_of_sockets());
3991 + _cpu_info->set_cpu_name(VM_Version::cpu_name());
3992 + _cpu_info->set_cpu_description(VM_Version::cpu_description());
3993 + return true;
3996 +CPUInformationInterface::~CPUInformationInterface() {
3997 + if (_cpu_info != NULL) {
3998 + if (_cpu_info->cpu_name() != NULL) {
3999 + const char* cpu_name = _cpu_info->cpu_name();
4000 + FREE_C_HEAP_ARRAY(char, cpu_name);
4001 + _cpu_info->set_cpu_name(NULL);
4003 + if (_cpu_info->cpu_description() != NULL) {
4004 + const char* cpu_desc = _cpu_info->cpu_description();
4005 + FREE_C_HEAP_ARRAY(char, cpu_desc);
4006 + _cpu_info->set_cpu_description(NULL);
4008 + delete _cpu_info;
4012 +int CPUInformationInterface::cpu_information(CPUInformation& cpu_info) {
4013 + if (_cpu_info == NULL) {
4014 + return OS_ERR;
4017 + cpu_info = *_cpu_info; // shallow copy assignment
4018 + return OS_OK;
4021 +class NetworkPerformanceInterface::NetworkPerformance : public CHeapObj<mtInternal> {
4022 + friend class NetworkPerformanceInterface;
4023 + private:
4024 + NetworkPerformance();
4025 + NONCOPYABLE(NetworkPerformance);
4026 + bool initialize();
4027 + ~NetworkPerformance();
4028 + int network_utilization(NetworkInterface** network_interfaces) const;
4031 +NetworkPerformanceInterface::NetworkPerformance::NetworkPerformance() {
4035 +bool NetworkPerformanceInterface::NetworkPerformance::initialize() {
4036 + return true;
4039 +NetworkPerformanceInterface::NetworkPerformance::~NetworkPerformance() {
4043 +int NetworkPerformanceInterface::NetworkPerformance::network_utilization(NetworkInterface** network_interfaces) const
4045 + kstat_ctl_t* ctl = kstat_open();
4046 + if (ctl == NULL) {
4047 + return OS_ERR;
4050 + NetworkInterface* ret = NULL;
4051 + for (kstat_t* k = ctl->kc_chain; k != NULL; k = k->ks_next) {
4052 + if (strcmp(k->ks_class, "net") != 0) {
4053 + continue;
4055 + if (strcmp(k->ks_module, "link") != 0) {
4056 + continue;
4059 + if (kstat_read(ctl, k, NULL) == -1) {
4060 + return OS_ERR;
4063 + uint64_t bytes_in = UINT64_MAX;
4064 + uint64_t bytes_out = UINT64_MAX;
4065 + for (unsigned int i = 0; i < k->ks_ndata; ++i) {
4066 + kstat_named_t* data = &reinterpret_cast<kstat_named_t*>(k->ks_data)[i];
4067 + if (strcmp(data->name, "rbytes64") == 0) {
4068 + bytes_in = data->value.ui64;
4070 + else if (strcmp(data->name, "obytes64") == 0) {
4071 + bytes_out = data->value.ui64;
4075 + if ((bytes_in != UINT64_MAX) && (bytes_out != UINT64_MAX)) {
4076 + NetworkInterface* cur = new NetworkInterface(k->ks_name, bytes_in, bytes_out, ret);
4077 + ret = cur;
4081 + kstat_close(ctl);
4082 + *network_interfaces = ret;
4084 + return OS_OK;
4087 +NetworkPerformanceInterface::NetworkPerformanceInterface() {
4088 + _impl = NULL;
4091 +NetworkPerformanceInterface::~NetworkPerformanceInterface() {
4092 + if (_impl != NULL) {
4093 + delete _impl;
4097 +bool NetworkPerformanceInterface::initialize() {
4098 + _impl = new NetworkPerformanceInterface::NetworkPerformance();
4099 + return _impl->initialize();
4102 +int NetworkPerformanceInterface::network_utilization(NetworkInterface** network_interfaces) const {
4103 + return _impl->network_utilization(network_interfaces);
4105 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os/solaris/os_solaris.cpp jdk21u-jdk-21.0.4-ga/src/hotspot/os/solaris/os_solaris.cpp
4106 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os/solaris/os_solaris.cpp 1970-01-01 01:00:00.000000000 +0100
4107 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/os/solaris/os_solaris.cpp 2024-08-17 19:13:01.449239446 +0200
4108 @@ -0,0 +1,3073 @@
4110 + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
4111 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4113 + * This code is free software; you can redistribute it and/or modify it
4114 + * under the terms of the GNU General Public License version 2 only, as
4115 + * published by the Free Software Foundation.
4117 + * This code is distributed in the hope that it will be useful, but WITHOUT
4118 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
4119 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
4120 + * version 2 for more details (a copy is included in the LICENSE file that
4121 + * accompanied this code).
4123 + * You should have received a copy of the GNU General Public License version
4124 + * 2 along with this work; if not, write to the Free Software Foundation,
4125 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
4127 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
4128 + * or visit www.oracle.com if you need additional information or have any
4129 + * questions.
4131 + */
4133 +// no precompiled headers
4134 +#include "jvm.h"
4135 +#include "classfile/classLoader.hpp"
4136 +#include "classfile/systemDictionary.hpp"
4137 +#include "classfile/vmSymbols.hpp"
4138 +#include "code/icBuffer.hpp"
4139 +#include "code/vtableStubs.hpp"
4140 +#include "compiler/compileBroker.hpp"
4141 +#include "compiler/disassembler.hpp"
4142 +#include "interpreter/interpreter.hpp"
4143 +#include "jvmtifiles/jvmti.h"
4144 +#include "logging/log.hpp"
4145 +#include "logging/logStream.hpp"
4146 +#include "memory/allocation.inline.hpp"
4147 +#include "memory/universe.hpp"
4148 +#include "oops/oop.inline.hpp"
4149 +#include "os_solaris.inline.hpp"
4150 +#include "prims/jniFastGetField.hpp"
4151 +#include "prims/jvm_misc.hpp"
4152 +#include "runtime/arguments.hpp"
4153 +#include "runtime/atomic.hpp"
4154 +#include "runtime/globals.hpp"
4155 +#include "runtime/globals_extension.hpp"
4156 +#include "runtime/interfaceSupport.inline.hpp"
4157 +#include "runtime/java.hpp"
4158 +#include "runtime/javaCalls.hpp"
4159 +#include "runtime/javaThread.hpp"
4160 +#include "runtime/mutexLocker.hpp"
4161 +#include "runtime/objectMonitor.hpp"
4162 +#include "runtime/osInfo.hpp"
4163 +#include "runtime/orderAccess.hpp"
4164 +#include "runtime/osThread.hpp"
4165 +#include "runtime/park.hpp"
4166 +#include "runtime/perfMemory.hpp"
4167 +#include "runtime/sharedRuntime.hpp"
4168 +#include "runtime/statSampler.hpp"
4169 +#include "runtime/stubRoutines.hpp"
4170 +#include "runtime/threadCritical.hpp"
4171 +#include "runtime/threads.hpp"
4172 +#include "runtime/timer.hpp"
4173 +#include "runtime/vm_version.hpp"
4174 +#include "semaphore_posix.hpp"
4175 +#include "services/attachListener.hpp"
4176 +#include "services/memTracker.hpp"
4177 +#include "services/runtimeService.hpp"
4178 +#include "signals_posix.hpp"
4179 +#include "utilities/align.hpp"
4180 +#include "utilities/decoder.hpp"
4181 +#include "utilities/defaultStream.hpp"
4182 +#include "utilities/events.hpp"
4183 +#include "utilities/growableArray.hpp"
4184 +#include "utilities/macros.hpp"
4185 +#include "utilities/vmError.hpp"
4187 +// put OS-includes here
4188 +# include <dlfcn.h>
4189 +# include <errno.h>
4190 +# include <exception>
4191 +# include <link.h>
4192 +# include <poll.h>
4193 +# include <pthread.h>
4194 +# include <setjmp.h>
4195 +# include <signal.h>
4196 +# include <stdio.h>
4197 +# include <alloca.h>
4198 +# include <sys/filio.h>
4199 +# include <sys/ipc.h>
4200 +# include <sys/lwp.h>
4201 +# include <sys/machelf.h> // for elf Sym structure used by dladdr1
4202 +# include <sys/mman.h>
4203 +# include <sys/processor.h>
4204 +# include <sys/procset.h>
4205 +# include <sys/pset.h>
4206 +# include <sys/resource.h>
4207 +# include <sys/shm.h>
4208 +# include <sys/socket.h>
4209 +# include <sys/stat.h>
4210 +# include <sys/systeminfo.h>
4211 +# include <sys/time.h>
4212 +# include <sys/times.h>
4213 +# include <sys/types.h>
4214 +# include <sys/wait.h>
4215 +# include <sys/utsname.h>
4216 +# include <thread.h>
4217 +# include <unistd.h>
4218 +# include <sys/priocntl.h>
4219 +# include <sys/rtpriocntl.h>
4220 +# include <sys/tspriocntl.h>
4221 +# include <sys/iapriocntl.h>
4222 +# include <sys/fxpriocntl.h>
4223 +# include <sys/loadavg.h>
4224 +# include <string.h>
4225 +# include <stdio.h>
4227 +# include <procfs.h>
4229 +#define MAX_PATH (2 * K)
4231 +// for timer info max values which include all bits
4232 +#define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF)
4234 +// Here are some liblgrp types from sys/lgrp_user.h to be able to
4235 +// compile on older systems without this header file.
4237 +#ifndef MADV_ACCESS_LWP
4238 + #define MADV_ACCESS_LWP 7 /* next LWP to access heavily */
4239 +#endif
4240 +#ifndef MADV_ACCESS_MANY
4241 + #define MADV_ACCESS_MANY 8 /* many processes to access heavily */
4242 +#endif
4244 +#ifndef LGRP_RSRC_CPU
4245 + #define LGRP_RSRC_CPU 0 /* CPU resources */
4246 +#endif
4247 +#ifndef LGRP_RSRC_MEM
4248 + #define LGRP_RSRC_MEM 1 /* memory resources */
4249 +#endif
4251 +// guarded in sys/mman.h
4252 +extern "C" {
4253 +extern int getpagesizes(size_t[], int);
4256 +// Values for ThreadPriorityPolicy == 1
4257 +int prio_policy1[CriticalPriority+1] = {
4258 + -99999, 0, 16, 32, 48, 64,
4259 + 80, 96, 112, 124, 127, 127 };
4261 +// System parameters used internally
4262 +static clock_t clock_tics_per_sec = 100;
4264 +// For diagnostics to print a message once. see run_periodic_checks
4265 +static bool check_addr0_done = false;
4267 +address os::Solaris::handler_start; // start pc of thr_sighndlrinfo
4268 +address os::Solaris::handler_end; // end pc of thr_sighndlrinfo
4270 +address os::Solaris::_main_stack_base = NULL; // 4352906 workaround
4272 +os::Solaris::pthread_setname_np_func_t os::Solaris::_pthread_setname_np = NULL;
4274 +// "default" initializers for missing libc APIs
4275 +extern "C" {
4276 + int memcntl(void *, size_t, int, void *, int, int);
4277 + int meminfo(const uint64_t *, int, const uint_t *, int, uint64_t *, uint_t *);
4280 +static inline size_t adjust_stack_size(address base, size_t size) {
4281 + if ((ssize_t)size < 0) {
4282 + // 4759953: Compensate for ridiculous stack size.
4283 + size = max_intx;
4285 + if (size > (size_t)base) {
4286 + // 4812466: Make sure size doesn't allow the stack to wrap the address space.
4287 + size = (size_t)base;
4289 + return size;
4292 +static inline stack_t get_stack_info() {
4293 + stack_t st;
4294 + int retval = thr_stksegment(&st);
4295 + st.ss_size = adjust_stack_size((address)st.ss_sp, st.ss_size);
4296 + assert(retval == 0, "incorrect return value from thr_stksegment");
4297 + assert((address)&st < (address)st.ss_sp, "Invalid stack base returned");
4298 + assert((address)&st > (address)st.ss_sp-st.ss_size, "Invalid stack size returned");
4299 + return st;
4302 +bool os::is_primordial_thread(void) {
4303 + int r = thr_main();
4304 + guarantee(r == 0 || r == 1, "CR6501650 or CR6493689");
4305 + return r == 1;
4308 +address os::current_stack_base() {
4309 + bool _is_primordial_thread = is_primordial_thread();
4311 + // Workaround 4352906, avoid calls to thr_stksegment by
4312 + // thr_main after the first one (it looks like we trash
4313 + // some data, causing the value for ss_sp to be incorrect).
4314 + if (!_is_primordial_thread || os::Solaris::_main_stack_base == NULL) {
4315 + stack_t st = get_stack_info();
4316 + if (_is_primordial_thread) {
4317 + // cache initial value of stack base
4318 + os::Solaris::_main_stack_base = (address)st.ss_sp;
4320 + return (address)st.ss_sp;
4321 + } else {
4322 + guarantee(os::Solaris::_main_stack_base != NULL, "Attempt to use null cached stack base");
4323 + return os::Solaris::_main_stack_base;
4327 +size_t os::current_stack_size() {
4328 + size_t size;
4330 + if (!is_primordial_thread()) {
4331 + size = get_stack_info().ss_size;
4332 + } else {
4333 + struct rlimit limits;
4334 + getrlimit(RLIMIT_STACK, &limits);
4335 + size = adjust_stack_size(os::Solaris::_main_stack_base, (size_t)limits.rlim_cur);
4337 + // base may not be page aligned
4338 + address base = current_stack_base();
4339 + address bottom = align_up(base - size, os::vm_page_size());;
4340 + return (size_t)(base - bottom);
4343 +jint os::Solaris::_os_thread_limit = 0;
4344 +volatile jint os::Solaris::_os_thread_count = 0;
4346 +julong os::available_memory() {
4347 + return Solaris::available_memory();
4350 +julong os::free_memory() {
4351 + return Solaris::available_memory();
4354 +julong os::Solaris::available_memory() {
4355 + return (julong)sysconf(_SC_AVPHYS_PAGES) * os::vm_page_size();
4358 +julong os::Solaris::_physical_memory = 0;
4360 +julong os::physical_memory() {
4361 + return Solaris::physical_memory();
4364 +static hrtime_t first_hrtime = 0;
4365 +static const hrtime_t hrtime_hz = 1000*1000*1000;
4366 +static volatile hrtime_t max_hrtime = 0;
4369 +void os::Solaris::initialize_system_info() {
4370 + set_processor_count(sysconf(_SC_NPROCESSORS_CONF));
4371 + _physical_memory = (julong)sysconf(_SC_PHYS_PAGES) *
4372 + (julong)sysconf(_SC_PAGESIZE);
4375 +uint os::processor_id() {
4376 + const processorid_t id = ::getcpuid();
4377 + assert(id >= 0 && id < _processor_count, "Invalid processor id");
4378 + return (uint)id;
4381 +int os::active_processor_count() {
4382 + // User has overridden the number of active processors
4383 + if (ActiveProcessorCount > 0) {
4384 + log_trace(os)("active_processor_count: "
4385 + "active processor count set by user : %d",
4386 + ActiveProcessorCount);
4387 + return ActiveProcessorCount;
4390 + int online_cpus = sysconf(_SC_NPROCESSORS_ONLN);
4391 + pid_t pid = getpid();
4392 + psetid_t pset = PS_NONE;
4393 + // Are we running in a processor set or is there any processor set around?
4394 + if (pset_bind(PS_QUERY, P_PID, pid, &pset) == 0) {
4395 + uint_t pset_cpus;
4396 + // Query the number of cpus available to us.
4397 + if (pset_info(pset, NULL, &pset_cpus, NULL) == 0) {
4398 + assert(pset_cpus > 0 && pset_cpus <= online_cpus, "sanity check");
4399 + return pset_cpus;
4402 + // Otherwise return number of online cpus
4403 + return online_cpus;
4406 +void os::set_native_thread_name(const char *name) {
4407 + if (Solaris::_pthread_setname_np != NULL) {
4408 + // Only the first 31 bytes of 'name' are processed by pthread_setname_np
4409 + // but we explicitly copy into a size-limited buffer to avoid any
4410 + // possible overflow.
4411 + char buf[32];
4412 + snprintf(buf, sizeof(buf), "%s", name);
4413 + buf[sizeof(buf) - 1] = '\0';
4414 + Solaris::_pthread_setname_np(pthread_self(), buf);
4418 +void os::init_system_properties_values() {
4419 + // The next steps are taken in the product version:
4420 + //
4421 + // Obtain the JAVA_HOME value from the location of libjvm.so.
4422 + // This library should be located at:
4423 + // <JAVA_HOME>/jre/lib/<arch>/{client|server}/libjvm.so.
4424 + //
4425 + // If "/jre/lib/" appears at the right place in the path, then we
4426 + // assume libjvm.so is installed in a JDK and we use this path.
4427 + //
4428 + // Otherwise exit with message: "Could not create the Java virtual machine."
4429 + //
4430 + // The following extra steps are taken in the debugging version:
4431 + //
4432 + // If "/jre/lib/" does NOT appear at the right place in the path
4433 + // instead of exit check for $JAVA_HOME environment variable.
4434 + //
4435 + // If it is defined and we are able to locate $JAVA_HOME/jre/lib/<arch>,
4436 + // then we append a fake suffix "hotspot/libjvm.so" to this path so
4437 + // it looks like libjvm.so is installed there
4438 + // <JAVA_HOME>/jre/lib/<arch>/hotspot/libjvm.so.
4439 + //
4440 + // Otherwise exit.
4441 + //
4442 + // Important note: if the location of libjvm.so changes this
4443 + // code needs to be changed accordingly.
4445 +// Base path of extensions installed on the system.
4446 +#define SYS_EXT_DIR "/usr/jdk/packages"
4447 +#define EXTENSIONS_DIR "/lib/ext"
4449 + // Buffer that fits several sprintfs.
4450 + // Note that the space for the colon and the trailing null are provided
4451 + // by the nulls included by the sizeof operator.
4452 + const size_t bufsize =
4453 + MAX3((size_t)MAXPATHLEN, // For dll_dir & friends.
4454 + sizeof(SYS_EXT_DIR) + sizeof("/lib/"), // invariant ld_library_path
4455 + (size_t)MAXPATHLEN + sizeof(EXTENSIONS_DIR) + sizeof(SYS_EXT_DIR) + sizeof(EXTENSIONS_DIR)); // extensions dir
4456 + char *buf = NEW_C_HEAP_ARRAY(char, bufsize, mtInternal);
4458 + // sysclasspath, java_home, dll_dir
4460 + char *pslash;
4461 + os::jvm_path(buf, bufsize);
4463 + // Found the full path to libjvm.so.
4464 + // Now cut the path to <java_home>/jre if we can.
4465 + *(strrchr(buf, '/')) = '\0'; // Get rid of /libjvm.so.
4466 + pslash = strrchr(buf, '/');
4467 + if (pslash != NULL) {
4468 + *pslash = '\0'; // Get rid of /{client|server|hotspot}.
4470 + Arguments::set_dll_dir(buf);
4472 + if (pslash != NULL) {
4473 + pslash = strrchr(buf, '/');
4474 + if (pslash != NULL) {
4475 + *pslash = '\0'; // Get rid of /lib.
4478 + Arguments::set_java_home(buf);
4479 + if (!set_boot_path('/', ':')) {
4480 + vm_exit_during_initialization("Failed setting boot class path.", NULL);
4484 + // Where to look for native libraries.
4486 + // Use dlinfo() to determine the correct java.library.path.
4487 + //
4488 + // If we're launched by the Java launcher, and the user
4489 + // does not set java.library.path explicitly on the commandline,
4490 + // the Java launcher sets LD_LIBRARY_PATH for us and unsets
4491 + // LD_LIBRARY_PATH_32 and LD_LIBRARY_PATH_64. In this case
4492 + // dlinfo returns LD_LIBRARY_PATH + crle settings (including
4493 + // /usr/lib), which is exactly what we want.
4494 + //
4495 + // If the user does set java.library.path, it completely
4496 + // overwrites this setting, and always has.
4497 + //
4498 + // If we're not launched by the Java launcher, we may
4499 + // get here with any/all of the LD_LIBRARY_PATH[_32|64]
4500 + // settings. Again, dlinfo does exactly what we want.
4502 + Dl_serinfo info_sz, *info = &info_sz;
4503 + Dl_serpath *path;
4504 + char *library_path;
4505 + char *common_path = buf;
4507 + // Determine search path count and required buffer size.
4508 + if (dlinfo(RTLD_SELF, RTLD_DI_SERINFOSIZE, (void *)info) == -1) {
4509 + FREE_C_HEAP_ARRAY(char, buf);
4510 + vm_exit_during_initialization("dlinfo SERINFOSIZE request", dlerror());
4513 + // Allocate new buffer and initialize.
4514 + info = (Dl_serinfo*)NEW_C_HEAP_ARRAY(char, info_sz.dls_size, mtInternal);
4515 + info->dls_size = info_sz.dls_size;
4516 + info->dls_cnt = info_sz.dls_cnt;
4518 + // Obtain search path information.
4519 + if (dlinfo(RTLD_SELF, RTLD_DI_SERINFO, (void *)info) == -1) {
4520 + FREE_C_HEAP_ARRAY(char, buf);
4521 + FREE_C_HEAP_ARRAY(char, info);
4522 + vm_exit_during_initialization("dlinfo SERINFO request", dlerror());
4525 + path = &info->dls_serpath[0];
4527 + // Note: Due to a legacy implementation, most of the library path
4528 + // is set in the launcher. This was to accommodate linking restrictions
4529 + // on legacy Solaris implementations (which are no longer supported).
4530 + // Eventually, all the library path setting will be done here.
4531 + //
4532 + // However, to prevent the proliferation of improperly built native
4533 + // libraries, the new path component /usr/jdk/packages is added here.
4535 + // Construct the invariant part of ld_library_path.
4536 + sprintf(common_path, SYS_EXT_DIR "/lib");
4538 + // Struct size is more than sufficient for the path components obtained
4539 + // through the dlinfo() call, so only add additional space for the path
4540 + // components explicitly added here.
4541 + size_t library_path_size = info->dls_size + strlen(common_path);
4542 + library_path = NEW_C_HEAP_ARRAY(char, library_path_size, mtInternal);
4543 + library_path[0] = '\0';
4545 + // Construct the desired Java library path from the linker's library
4546 + // search path.
4547 + //
4548 + // For compatibility, it is optimal that we insert the additional path
4549 + // components specific to the Java VM after those components specified
4550 + // in LD_LIBRARY_PATH (if any) but before those added by the ld.so
4551 + // infrastructure.
4552 + if (info->dls_cnt == 0) { // Not sure this can happen, but allow for it.
4553 + strcpy(library_path, common_path);
4554 + } else {
4555 + int inserted = 0;
4556 + uint_t i;
4557 + for (i = 0; i < info->dls_cnt; i++, path++) {
4558 + uint_t flags = path->dls_flags & LA_SER_MASK;
4559 + if (((flags & LA_SER_LIBPATH) == 0) && !inserted) {
4560 + strcat(library_path, common_path);
4561 + strcat(library_path, os::path_separator());
4562 + inserted = 1;
4564 + strcat(library_path, path->dls_name);
4565 + strcat(library_path, os::path_separator());
4567 + // Eliminate trailing path separator.
4568 + library_path[strlen(library_path)-1] = '\0';
4571 + // happens before argument parsing - can't use a trace flag
4572 + // tty->print_raw("init_system_properties_values: native lib path: ");
4573 + // tty->print_raw_cr(library_path);
4575 + // Callee copies into its own buffer.
4576 + Arguments::set_library_path(library_path);
4578 + FREE_C_HEAP_ARRAY(char, library_path);
4579 + FREE_C_HEAP_ARRAY(char, info);
4582 + // Extensions directories.
4583 + sprintf(buf, "%s" EXTENSIONS_DIR ":" SYS_EXT_DIR EXTENSIONS_DIR, Arguments::get_java_home());
4584 + Arguments::set_ext_dirs(buf);
4586 + FREE_C_HEAP_ARRAY(char, buf);
4588 +#undef SYS_EXT_DIR
4589 +#undef EXTENSIONS_DIR
4592 +static thread_t main_thread;
4594 +// Thread start routine for all newly created threads
4595 +extern "C" void* thread_native_entry(void* thread_addr) {
4597 + Thread* thread = (Thread*)thread_addr;
4599 + thread->record_stack_base_and_size();
4601 + // Try to randomize the cache line index of hot stack frames.
4602 + // This helps when threads of the same stack traces evict each other's
4603 + // cache lines. The threads can be either from the same JVM instance, or
4604 + // from different JVM instances. The benefit is especially true for
4605 + // processors with hyperthreading technology.
4606 + static int counter = 0;
4607 + int pid = os::current_process_id();
4608 + alloca(((pid ^ counter++) & 7) * 128);
4610 + int prio;
4612 + thread->initialize_thread_current();
4614 + OSThread* osthr = thread->osthread();
4616 + osthr->set_lwp_id(_lwp_self()); // Store lwp in case we are bound
4618 + log_info(os, thread)("Thread is alive (tid: " UINTX_FORMAT ").",
4619 + os::current_thread_id());
4621 + if (UseNUMA) {
4622 + int lgrp_id = os::numa_get_group_id();
4623 + if (lgrp_id != -1) {
4624 + thread->set_lgrp_id(lgrp_id);
4628 + // Our priority was set when we were created, and stored in the
4629 + // osthread, but couldn't be passed through to our LWP until now.
4630 + // So read back the priority and set it again.
4632 + if (osthr->thread_id() != -1) {
4633 + if (UseThreadPriorities) {
4634 + int prio = osthr->native_priority();
4635 + os::set_native_priority(thread, prio);
4639 + assert(osthr->get_state() == RUNNABLE, "invalid os thread state");
4641 + // initialize signal mask for this thread
4642 + PosixSignals::hotspot_sigmask(thread);
4644 + os::Solaris::init_thread_fpu_state();
4646 + thread->call_run();
4648 + // Note: at this point the thread object may already have deleted itself.
4649 + // Do not dereference it from here on out.
4651 + // One less thread is executing
4652 + // When the VMThread gets here, the main thread may have already exited
4653 + // which frees the CodeHeap containing the Atomic::dec code
4654 + if (thread != VMThread::vm_thread() && VMThread::vm_thread() != NULL) {
4655 + Atomic::dec(&os::Solaris::_os_thread_count);
4658 + log_info(os, thread)("Thread finished (tid: " UINTX_FORMAT ").", os::current_thread_id());
4660 + thr_exit(NULL);
4661 + ShouldNotReachHere();
4663 + return NULL;
4666 +static OSThread* create_os_thread(Thread* thread, thread_t thread_id) {
4667 + // Allocate the OSThread object
4668 + OSThread* osthread = new OSThread();
4669 + if (osthread == NULL) return NULL;
4671 + // Store info on the Solaris thread into the OSThread
4672 + osthread->set_thread_id(thread_id);
4673 + osthread->set_lwp_id(_lwp_self());
4675 + if (UseNUMA) {
4676 + int lgrp_id = os::numa_get_group_id();
4677 + if (lgrp_id != -1) {
4678 + thread->set_lgrp_id(lgrp_id);
4682 + // Initial thread state is INITIALIZED, not SUSPENDED
4683 + osthread->set_state(INITIALIZED);
4685 + return osthread;
4688 +bool os::create_attached_thread(JavaThread* thread) {
4689 +#ifdef ASSERT
4690 + thread->verify_not_published();
4691 +#endif
4692 + OSThread* osthread = create_os_thread(thread, thr_self());
4693 + if (osthread == NULL) {
4694 + return false;
4697 + // Initial thread state is RUNNABLE
4698 + osthread->set_state(RUNNABLE);
4699 + thread->set_osthread(osthread);
4701 + if (os::is_primordial_thread()) {
4702 + os::Solaris::correct_stack_boundaries_for_primordial_thread(thread);
4705 + // initialize signal mask for this thread
4706 + // and save the caller's signal mask
4707 + PosixSignals::hotspot_sigmask(thread);
4709 + log_info(os, thread)("Thread attached (tid: " UINTX_FORMAT ").",
4710 + os::current_thread_id());
4712 + return true;
4715 +bool os::create_main_thread(JavaThread* thread) {
4716 +#ifdef ASSERT
4717 + thread->verify_not_published();
4718 +#endif
4719 + if (_starting_thread == NULL) {
4720 + _starting_thread = create_os_thread(thread, main_thread);
4721 + if (_starting_thread == NULL) {
4722 + return false;
4726 + // The primodial thread is runnable from the start
4727 + _starting_thread->set_state(RUNNABLE);
4729 + thread->set_osthread(_starting_thread);
4731 + // initialize signal mask for this thread
4732 + // and save the caller's signal mask
4733 + PosixSignals::hotspot_sigmask(thread);
4735 + return true;
4738 +// Helper function to trace thread attributes, similar to os::Posix::describe_pthread_attr()
4739 +static char* describe_thr_create_attributes(char* buf, size_t buflen,
4740 + size_t stacksize, long flags) {
4741 + stringStream ss(buf, buflen);
4742 + ss.print("stacksize: " SIZE_FORMAT "k, ", stacksize / 1024);
4743 + ss.print("flags: ");
4744 + #define PRINT_FLAG(f) if (flags & f) ss.print( #f " ");
4745 + #define ALL(X) \
4746 + X(THR_SUSPENDED) \
4747 + X(THR_DETACHED) \
4748 + X(THR_BOUND) \
4749 + X(THR_NEW_LWP) \
4750 + X(THR_DAEMON)
4751 + ALL(PRINT_FLAG)
4752 + #undef ALL
4753 + #undef PRINT_FLAG
4754 + return buf;
4757 +// return default stack size for thr_type
4758 +size_t os::Posix::default_stack_size(os::ThreadType thr_type) {
4759 + // default stack size when not specified by caller is 1M (2M for LP64)
4760 + size_t s = (BytesPerWord >> 2) * K * K;
4761 + return s;
4764 +bool os::create_thread(Thread* thread, ThreadType thr_type,
4765 + size_t req_stack_size) {
4766 + // Allocate the OSThread object
4767 + OSThread* osthread = new OSThread();
4768 + if (osthread == NULL) {
4769 + return false;
4772 + // calculate stack size if it's not specified by caller
4773 + size_t stack_size = os::Posix::get_initial_stack_size(thr_type, req_stack_size);
4775 + // Initial state is ALLOCATED but not INITIALIZED
4776 + osthread->set_state(ALLOCATED);
4778 + if (os::Solaris::_os_thread_count > os::Solaris::_os_thread_limit) {
4779 + // We got lots of threads. Check if we still have some address space left.
4780 + // Need to be at least 5Mb of unreserved address space. We do check by
4781 + // trying to reserve some.
4782 + const size_t VirtualMemoryBangSize = 20*K*K;
4783 + char* mem = os::reserve_memory(VirtualMemoryBangSize);
4784 + if (mem == NULL) {
4785 + delete osthread;
4786 + return false;
4787 + } else {
4788 + // Release the memory again
4789 + os::release_memory(mem, VirtualMemoryBangSize);
4793 + // Setup osthread because the child thread may need it.
4794 + thread->set_osthread(osthread);
4796 + // Create the Solaris thread
4797 + thread_t tid = 0;
4798 + long flags = THR_DETACHED | THR_SUSPENDED;
4799 + int status;
4801 + // Mark that we don't have an lwp or thread id yet.
4802 + // In case we attempt to set the priority before the thread starts.
4803 + osthread->set_lwp_id(-1);
4804 + osthread->set_thread_id(-1);
4806 + status = thr_create(NULL, stack_size, thread_native_entry, thread, flags, &tid);
4808 + char buf[64];
4809 + if (status == 0) {
4810 + log_info(os, thread)("Thread \"%s\" started (tid: " UINTX_FORMAT ", attributes: %s). ",
4811 + thread->name(), (uintx) tid, describe_thr_create_attributes(buf, sizeof(buf), stack_size, flags));
4812 + } else {
4813 + log_warning(os, thread)("Failed to start thread \"%s\" - thr_create failed (%s) for attributes: %s.",
4814 + thread->name(), os::errno_name(status), describe_thr_create_attributes(buf, sizeof(buf), stack_size, flags));
4815 + // Log some OS information which might explain why creating the thread failed.
4816 + log_info(os, thread)("Number of threads approx. running in the VM: %d", Threads::number_of_threads());
4817 + LogStream st(Log(os, thread)::info());
4818 + os::Posix::print_rlimit_info(&st);
4819 + os::print_memory_info(&st);
4822 + if (status != 0) {
4823 + thread->set_osthread(NULL);
4824 + // Need to clean up stuff we've allocated so far
4825 + delete osthread;
4826 + return false;
4829 + Atomic::inc(&os::Solaris::_os_thread_count);
4831 + // Store info on the Solaris thread into the OSThread
4832 + osthread->set_thread_id(tid);
4834 + // Remember that we created this thread so we can set priority on it
4835 + osthread->set_vm_created();
4837 + // Most thread types will set an explicit priority before starting the thread,
4838 + // but for those that don't we need a valid value to read back in thread_native_entry.
4839 + osthread->set_native_priority(NormPriority);
4841 + // Initial thread state is INITIALIZED, not SUSPENDED
4842 + osthread->set_state(INITIALIZED);
4844 + // The thread is returned suspended (in state INITIALIZED), and is started higher up in the call chain
4845 + return true;
4848 +// CR 7190089: on Solaris, primordial thread's stack needs adjusting.
4849 +// Without the adjustment, stack size is incorrect if stack is set to unlimited (ulimit -s unlimited).
4850 +void os::Solaris::correct_stack_boundaries_for_primordial_thread(Thread* thr) {
4851 + assert(is_primordial_thread(), "Call only for primordial thread");
4853 + JavaThread* jt = (JavaThread *)thr;
4854 + assert(jt != NULL, "Sanity check");
4855 + size_t stack_size;
4856 + address base = jt->stack_base();
4857 + if (Arguments::created_by_java_launcher()) {
4858 + // Use 2MB to allow for Solaris 7 64 bit mode.
4859 + stack_size = JavaThread::stack_size_at_create() == 0
4860 + ? 2048*K : JavaThread::stack_size_at_create();
4862 + // There are rare cases when we may have already used more than
4863 + // the basic stack size allotment before this method is invoked.
4864 + // Attempt to allow for a normally sized java_stack.
4865 + size_t current_stack_offset = (size_t)(base - (address)&stack_size);
4866 + stack_size += ReservedSpace::page_align_size_down(current_stack_offset);
4867 + } else {
4868 + // 6269555: If we were not created by a Java launcher, i.e. if we are
4869 + // running embedded in a native application, treat the primordial thread
4870 + // as much like a native attached thread as possible. This means using
4871 + // the current stack size from thr_stksegment(), unless it is too large
4872 + // to reliably setup guard pages. A reasonable max size is 8MB.
4873 + size_t current_size = os::current_stack_size();
4874 + // This should never happen, but just in case....
4875 + if (current_size == 0) current_size = 2 * K * K;
4876 + stack_size = current_size > (8 * K * K) ? (8 * K * K) : current_size;
4878 + address bottom = align_up(base - stack_size, os::vm_page_size());;
4879 + stack_size = (size_t)(base - bottom);
4881 + assert(stack_size > 0, "Stack size calculation problem");
4883 + if (stack_size > jt->stack_size()) {
4884 +#ifndef PRODUCT
4885 + struct rlimit limits;
4886 + getrlimit(RLIMIT_STACK, &limits);
4887 + size_t size = adjust_stack_size(base, (size_t)limits.rlim_cur);
4888 + assert(size >= jt->stack_size(), "Stack size problem in main thread");
4889 +#endif
4890 + tty->print_cr("Stack size of " SIZE_FORMAT " Kb exceeds current limit of " SIZE_FORMAT " Kb.\n"
4891 + "(Stack sizes are rounded up to a multiple of the system page size.)\n"
4892 + "See limit(1) to increase the stack size limit.",
4893 + stack_size / K, jt->stack_size() / K);
4894 + vm_exit(1);
4896 + assert(jt->stack_size() >= stack_size,
4897 + "Attempt to map more stack than was allocated");
4898 + jt->set_stack_size(stack_size);
4904 +// Free Solaris resources related to the OSThread
4905 +void os::free_thread(OSThread* osthread) {
4906 + assert(osthread != NULL, "os::free_thread but osthread not set");
4908 + // We are told to free resources of the argument thread,
4909 + // but we can only really operate on the current thread.
4910 + assert(Thread::current()->osthread() == osthread,
4911 + "os::free_thread but not current thread");
4913 + // Restore caller's signal mask
4914 + sigset_t sigmask = osthread->caller_sigmask();
4915 + pthread_sigmask(SIG_SETMASK, &sigmask, NULL);
4917 + delete osthread;
4920 +void os::pd_start_thread(Thread* thread) {
4921 + int status = thr_continue(thread->osthread()->thread_id());
4922 + assert_status(status == 0, status, "thr_continue failed");
4926 +intx os::current_thread_id() {
4927 + return (intx)thr_self();
4930 +static pid_t _initial_pid = 0;
4932 +int os::current_process_id() {
4933 + return (int)(_initial_pid ? _initial_pid : getpid());
4936 +// gethrtime() should be monotonic according to the documentation,
4937 +// but some virtualized platforms are known to break this guarantee.
4938 +// getTimeNanos() must be guaranteed not to move backwards, so we
4939 +// are forced to add a check here.
4940 +inline hrtime_t getTimeNanos() {
4941 + const hrtime_t now = gethrtime();
4942 + const hrtime_t prev = max_hrtime;
4943 + if (now <= prev) {
4944 + return prev; // same or retrograde time;
4946 + const hrtime_t obsv = Atomic::cmpxchg(&max_hrtime, prev, now);
4947 + assert(obsv >= prev, "invariant"); // Monotonicity
4948 + // If the CAS succeeded then we're done and return "now".
4949 + // If the CAS failed and the observed value "obsv" is >= now then
4950 + // we should return "obsv". If the CAS failed and now > obsv > prv then
4951 + // some other thread raced this thread and installed a new value, in which case
4952 + // we could either (a) retry the entire operation, (b) retry trying to install now
4953 + // or (c) just return obsv. We use (c). No loop is required although in some cases
4954 + // we might discard a higher "now" value in deference to a slightly lower but freshly
4955 + // installed obsv value. That's entirely benign -- it admits no new orderings compared
4956 + // to (a) or (b) -- and greatly reduces coherence traffic.
4957 + // We might also condition (c) on the magnitude of the delta between obsv and now.
4958 + // Avoiding excessive CAS operations to hot RW locations is critical.
4959 + // See https://blogs.oracle.com/dave/entry/cas_and_cache_trivia_invalidate
4960 + return (prev == obsv) ? now : obsv;
4963 +double os::elapsedVTime() {
4964 + return (double)gethrvtime() / (double)hrtime_hz;
4967 +// DLL functions
4969 +// This must be hard coded because it's the system's temporary
4970 +// directory not the java application's temp directory, ala java.io.tmpdir.
4971 +const char* os::get_temp_directory() { return "/tmp"; }
4973 +// check if addr is inside libjvm.so
4974 +bool os::address_is_in_vm(address addr) {
4975 + static address libjvm_base_addr;
4976 + Dl_info dlinfo;
4978 + if (libjvm_base_addr == NULL) {
4979 + if (dladdr(CAST_FROM_FN_PTR(void *, os::address_is_in_vm), &dlinfo) != 0) {
4980 + libjvm_base_addr = (address)dlinfo.dli_fbase;
4982 + assert(libjvm_base_addr !=NULL, "Cannot obtain base address for libjvm");
4985 + if (dladdr((void *)addr, &dlinfo) != 0) {
4986 + if (libjvm_base_addr == (address)dlinfo.dli_fbase) return true;
4989 + return false;
4992 +void os::prepare_native_symbols() {
4995 +typedef int (*dladdr1_func_type)(void *, Dl_info *, void **, int);
4996 +static dladdr1_func_type dladdr1_func = NULL;
4998 +bool os::dll_address_to_function_name(address addr, char *buf,
4999 + int buflen, int * offset,
5000 + bool demangle) {
5001 + // buf is not optional, but offset is optional
5002 + assert(buf != NULL, "sanity check");
5004 + Dl_info dlinfo;
5006 + // dladdr1_func was initialized in os::init()
5007 + if (dladdr1_func != NULL) {
5008 + // yes, we have dladdr1
5010 + // Support for dladdr1 is checked at runtime; it may be
5011 + // available even if the vm is built on a machine that does
5012 + // not have dladdr1 support. Make sure there is a value for
5013 + // RTLD_DL_SYMENT.
5014 +#ifndef RTLD_DL_SYMENT
5015 + #define RTLD_DL_SYMENT 1
5016 +#endif
5017 +#ifdef _LP64
5018 + Elf64_Sym * info;
5019 +#else
5020 + Elf32_Sym * info;
5021 +#endif
5022 + if (dladdr1_func((void *)addr, &dlinfo, (void **)&info,
5023 + RTLD_DL_SYMENT) != 0) {
5024 + // see if we have a matching symbol that covers our address
5025 + if (dlinfo.dli_saddr != NULL &&
5026 + (char *)dlinfo.dli_saddr + info->st_size > (char *)addr) {
5027 + if (dlinfo.dli_sname != NULL) {
5028 + if (!(demangle && Decoder::demangle(dlinfo.dli_sname, buf, buflen))) {
5029 + jio_snprintf(buf, buflen, "%s", dlinfo.dli_sname);
5031 + if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr;
5032 + return true;
5035 + // no matching symbol so try for just file info
5036 + if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != NULL) {
5037 + if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
5038 + buf, buflen, offset, dlinfo.dli_fname, demangle)) {
5039 + return true;
5043 + buf[0] = '\0';
5044 + if (offset != NULL) *offset = -1;
5045 + return false;
5048 + // no, only dladdr is available
5049 + if (dladdr((void *)addr, &dlinfo) != 0) {
5050 + // see if we have a matching symbol
5051 + if (dlinfo.dli_saddr != NULL && dlinfo.dli_sname != NULL) {
5052 + if (!(demangle && Decoder::demangle(dlinfo.dli_sname, buf, buflen))) {
5053 + jio_snprintf(buf, buflen, dlinfo.dli_sname);
5055 + if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr;
5056 + return true;
5058 + // no matching symbol so try for just file info
5059 + if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != NULL) {
5060 + if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
5061 + buf, buflen, offset, dlinfo.dli_fname, demangle)) {
5062 + return true;
5066 + buf[0] = '\0';
5067 + if (offset != NULL) *offset = -1;
5068 + return false;
5071 +bool os::dll_address_to_library_name(address addr, char* buf,
5072 + int buflen, int* offset) {
5073 + // buf is not optional, but offset is optional
5074 + assert(buf != NULL, "sanity check");
5076 + Dl_info dlinfo;
5078 + if (dladdr((void*)addr, &dlinfo) != 0) {
5079 + if (dlinfo.dli_fname != NULL) {
5080 + jio_snprintf(buf, buflen, "%s", dlinfo.dli_fname);
5082 + if (dlinfo.dli_fbase != NULL && offset != NULL) {
5083 + *offset = addr - (address)dlinfo.dli_fbase;
5085 + return true;
5088 + buf[0] = '\0';
5089 + if (offset) *offset = -1;
5090 + return false;
5093 +int os::get_loaded_modules_info(os::LoadedModulesCallbackFunc callback, void *param) {
5094 + Dl_info dli;
5095 + // Sanity check?
5096 + if (dladdr(CAST_FROM_FN_PTR(void *, os::get_loaded_modules_info), &dli) == 0 ||
5097 + dli.dli_fname == NULL) {
5098 + return 1;
5101 + void * handle = dlopen(dli.dli_fname, RTLD_LAZY);
5102 + if (handle == NULL) {
5103 + return 1;
5106 + Link_map *map;
5107 + dlinfo(handle, RTLD_DI_LINKMAP, &map);
5108 + if (map == NULL) {
5109 + dlclose(handle);
5110 + return 1;
5113 + while (map->l_prev != NULL) {
5114 + map = map->l_prev;
5117 + while (map != NULL) {
5118 + // Iterate through all map entries and call callback with fields of interest
5119 + if(callback(map->l_name, (address)map->l_addr, (address)0, param)) {
5120 + dlclose(handle);
5121 + return 1;
5123 + map = map->l_next;
5126 + dlclose(handle);
5127 + return 0;
5130 +int _print_dll_info_cb(const char * name, address base_address, address top_address, void * param) {
5131 + outputStream * out = (outputStream *) param;
5132 + out->print_cr(INTPTR_FORMAT " \t%s", (intptr_t)base_address, name);
5133 + return 0;
5136 +void os::print_dll_info(outputStream * st) {
5137 + st->print_cr("Dynamic libraries:"); st->flush();
5138 + if (get_loaded_modules_info(_print_dll_info_cb, (void *)st)) {
5139 + st->print_cr("Error: Cannot print dynamic libraries.");
5143 +static void change_endianness(Elf32_Half& val) {
5144 + unsigned char *ptr = (unsigned char *)&val;
5145 + unsigned char swp = ptr[0];
5146 + ptr[0] = ptr[1];
5147 + ptr[1] = swp;
5150 +// Loads .dll/.so and
5151 +// in case of error it checks if .dll/.so was built for the
5152 +// same architecture as Hotspot is running on
5154 +void * os::dll_load(const char *filename, char *ebuf, int ebuflen) {
5155 + log_info(os)("attempting shared library load of %s", filename);
5157 + void * result= ::dlopen(filename, RTLD_LAZY);
5158 + if (result != NULL) {
5159 + // Successful loading
5160 + Events::log(NULL, "Loaded shared library %s", filename);
5161 + log_info(os)("shared library load of %s was successful", filename);
5162 + return result;
5165 + Elf32_Ehdr elf_head;
5166 + const char* error_report = ::dlerror();
5167 + if (error_report == NULL) {
5168 + error_report = "dlerror returned no error description";
5170 + if (ebuf != NULL && ebuflen > 0) {
5171 + ::strncpy(ebuf, error_report, ebuflen-1);
5172 + ebuf[ebuflen-1]='\0';
5175 + Events::log(NULL, "Loading shared library %s failed, %s", filename, error_report);
5176 + log_info(os)("shared library load of %s failed, %s", filename, error_report);
5178 + int diag_msg_max_length=ebuflen-strlen(ebuf);
5179 + char* diag_msg_buf=ebuf+strlen(ebuf);
5181 + if (diag_msg_max_length==0) {
5182 + // No more space in ebuf for additional diagnostics message
5183 + return NULL;
5187 + int file_descriptor= ::open(filename, O_RDONLY | O_NONBLOCK);
5189 + if (file_descriptor < 0) {
5190 + // Can't open library, report dlerror() message
5191 + return NULL;
5194 + bool failed_to_read_elf_head=
5195 + (sizeof(elf_head)!=
5196 + (::read(file_descriptor, &elf_head,sizeof(elf_head))));
5198 + ::close(file_descriptor);
5199 + if (failed_to_read_elf_head) {
5200 + // file i/o error - report dlerror() msg
5201 + return NULL;
5204 + if (elf_head.e_ident[EI_DATA] != LITTLE_ENDIAN_ONLY(ELFDATA2LSB) BIG_ENDIAN_ONLY(ELFDATA2MSB)) {
5205 + // handle invalid/out of range endianness values
5206 + if (elf_head.e_ident[EI_DATA] == 0 || elf_head.e_ident[EI_DATA] > 2) {
5207 + return NULL;
5209 + change_endianness(elf_head.e_machine);
5212 + typedef struct {
5213 + Elf32_Half code; // Actual value as defined in elf.h
5214 + Elf32_Half compat_class; // Compatibility of archs at VM's sense
5215 + unsigned char elf_class; // 32 or 64 bit
5216 + unsigned char endianess; // MSB or LSB
5217 + char* name; // String representation
5218 + } arch_t;
5220 + static const arch_t arch_array[]={
5221 + {EM_386, EM_386, ELFCLASS32, ELFDATA2LSB, (char*)"IA 32"},
5222 + {EM_486, EM_386, ELFCLASS32, ELFDATA2LSB, (char*)"IA 32"},
5223 + {EM_IA_64, EM_IA_64, ELFCLASS64, ELFDATA2LSB, (char*)"IA 64"},
5224 + {EM_X86_64, EM_X86_64, ELFCLASS64, ELFDATA2LSB, (char*)"AMD 64"},
5225 + {EM_SPARC, EM_SPARC, ELFCLASS32, ELFDATA2MSB, (char*)"Sparc 32"},
5226 + {EM_SPARC32PLUS, EM_SPARC, ELFCLASS32, ELFDATA2MSB, (char*)"Sparc 32"},
5227 + {EM_SPARCV9, EM_SPARCV9, ELFCLASS64, ELFDATA2MSB, (char*)"Sparc v9 64"},
5228 + {EM_PPC, EM_PPC, ELFCLASS32, ELFDATA2MSB, (char*)"Power PC 32"},
5229 + {EM_PPC64, EM_PPC64, ELFCLASS64, ELFDATA2MSB, (char*)"Power PC 64"},
5230 + {EM_ARM, EM_ARM, ELFCLASS32, ELFDATA2LSB, (char*)"ARM"},
5231 + // we only support 64 bit z architecture
5232 + {EM_S390, EM_S390, ELFCLASS64, ELFDATA2MSB, (char*)"IBM System/390"},
5233 + {EM_AARCH64, EM_AARCH64, ELFCLASS64, ELFDATA2LSB, (char*)"AARCH64"}
5234 + };
5236 +#if (defined IA32)
5237 + static Elf32_Half running_arch_code=EM_386;
5238 +#elif (defined AMD64)
5239 + static Elf32_Half running_arch_code=EM_X86_64;
5240 +#elif (defined IA64)
5241 + static Elf32_Half running_arch_code=EM_IA_64;
5242 +#elif (defined __sparc) && (defined _LP64)
5243 + static Elf32_Half running_arch_code=EM_SPARCV9;
5244 +#elif (defined __sparc) && (!defined _LP64)
5245 + static Elf32_Half running_arch_code=EM_SPARC;
5246 +#elif (defined __powerpc64__)
5247 + static Elf32_Half running_arch_code=EM_PPC64;
5248 +#elif (defined __powerpc__)
5249 + static Elf32_Half running_arch_code=EM_PPC;
5250 +#elif (defined ARM)
5251 + static Elf32_Half running_arch_code=EM_ARM;
5252 +#else
5253 + #error Method os::dll_load requires that one of following is defined:\
5254 + IA32, AMD64, IA64, __sparc, __powerpc__, ARM, ARM
5255 +#endif
5257 + // Identify compatibility class for VM's architecture and library's architecture
5258 + // Obtain string descriptions for architectures
5260 + arch_t lib_arch={elf_head.e_machine,0,elf_head.e_ident[EI_CLASS], elf_head.e_ident[EI_DATA], NULL};
5261 + int running_arch_index=-1;
5263 + for (unsigned int i=0; i < ARRAY_SIZE(arch_array); i++) {
5264 + if (running_arch_code == arch_array[i].code) {
5265 + running_arch_index = i;
5267 + if (lib_arch.code == arch_array[i].code) {
5268 + lib_arch.compat_class = arch_array[i].compat_class;
5269 + lib_arch.name = arch_array[i].name;
5273 + assert(running_arch_index != -1,
5274 + "Didn't find running architecture code (running_arch_code) in arch_array");
5275 + if (running_arch_index == -1) {
5276 + // Even though running architecture detection failed
5277 + // we may still continue with reporting dlerror() message
5278 + return NULL;
5281 + if (lib_arch.compat_class != arch_array[running_arch_index].compat_class) {
5282 + if (lib_arch.name != NULL) {
5283 + ::snprintf(diag_msg_buf, diag_msg_max_length-1,
5284 + " (Possible cause: can't load %s .so on a %s platform)",
5285 + lib_arch.name, arch_array[running_arch_index].name);
5286 + } else {
5287 + ::snprintf(diag_msg_buf, diag_msg_max_length-1,
5288 + " (Possible cause: can't load this .so (machine code=0x%x) on a %s platform)",
5289 + lib_arch.code, arch_array[running_arch_index].name);
5291 + return NULL;
5294 + if (lib_arch.endianess != arch_array[running_arch_index].endianess) {
5295 + ::snprintf(diag_msg_buf, diag_msg_max_length-1," (Possible cause: endianness mismatch)");
5296 + return NULL;
5299 + // ELF file class/capacity : 0 - invalid, 1 - 32bit, 2 - 64bit
5300 + if (lib_arch.elf_class > 2 || lib_arch.elf_class < 1) {
5301 + ::snprintf(diag_msg_buf, diag_msg_max_length-1, " (Possible cause: invalid ELF file class)");
5302 + return NULL;
5305 + if (lib_arch.elf_class != arch_array[running_arch_index].elf_class) {
5306 + ::snprintf(diag_msg_buf, diag_msg_max_length-1,
5307 + " (Possible cause: architecture word width mismatch, can't load %d-bit .so on a %d-bit platform)",
5308 + (int) lib_arch.elf_class * 32, arch_array[running_arch_index].elf_class * 32);
5309 + return NULL;
5312 + return NULL;
5315 +static inline time_t get_mtime(const char* filename) {
5316 + struct stat st;
5317 + int ret = os::stat(filename, &st);
5318 + assert(ret == 0, "failed to stat() file '%s': %s", filename, os::strerror(errno));
5319 + return st.st_mtime;
5322 +int os::compare_file_modified_times(const char* file1, const char* file2) {
5323 + time_t t1 = get_mtime(file1);
5324 + time_t t2 = get_mtime(file2);
5325 + return t1 - t2;
5328 +static bool _print_ascii_file(const char* filename, outputStream* st) {
5329 + int fd = ::open(filename, O_RDONLY);
5330 + if (fd == -1) {
5331 + return false;
5334 + char buf[32];
5335 + int bytes;
5336 + while ((bytes = ::read(fd, buf, sizeof(buf))) > 0) {
5337 + st->print_raw(buf, bytes);
5340 + ::close(fd);
5342 + return true;
5345 +void os::print_os_info_brief(outputStream* st) {
5346 + os::Solaris::print_distro_info(st);
5348 + os::Posix::print_uname_info(st);
5350 + os::Solaris::print_libversion_info(st);
5353 +void os::print_os_info(outputStream* st) {
5354 + st->print("OS:");
5356 + os::Solaris::print_distro_info(st);
5358 + os::Posix::print_uname_info(st);
5360 + os::Posix::print_uptime_info(st);
5362 + os::Solaris::print_libversion_info(st);
5364 + os::Posix::print_rlimit_info(st);
5366 + os::Posix::print_load_average(st);
5369 +void os::Solaris::print_distro_info(outputStream* st) {
5370 + if (!_print_ascii_file("/etc/release", st)) {
5371 + st->print("Solaris");
5373 + st->cr();
5376 +void os::get_summary_os_info(char* buf, size_t buflen) {
5377 + strncpy(buf, "Solaris", buflen); // default to plain solaris
5378 + FILE* fp = fopen("/etc/release", "r");
5379 + if (fp != NULL) {
5380 + char tmp[256];
5381 + // Only get the first line and chop out everything but the os name.
5382 + if (fgets(tmp, sizeof(tmp), fp)) {
5383 + char* ptr = tmp;
5384 + // skip past whitespace characters
5385 + while (*ptr != '\0' && (*ptr == ' ' || *ptr == '\t' || *ptr == '\n')) ptr++;
5386 + if (*ptr != '\0') {
5387 + char* nl = strchr(ptr, '\n');
5388 + if (nl != NULL) *nl = '\0';
5389 + strncpy(buf, ptr, buflen);
5392 + fclose(fp);
5396 +void os::Solaris::print_libversion_info(outputStream* st) {
5397 + st->print(" (T2 libthread)");
5398 + st->cr();
5401 +static bool check_addr0(outputStream* st) {
5402 + jboolean status = false;
5403 + const int read_chunk = 200;
5404 + int ret = 0;
5405 + int nmap = 0;
5406 + int fd = ::open("/proc/self/map",O_RDONLY);
5407 + if (fd >= 0) {
5408 + prmap_t *p = NULL;
5409 + char *mbuff = (char *) calloc(read_chunk, sizeof(prmap_t));
5410 + if (NULL == mbuff) {
5411 + ::close(fd);
5412 + return status;
5414 + while ((ret = ::read(fd, mbuff, read_chunk*sizeof(prmap_t))) > 0) {
5415 + //check if read() has not read partial data
5416 + if( 0 != ret % sizeof(prmap_t)){
5417 + break;
5419 + nmap = ret / sizeof(prmap_t);
5420 + p = (prmap_t *)mbuff;
5421 + for(int i = 0; i < nmap; i++){
5422 + if (p->pr_vaddr == 0x0) {
5423 + st->print("Warning: Address: " PTR_FORMAT ", Size: " SIZE_FORMAT "K, ",p->pr_vaddr, p->pr_size/1024);
5424 + st->print("Mapped file: %s, ", p->pr_mapname[0] == '\0' ? "None" : p->pr_mapname);
5425 + st->print("Access: ");
5426 + st->print("%s",(p->pr_mflags & MA_READ) ? "r" : "-");
5427 + st->print("%s",(p->pr_mflags & MA_WRITE) ? "w" : "-");
5428 + st->print("%s",(p->pr_mflags & MA_EXEC) ? "x" : "-");
5429 + st->cr();
5430 + status = true;
5432 + p++;
5435 + free(mbuff);
5436 + ::close(fd);
5438 + return status;
5441 +void os::get_summary_cpu_info(char* buf, size_t buflen) {
5442 + // Get MHz with system call. We don't seem to already have this.
5443 + processor_info_t stats;
5444 + processorid_t id = getcpuid();
5445 + int clock = 0;
5446 + if (processor_info(id, &stats) != -1) {
5447 + clock = stats.pi_clock; // pi_processor_type isn't more informative than below
5449 + snprintf(buf, buflen, "64 bit %d MHz", clock);
5452 +void os::pd_print_cpu_info(outputStream* st, char* buf, size_t buflen) {
5453 + // Nothing to do for now.
5456 +void os::print_memory_info(outputStream* st) {
5457 + st->print("Memory:");
5458 + st->print(" %dk page", os::vm_page_size()>>10);
5459 + st->print(", physical " UINT64_FORMAT "k", os::physical_memory()>>10);
5460 + st->print("(" UINT64_FORMAT "k free)", os::available_memory() >> 10);
5461 + st->cr();
5462 + (void) check_addr0(st);
5465 +static int Maxsignum = 0;
5467 +static char saved_jvm_path[MAXPATHLEN] = { 0 };
5469 +// Find the full path to the current module, libjvm.so
5470 +void os::jvm_path(char *buf, jint buflen) {
5471 + // Error checking.
5472 + if (buflen < MAXPATHLEN) {
5473 + assert(false, "must use a large-enough buffer");
5474 + buf[0] = '\0';
5475 + return;
5477 + // Lazy resolve the path to current module.
5478 + if (saved_jvm_path[0] != 0) {
5479 + strcpy(buf, saved_jvm_path);
5480 + return;
5483 + Dl_info dlinfo;
5484 + int ret = dladdr(CAST_FROM_FN_PTR(void *, os::jvm_path), &dlinfo);
5485 + assert(ret != 0, "cannot locate libjvm");
5486 + if (ret != 0 && dlinfo.dli_fname != NULL) {
5487 + if (os::Posix::realpath((char *)dlinfo.dli_fname, buf, buflen) == NULL) {
5488 + return;
5490 + } else {
5491 + buf[0] = '\0';
5492 + return;
5495 + if (Arguments::sun_java_launcher_is_altjvm()) {
5496 + // Support for the java launcher's '-XXaltjvm=<path>' option. Typical
5497 + // value for buf is "<JAVA_HOME>/jre/lib/<arch>/<vmtype>/libjvm.so".
5498 + // If "/jre/lib/" appears at the right place in the string, then
5499 + // assume we are installed in a JDK and we're done. Otherwise, check
5500 + // for a JAVA_HOME environment variable and fix up the path so it
5501 + // looks like libjvm.so is installed there (append a fake suffix
5502 + // hotspot/libjvm.so).
5503 + const char *p = buf + strlen(buf) - 1;
5504 + for (int count = 0; p > buf && count < 5; ++count) {
5505 + for (--p; p > buf && *p != '/'; --p)
5506 + /* empty */ ;
5509 + if (strncmp(p, "/jre/lib/", 9) != 0) {
5510 + // Look for JAVA_HOME in the environment.
5511 + char* java_home_var = ::getenv("JAVA_HOME");
5512 + if (java_home_var != NULL && java_home_var[0] != 0) {
5513 + char* jrelib_p;
5514 + int len;
5516 + // Check the current module name "libjvm.so".
5517 + p = strrchr(buf, '/');
5518 + assert(strstr(p, "/libjvm") == p, "invalid library name");
5520 + if (os::Posix::realpath(java_home_var, buf, buflen) == NULL) {
5521 + return;
5523 + // determine if this is a legacy image or modules image
5524 + // modules image doesn't have "jre" subdirectory
5525 + len = strlen(buf);
5526 + assert(len < buflen, "Ran out of buffer space");
5527 + jrelib_p = buf + len;
5528 + snprintf(jrelib_p, buflen-len, "/jre/lib");
5529 + if (0 != access(buf, F_OK)) {
5530 + snprintf(jrelib_p, buflen-len, "/lib");
5533 + if (0 == access(buf, F_OK)) {
5534 + // Use current module name "libjvm.so"
5535 + len = strlen(buf);
5536 + snprintf(buf + len, buflen-len, "/hotspot/libjvm.so");
5537 + } else {
5538 + // Go back to path of .so
5539 + if (os::Posix::realpath((char *)dlinfo.dli_fname, buf, buflen) == NULL) {
5540 + return;
5547 + strncpy(saved_jvm_path, buf, MAXPATHLEN);
5548 + saved_jvm_path[MAXPATHLEN - 1] = '\0';
5551 +////////////////////////////////////////////////////////////////////////////////
5552 +// Virtual Memory
5554 +static bool recoverable_mmap_error(int err) {
5555 + // See if the error is one we can let the caller handle. This
5556 + // list of errno values comes from the Solaris mmap(2) man page.
5557 + switch (err) {
5558 + case EBADF:
5559 + case EINVAL:
5560 + case ENOTSUP:
5561 + // let the caller deal with these errors
5562 + return true;
5564 + default:
5565 + // Any remaining errors on this OS can cause our reserved mapping
5566 + // to be lost. That can cause confusion where different data
5567 + // structures think they have the same memory mapped. The worst
5568 + // scenario is if both the VM and a library think they have the
5569 + // same memory mapped.
5570 + return false;
5574 +static void warn_fail_commit_memory(char* addr, size_t bytes, bool exec,
5575 + int err) {
5576 + warning("INFO: os::commit_memory(" PTR_FORMAT ", " SIZE_FORMAT
5577 + ", %d) failed; error='%s' (errno=%d)", p2i(addr), bytes, exec,
5578 + os::strerror(err), err);
5581 +static void warn_fail_commit_memory(char* addr, size_t bytes,
5582 + size_t alignment_hint, bool exec,
5583 + int err) {
5584 + warning("INFO: os::commit_memory(" PTR_FORMAT ", " SIZE_FORMAT
5585 + ", " SIZE_FORMAT ", %d) failed; error='%s' (errno=%d)", p2i(addr),
5586 + bytes, alignment_hint, exec, os::strerror(err), err);
5589 +int os::Solaris::commit_memory_impl(char* addr, size_t bytes, bool exec) {
5590 + int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE;
5591 + size_t size = bytes;
5592 + char *res = Solaris::mmap_chunk(addr, size, MAP_PRIVATE|MAP_FIXED, prot);
5593 + if (res != NULL) {
5594 + if (UseNUMAInterleaving) {
5595 + numa_make_global(addr, bytes);
5597 + return 0;
5600 + int err = errno; // save errno from mmap() call in mmap_chunk()
5602 + if (!recoverable_mmap_error(err)) {
5603 + warn_fail_commit_memory(addr, bytes, exec, err);
5604 + vm_exit_out_of_memory(bytes, OOM_MMAP_ERROR, "committing reserved memory.");
5607 + return err;
5610 +bool os::pd_commit_memory(char* addr, size_t bytes, bool exec) {
5611 + return Solaris::commit_memory_impl(addr, bytes, exec) == 0;
5614 +void os::pd_commit_memory_or_exit(char* addr, size_t bytes, bool exec,
5615 + const char* mesg) {
5616 + assert(mesg != NULL, "mesg must be specified");
5617 + int err = os::Solaris::commit_memory_impl(addr, bytes, exec);
5618 + if (err != 0) {
5619 + // the caller wants all commit errors to exit with the specified mesg:
5620 + warn_fail_commit_memory(addr, bytes, exec, err);
5621 + vm_exit_out_of_memory(bytes, OOM_MMAP_ERROR, "%s", mesg);
5625 +size_t os::Solaris::page_size_for_alignment(size_t alignment) {
5626 + assert(is_aligned(alignment, (size_t) os::vm_page_size()),
5627 + SIZE_FORMAT " is not aligned to " SIZE_FORMAT,
5628 + alignment, (size_t) os::vm_page_size());
5630 + int page_sizes_max = 9;
5631 + size_t _illumos_page_sizes[page_sizes_max];
5632 + int n = getpagesizes(_illumos_page_sizes, page_sizes_max);
5633 + for (int i = 0; _illumos_page_sizes[i] != 0; i++) {
5634 + if (is_aligned(alignment, _illumos_page_sizes[i])) {
5635 + return _illumos_page_sizes[i];
5639 + return (size_t) os::vm_page_size();
5642 +int os::Solaris::commit_memory_impl(char* addr, size_t bytes,
5643 + size_t alignment_hint, bool exec) {
5644 + int err = Solaris::commit_memory_impl(addr, bytes, exec);
5645 + if (err == 0 && UseLargePages && alignment_hint > 0) {
5646 + assert(is_aligned(bytes, alignment_hint),
5647 + SIZE_FORMAT " is not aligned to " SIZE_FORMAT, bytes, alignment_hint);
5649 + // The syscall memcntl requires an exact page size (see man memcntl for details).
5650 + size_t page_size = page_size_for_alignment(alignment_hint);
5651 + if (page_size > (size_t) os::vm_page_size()) {
5652 + (void)Solaris::setup_large_pages(addr, bytes, page_size);
5655 + return err;
5658 +bool os::pd_commit_memory(char* addr, size_t bytes, size_t alignment_hint,
5659 + bool exec) {
5660 + return Solaris::commit_memory_impl(addr, bytes, alignment_hint, exec) == 0;
5663 +void os::pd_commit_memory_or_exit(char* addr, size_t bytes,
5664 + size_t alignment_hint, bool exec,
5665 + const char* mesg) {
5666 + assert(mesg != NULL, "mesg must be specified");
5667 + int err = os::Solaris::commit_memory_impl(addr, bytes, alignment_hint, exec);
5668 + if (err != 0) {
5669 + // the caller wants all commit errors to exit with the specified mesg:
5670 + warn_fail_commit_memory(addr, bytes, alignment_hint, exec, err);
5671 + vm_exit_out_of_memory(bytes, OOM_MMAP_ERROR, "%s", mesg);
5675 +// Uncommit the pages in a specified region.
5676 +void os::pd_free_memory(char* addr, size_t bytes, size_t alignment_hint) {
5677 + if (posix_madvise(addr, bytes, MADV_FREE) < 0) {
5678 + debug_only(warning("MADV_FREE failed."));
5679 + return;
5683 +bool os::pd_create_stack_guard_pages(char* addr, size_t size) {
5684 + return os::commit_memory(addr, size, !ExecMem);
5687 +bool os::remove_stack_guard_pages(char* addr, size_t size) {
5688 + return os::uncommit_memory(addr, size);
5691 +// Change the page size in a given range.
5692 +void os::pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint) {
5693 + assert((intptr_t)addr % alignment_hint == 0, "Address should be aligned.");
5694 + assert((intptr_t)(addr + bytes) % alignment_hint == 0, "End should be aligned.");
5695 + if (UseLargePages) {
5696 + size_t page_size = Solaris::page_size_for_alignment(alignment_hint);
5697 + if (page_size > (size_t) os::vm_page_size()) {
5698 + Solaris::setup_large_pages(addr, bytes, page_size);
5703 +// Tell the OS to make the range local to the first-touching LWP
5704 +void os::numa_make_local(char *addr, size_t bytes, int lgrp_hint) {
5705 + assert((intptr_t)addr % os::vm_page_size() == 0, "Address should be page-aligned.");
5706 + if (posix_madvise(addr, bytes, MADV_ACCESS_LWP) < 0) {
5707 + debug_only(warning("MADV_ACCESS_LWP failed."));
5711 +// Tell the OS that this range would be accessed from different LWPs.
5712 +void os::numa_make_global(char *addr, size_t bytes) {
5713 + assert((intptr_t)addr % os::vm_page_size() == 0, "Address should be page-aligned.");
5714 + if (posix_madvise(addr, bytes, MADV_ACCESS_MANY) < 0) {
5715 + debug_only(warning("MADV_ACCESS_MANY failed."));
5719 +// Get the number of the locality groups.
5720 +size_t os::numa_get_groups_num() {
5721 + size_t n = Solaris::lgrp_nlgrps(Solaris::lgrp_cookie());
5722 + return n != -1 ? n : 1;
5725 +// Get a list of leaf locality groups. A leaf lgroup is group that
5726 +// doesn't have any children. Typical leaf group is a CPU or a CPU/memory
5727 +// board. An LWP is assigned to one of these groups upon creation.
5728 +size_t os::numa_get_leaf_groups(int *ids, size_t size) {
5729 + if ((ids[0] = Solaris::lgrp_root(Solaris::lgrp_cookie())) == -1) {
5730 + ids[0] = 0;
5731 + return 1;
5733 + int result_size = 0, top = 1, bottom = 0, cur = 0;
5734 + for (unsigned int k = 0; k < size; k++) {
5735 + int r = Solaris::lgrp_children(Solaris::lgrp_cookie(), ids[cur],
5736 + (Solaris::lgrp_id_t*)&ids[top], size - top);
5737 + if (r == -1) {
5738 + ids[0] = 0;
5739 + return 1;
5741 + if (!r) {
5742 + // That's a leaf node.
5743 + assert(bottom <= cur, "Sanity check");
5744 + // Check if the node has memory
5745 + if (Solaris::lgrp_resources(Solaris::lgrp_cookie(), ids[cur],
5746 + NULL, 0, LGRP_RSRC_MEM) > 0) {
5747 + ids[bottom++] = ids[cur];
5750 + top += r;
5751 + cur++;
5753 + if (bottom == 0) {
5754 + // Handle a situation, when the OS reports no memory available.
5755 + // Assume UMA architecture.
5756 + ids[0] = 0;
5757 + return 1;
5759 + return bottom;
5762 +// Detect the topology change. Typically happens during CPU plugging-unplugging.
5763 +bool os::numa_topology_changed() {
5764 + int is_stale = Solaris::lgrp_cookie_stale(Solaris::lgrp_cookie());
5765 + if (is_stale != -1 && is_stale) {
5766 + Solaris::lgrp_fini(Solaris::lgrp_cookie());
5767 + Solaris::lgrp_cookie_t c = Solaris::lgrp_init(Solaris::LGRP_VIEW_CALLER);
5768 + assert(c != 0, "Failure to initialize LGRP API");
5769 + Solaris::set_lgrp_cookie(c);
5770 + return true;
5772 + return false;
5775 +// Get the group id of the current LWP.
5776 +int os::numa_get_group_id() {
5777 + int lgrp_id = Solaris::lgrp_home(P_LWPID, P_MYID);
5778 + if (lgrp_id == -1) {
5779 + return 0;
5781 + const int size = os::numa_get_groups_num();
5782 + int *ids = (int*)alloca(size * sizeof(int));
5784 + // Get the ids of all lgroups with memory; r is the count.
5785 + int r = Solaris::lgrp_resources(Solaris::lgrp_cookie(), lgrp_id,
5786 + (Solaris::lgrp_id_t*)ids, size, LGRP_RSRC_MEM);
5787 + if (r <= 0) {
5788 + return 0;
5790 + return ids[os::random() % r];
5793 +int os::numa_get_group_id_for_address(const void* address) {
5794 + return 0;
5797 +bool os::numa_get_group_ids_for_range(const void** addresses, int* lgrp_ids, size_t count) {
5798 + return false;
5801 +// Scan the pages from start to end until a page different than
5802 +// the one described in the info parameter is encountered.
5803 +char *os::scan_pages(char *start, char* end, page_info* page_expected,
5804 + page_info* page_found) {
5805 + const uint_t info_types[] = { MEMINFO_VLGRP, MEMINFO_VPAGESIZE };
5806 + const size_t types = sizeof(info_types) / sizeof(info_types[0]);
5807 + uint64_t addrs[MAX_MEMINFO_CNT], outdata[types * MAX_MEMINFO_CNT + 1];
5808 + uint_t validity[MAX_MEMINFO_CNT];
5810 + size_t page_size = MAX2((size_t)os::vm_page_size(), page_expected->size);
5811 + uint64_t p = (uint64_t)start;
5812 + while (p < (uint64_t)end) {
5813 + addrs[0] = p;
5814 + size_t addrs_count = 1;
5815 + while (addrs_count < MAX_MEMINFO_CNT && addrs[addrs_count - 1] + page_size < (uint64_t)end) {
5816 + addrs[addrs_count] = addrs[addrs_count - 1] + page_size;
5817 + addrs_count++;
5820 + if (meminfo(addrs, addrs_count, info_types, types, outdata, validity) < 0) {
5821 + return NULL;
5824 + size_t i = 0;
5825 + for (; i < addrs_count; i++) {
5826 + if ((validity[i] & 1) != 0) {
5827 + if ((validity[i] & 4) != 0) {
5828 + if (outdata[types * i + 1] != page_expected->size) {
5829 + break;
5831 + } else if (page_expected->size != 0) {
5832 + break;
5835 + if ((validity[i] & 2) != 0 && page_expected->lgrp_id > 0) {
5836 + if (outdata[types * i] != page_expected->lgrp_id) {
5837 + break;
5840 + } else {
5841 + return NULL;
5845 + if (i < addrs_count) {
5846 + if ((validity[i] & 2) != 0) {
5847 + page_found->lgrp_id = outdata[types * i];
5848 + } else {
5849 + page_found->lgrp_id = -1;
5851 + if ((validity[i] & 4) != 0) {
5852 + page_found->size = outdata[types * i + 1];
5853 + } else {
5854 + page_found->size = 0;
5856 + return (char*)addrs[i];
5859 + p = addrs[addrs_count - 1] + page_size;
5861 + return end;
5864 +bool os::pd_uncommit_memory(char* addr, size_t bytes, bool exec) {
5865 + size_t size = bytes;
5866 + // Map uncommitted pages PROT_NONE so we fail early if we touch an
5867 + // uncommitted page. Otherwise, the read/write might succeed if we
5868 + // have enough swap space to back the physical page.
5869 + return
5870 + NULL != Solaris::mmap_chunk(addr, size,
5871 + MAP_PRIVATE|MAP_FIXED|MAP_NORESERVE,
5872 + PROT_NONE);
5875 +char* os::Solaris::mmap_chunk(char *addr, size_t size, int flags, int prot) {
5876 + char *b = (char *)mmap(addr, size, prot, flags, os::Solaris::_dev_zero_fd, 0);
5878 + if (b == MAP_FAILED) {
5879 + return NULL;
5881 + return b;
5884 +char* os::Solaris::anon_mmap(char* requested_addr, size_t bytes) {
5885 + char* addr = requested_addr;
5886 + int flags = MAP_PRIVATE | MAP_NORESERVE;
5888 + // Map uncommitted pages PROT_NONE so we fail early if we touch an
5889 + // uncommitted page. Otherwise, the read/write might succeed if we
5890 + // have enough swap space to back the physical page.
5891 + return mmap_chunk(addr, bytes, flags, PROT_NONE);
5894 +char* os::pd_reserve_memory(size_t bytes, bool exec) {
5895 + char* addr = Solaris::anon_mmap(NULL, bytes);
5897 + return addr;
5900 +char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, int file_desc) {
5901 + assert(file_desc >= 0, "file_desc is not valid");
5902 + char* result = pd_attempt_reserve_memory_at(requested_addr, bytes, !ExecMem);
5903 + if (result != NULL) {
5904 + if (replace_existing_mapping_with_file_mapping(result, bytes, file_desc) == NULL) {
5905 + vm_exit_during_initialization(err_msg("Error in mapping Java heap at the given filesystem directory"));
5908 + return result;
5911 +// Reserve memory at an arbitrary address, only if that area is
5912 +// available (and not reserved for something else).
5914 +char* os::pd_attempt_reserve_memory_at(char* requested_addr, size_t bytes, bool exec) {
5915 + // Assert only that the size is a multiple of the page size, since
5916 + // that's all that mmap requires, and since that's all we really know
5917 + // about at this low abstraction level. If we need higher alignment,
5918 + // we can either pass an alignment to this method or verify alignment
5919 + // in one of the methods further up the call chain. See bug 5044738.
5920 + assert(bytes % os::vm_page_size() == 0, "reserving unexpected size block");
5922 + // Since snv_84, Solaris attempts to honor the address hint - see 5003415.
5923 + char* addr = Solaris::anon_mmap(requested_addr, bytes);
5925 + volatile int err = errno;
5926 + if (addr == requested_addr) {
5927 + return addr;
5930 + if (addr != NULL) {
5931 + pd_unmap_memory(addr, bytes);
5934 + return NULL;
5937 +bool os::pd_release_memory(char* addr, size_t bytes) {
5938 + size_t size = bytes;
5939 + return munmap(addr, size) == 0;
5942 +static bool solaris_mprotect(char* addr, size_t bytes, int prot) {
5943 + assert(addr == (char*)align_down((uintptr_t)addr, os::vm_page_size()),
5944 + "addr must be page aligned");
5945 + Events::log(NULL, "Protecting memory [" INTPTR_FORMAT "," INTPTR_FORMAT "] with protection modes %x", p2i(addr), p2i(addr+bytes), prot);
5946 + int retVal = mprotect(addr, bytes, prot);
5947 + return retVal == 0;
5950 +// Protect memory (Used to pass readonly pages through
5951 +// JNI GetArray<type>Elements with empty arrays.)
5952 +// Also, used for serialization page and for compressed oops null pointer
5953 +// checking.
5954 +bool os::protect_memory(char* addr, size_t bytes, ProtType prot,
5955 + bool is_committed) {
5956 + unsigned int p = 0;
5957 + switch (prot) {
5958 + case MEM_PROT_NONE: p = PROT_NONE; break;
5959 + case MEM_PROT_READ: p = PROT_READ; break;
5960 + case MEM_PROT_RW: p = PROT_READ|PROT_WRITE; break;
5961 + case MEM_PROT_RWX: p = PROT_READ|PROT_WRITE|PROT_EXEC; break;
5962 + default:
5963 + ShouldNotReachHere();
5965 + // is_committed is unused.
5966 + return solaris_mprotect(addr, bytes, p);
5969 +// guard_memory and unguard_memory only happens within stack guard pages.
5970 +// Since ISM pertains only to the heap, guard and unguard memory should not
5971 +/// happen with an ISM region.
5972 +bool os::guard_memory(char* addr, size_t bytes) {
5973 + return solaris_mprotect(addr, bytes, PROT_NONE);
5976 +bool os::unguard_memory(char* addr, size_t bytes) {
5977 + return solaris_mprotect(addr, bytes, PROT_READ|PROT_WRITE);
5980 +// Large page support
5981 +static size_t _large_page_size = 0;
5983 +bool os::Solaris::mpss_sanity_check(bool warn, size_t* page_size) {
5984 + // Find the page sizes supported by the system
5985 + int page_sizes_max = 9;
5986 + size_t _illumos_page_sizes[page_sizes_max];
5987 + int n = getpagesizes(_illumos_page_sizes, page_sizes_max);
5988 + assert(n > 0, "illumos bug?");
5990 + if (n == 1) return false; // Only one page size available.
5992 + // Skip sizes larger than 4M (or LargePageSizeInBytes if it was set)
5993 + const size_t size_limit =
5994 + FLAG_IS_DEFAULT(LargePageSizeInBytes) ? 4 * M : LargePageSizeInBytes;
5995 + int beg;
5996 + for (beg = 0; beg < n; ++beg) {
5997 + if (_illumos_page_sizes[beg] <= size_limit) {
5998 + _page_sizes.add(_illumos_page_sizes[beg]);
5999 + if (_illumos_page_sizes[beg] > *page_size) {
6000 + *page_size = _illumos_page_sizes[beg];
6004 + // make sure we add the default
6005 + _page_sizes.add(os::vm_page_size());
6006 + return true;
6009 +void os::large_page_init() {
6010 + if (UseLargePages) {
6011 + // print a warning if any large page related flag is specified on command line
6012 + bool warn_on_failure = !FLAG_IS_DEFAULT(UseLargePages) ||
6013 + !FLAG_IS_DEFAULT(LargePageSizeInBytes);
6015 + UseLargePages = Solaris::mpss_sanity_check(warn_on_failure, &_large_page_size);
6019 +bool os::Solaris::is_valid_page_size(size_t bytes) {
6020 + return _page_sizes.contains(bytes);
6023 +bool os::Solaris::setup_large_pages(caddr_t start, size_t bytes, size_t align) {
6024 + assert(is_valid_page_size(align), SIZE_FORMAT " is not a valid page size", align);
6025 + assert(is_aligned((void*) start, align),
6026 + PTR_FORMAT " is not aligned to " SIZE_FORMAT, p2i((void*) start), align);
6027 + assert(is_aligned(bytes, align),
6028 + SIZE_FORMAT " is not aligned to " SIZE_FORMAT, bytes, align);
6030 + // Signal to OS that we want large pages for addresses
6031 + // from addr, addr + bytes
6032 + struct memcntl_mha mpss_struct;
6033 + mpss_struct.mha_cmd = MHA_MAPSIZE_VA;
6034 + mpss_struct.mha_pagesize = align;
6035 + mpss_struct.mha_flags = 0;
6036 + // Upon successful completion, memcntl() returns 0
6037 + if (memcntl(start, bytes, MC_HAT_ADVISE, (caddr_t) &mpss_struct, 0, 0)) {
6038 + debug_only(warning("Attempt to use MPSS failed."));
6039 + return false;
6041 + return true;
6044 +char* os::pd_reserve_memory_special(size_t size, size_t alignment, size_t page_size, char* addr, bool exec) {
6045 + fatal("os::reserve_memory_special should not be called on Solaris.");
6046 + return NULL;
6049 +bool os::pd_release_memory_special(char* base, size_t bytes) {
6050 + fatal("os::release_memory_special should not be called on Solaris.");
6051 + return false;
6054 +size_t os::large_page_size() {
6055 + return _large_page_size;
6058 +// MPSS allows application to commit large page memory on demand; with ISM
6059 +// the entire memory region must be allocated as shared memory.
6060 +bool os::can_commit_large_page_memory() {
6061 + return true;
6064 +bool os::can_execute_large_page_memory() {
6065 + return true;
6068 +// Interface for setting lwp priorities. We are using T2 libthread,
6069 +// which forces the use of bound threads, so all of our threads will
6070 +// be assigned to real lwp's. Using the thr_setprio function is
6071 +// meaningless in this mode so we must adjust the real lwp's priority.
6072 +// The routines below implement the getting and setting of lwp priorities.
6074 +// Note: There are three priority scales used on Solaris. Java priorities
6075 +// which range from 1 to 10, libthread "thr_setprio" scale which range
6076 +// from 0 to 127, and the current scheduling class of the process we
6077 +// are running in. This is typically from -60 to +60.
6078 +// The setting of the lwp priorities is done after a call to thr_setprio
6079 +// so Java priorities are mapped to libthread priorities and we map from
6080 +// the latter to lwp priorities. We don't keep priorities stored in
6081 +// Java priorities since some of our worker threads want to set priorities
6082 +// higher than all Java threads.
6084 +// For related information:
6085 +// (1) man -s 2 priocntl
6086 +// (2) man -s 4 priocntl
6087 +// (3) man dispadmin
6088 +// = librt.so
6089 +// = libthread/common/rtsched.c - thrp_setlwpprio().
6090 +// = ps -cL <pid> ... to validate priority.
6091 +// = sched_get_priority_min and _max
6092 +// pthread_create
6093 +// sched_setparam
6094 +// pthread_setschedparam
6096 +// Assumptions:
6097 +// + We assume that all threads in the process belong to the same
6098 +// scheduling class. IE. an homogenous process.
6099 +// + Must be root or in IA group to change change "interactive" attribute.
6100 +// Priocntl() will fail silently. The only indication of failure is when
6101 +// we read-back the value and notice that it hasn't changed.
6102 +// + Interactive threads enter the runq at the head, non-interactive at the tail.
6103 +// + For RT, change timeslice as well. Invariant:
6104 +// constant "priority integral"
6105 +// Konst == TimeSlice * (60-Priority)
6106 +// Given a priority, compute appropriate timeslice.
6107 +// + Higher numerical values have higher priority.
6109 +// sched class attributes
6110 +typedef struct {
6111 + int schedPolicy; // classID
6112 + int maxPrio;
6113 + int minPrio;
6114 +} SchedInfo;
6117 +static SchedInfo tsLimits, iaLimits, rtLimits, fxLimits;
6119 +#ifdef ASSERT
6120 +static int ReadBackValidate = 1;
6121 +#endif
6122 +static int myClass = 0;
6123 +static int myMin = 0;
6124 +static int myMax = 0;
6125 +static int myCur = 0;
6126 +static bool priocntl_enable = false;
6128 +static const int criticalPrio = FXCriticalPriority;
6129 +static int java_MaxPriority_to_os_priority = 0; // Saved mapping
6132 +// lwp_priocntl_init
6134 +// Try to determine the priority scale for our process.
6136 +// Return errno or 0 if OK.
6138 +static int lwp_priocntl_init() {
6139 + int rslt;
6140 + pcinfo_t ClassInfo;
6141 + pcparms_t ParmInfo;
6142 + int i;
6144 + if (!UseThreadPriorities) return 0;
6146 + // If ThreadPriorityPolicy is 1, switch tables
6147 + if (ThreadPriorityPolicy == 1) {
6148 + for (i = 0; i < CriticalPriority+1; i++)
6149 + os::java_to_os_priority[i] = prio_policy1[i];
6151 + if (UseCriticalJavaThreadPriority) {
6152 + // MaxPriority always maps to the FX scheduling class and criticalPrio.
6153 + // See set_native_priority() and set_lwp_class_and_priority().
6154 + // Save original MaxPriority mapping in case attempt to
6155 + // use critical priority fails.
6156 + java_MaxPriority_to_os_priority = os::java_to_os_priority[MaxPriority];
6157 + // Set negative to distinguish from other priorities
6158 + os::java_to_os_priority[MaxPriority] = -criticalPrio;
6161 + // Get IDs for a set of well-known scheduling classes.
6162 + // TODO-FIXME: GETCLINFO returns the current # of classes in the
6163 + // the system. We should have a loop that iterates over the
6164 + // classID values, which are known to be "small" integers.
6166 + strcpy(ClassInfo.pc_clname, "TS");
6167 + ClassInfo.pc_cid = -1;
6168 + rslt = priocntl(P_ALL, 0, PC_GETCID, (caddr_t)&ClassInfo);
6169 + if (rslt < 0) return errno;
6170 + assert(ClassInfo.pc_cid != -1, "cid for TS class is -1");
6171 + tsLimits.schedPolicy = ClassInfo.pc_cid;
6172 + tsLimits.maxPrio = ((tsinfo_t*)ClassInfo.pc_clinfo)->ts_maxupri;
6173 + tsLimits.minPrio = -tsLimits.maxPrio;
6175 + strcpy(ClassInfo.pc_clname, "IA");
6176 + ClassInfo.pc_cid = -1;
6177 + rslt = priocntl(P_ALL, 0, PC_GETCID, (caddr_t)&ClassInfo);
6178 + if (rslt < 0) return errno;
6179 + assert(ClassInfo.pc_cid != -1, "cid for IA class is -1");
6180 + iaLimits.schedPolicy = ClassInfo.pc_cid;
6181 + iaLimits.maxPrio = ((iainfo_t*)ClassInfo.pc_clinfo)->ia_maxupri;
6182 + iaLimits.minPrio = -iaLimits.maxPrio;
6184 + strcpy(ClassInfo.pc_clname, "RT");
6185 + ClassInfo.pc_cid = -1;
6186 + rslt = priocntl(P_ALL, 0, PC_GETCID, (caddr_t)&ClassInfo);
6187 + if (rslt < 0) return errno;
6188 + assert(ClassInfo.pc_cid != -1, "cid for RT class is -1");
6189 + rtLimits.schedPolicy = ClassInfo.pc_cid;
6190 + rtLimits.maxPrio = ((rtinfo_t*)ClassInfo.pc_clinfo)->rt_maxpri;
6191 + rtLimits.minPrio = 0;
6193 + strcpy(ClassInfo.pc_clname, "FX");
6194 + ClassInfo.pc_cid = -1;
6195 + rslt = priocntl(P_ALL, 0, PC_GETCID, (caddr_t)&ClassInfo);
6196 + if (rslt < 0) return errno;
6197 + assert(ClassInfo.pc_cid != -1, "cid for FX class is -1");
6198 + fxLimits.schedPolicy = ClassInfo.pc_cid;
6199 + fxLimits.maxPrio = ((fxinfo_t*)ClassInfo.pc_clinfo)->fx_maxupri;
6200 + fxLimits.minPrio = 0;
6202 + // Query our "current" scheduling class.
6203 + // This will normally be IA, TS or, rarely, FX or RT.
6204 + memset(&ParmInfo, 0, sizeof(ParmInfo));
6205 + ParmInfo.pc_cid = PC_CLNULL;
6206 + rslt = priocntl(P_PID, P_MYID, PC_GETPARMS, (caddr_t)&ParmInfo);
6207 + if (rslt < 0) return errno;
6208 + myClass = ParmInfo.pc_cid;
6210 + // We now know our scheduling classId, get specific information
6211 + // about the class.
6212 + ClassInfo.pc_cid = myClass;
6213 + ClassInfo.pc_clname[0] = 0;
6214 + rslt = priocntl((idtype)0, 0, PC_GETCLINFO, (caddr_t)&ClassInfo);
6215 + if (rslt < 0) return errno;
6217 + memset(&ParmInfo, 0, sizeof(pcparms_t));
6218 + ParmInfo.pc_cid = PC_CLNULL;
6219 + rslt = priocntl(P_PID, P_MYID, PC_GETPARMS, (caddr_t)&ParmInfo);
6220 + if (rslt < 0) return errno;
6222 + if (ParmInfo.pc_cid == rtLimits.schedPolicy) {
6223 + myMin = rtLimits.minPrio;
6224 + myMax = rtLimits.maxPrio;
6225 + } else if (ParmInfo.pc_cid == iaLimits.schedPolicy) {
6226 + iaparms_t *iaInfo = (iaparms_t*)ParmInfo.pc_clparms;
6227 + myMin = iaLimits.minPrio;
6228 + myMax = iaLimits.maxPrio;
6229 + myMax = MIN2(myMax, (int)iaInfo->ia_uprilim); // clamp - restrict
6230 + } else if (ParmInfo.pc_cid == tsLimits.schedPolicy) {
6231 + tsparms_t *tsInfo = (tsparms_t*)ParmInfo.pc_clparms;
6232 + myMin = tsLimits.minPrio;
6233 + myMax = tsLimits.maxPrio;
6234 + myMax = MIN2(myMax, (int)tsInfo->ts_uprilim); // clamp - restrict
6235 + } else if (ParmInfo.pc_cid == fxLimits.schedPolicy) {
6236 + fxparms_t *fxInfo = (fxparms_t*)ParmInfo.pc_clparms;
6237 + myMin = fxLimits.minPrio;
6238 + myMax = fxLimits.maxPrio;
6239 + myMax = MIN2(myMax, (int)fxInfo->fx_uprilim); // clamp - restrict
6240 + } else {
6241 + return EINVAL; // no clue, punt
6244 + priocntl_enable = true; // Enable changing priorities
6245 + return 0;
6248 +#define IAPRI(x) ((iaparms_t *)((x).pc_clparms))
6249 +#define RTPRI(x) ((rtparms_t *)((x).pc_clparms))
6250 +#define TSPRI(x) ((tsparms_t *)((x).pc_clparms))
6251 +#define FXPRI(x) ((fxparms_t *)((x).pc_clparms))
6254 +// scale_to_lwp_priority
6256 +// Convert from the libthread "thr_setprio" scale to our current
6257 +// lwp scheduling class scale.
6259 +static int scale_to_lwp_priority(int rMin, int rMax, int x) {
6260 + int v;
6262 + if (x == 127) return rMax; // avoid round-down
6263 + v = (((x*(rMax-rMin)))/128)+rMin;
6264 + return v;
6268 +// set_lwp_class_and_priority
6269 +int set_lwp_class_and_priority(int ThreadID, int lwpid,
6270 + int newPrio, int new_class, bool scale) {
6271 + int rslt;
6272 + int Actual, Expected, prv;
6273 + pcparms_t ParmInfo; // for GET-SET
6274 +#ifdef ASSERT
6275 + pcparms_t ReadBack; // for readback
6276 +#endif
6278 + // Set priority via PC_GETPARMS, update, PC_SETPARMS
6279 + // Query current values.
6280 + // TODO: accelerate this by eliminating the PC_GETPARMS call.
6281 + // Cache "pcparms_t" in global ParmCache.
6282 + // TODO: elide set-to-same-value
6284 + // If something went wrong on init, don't change priorities.
6285 + if (!priocntl_enable) {
6286 + return EINVAL;
6289 + // If lwp hasn't started yet, just return
6290 + // the _start routine will call us again.
6291 + if (lwpid <= 0) {
6292 + return 0;
6295 + memset(&ParmInfo, 0, sizeof(pcparms_t));
6296 + ParmInfo.pc_cid = PC_CLNULL;
6297 + rslt = priocntl(P_LWPID, lwpid, PC_GETPARMS, (caddr_t)&ParmInfo);
6298 + if (rslt < 0) return errno;
6300 + int cur_class = ParmInfo.pc_cid;
6301 + ParmInfo.pc_cid = (id_t)new_class;
6303 + if (new_class == rtLimits.schedPolicy) {
6304 + rtparms_t *rtInfo = (rtparms_t*)ParmInfo.pc_clparms;
6305 + rtInfo->rt_pri = scale ? scale_to_lwp_priority(rtLimits.minPrio,
6306 + rtLimits.maxPrio, newPrio)
6307 + : newPrio;
6308 + rtInfo->rt_tqsecs = RT_NOCHANGE;
6309 + rtInfo->rt_tqnsecs = RT_NOCHANGE;
6310 + } else if (new_class == iaLimits.schedPolicy) {
6311 + iaparms_t* iaInfo = (iaparms_t*)ParmInfo.pc_clparms;
6312 + int maxClamped = MIN2(iaLimits.maxPrio,
6313 + cur_class == new_class
6314 + ? (int)iaInfo->ia_uprilim : iaLimits.maxPrio);
6315 + iaInfo->ia_upri = scale ? scale_to_lwp_priority(iaLimits.minPrio,
6316 + maxClamped, newPrio)
6317 + : newPrio;
6318 + iaInfo->ia_uprilim = cur_class == new_class
6319 + ? IA_NOCHANGE : (pri_t)iaLimits.maxPrio;
6320 + iaInfo->ia_mode = IA_NOCHANGE;
6321 + } else if (new_class == tsLimits.schedPolicy) {
6322 + tsparms_t* tsInfo = (tsparms_t*)ParmInfo.pc_clparms;
6323 + int maxClamped = MIN2(tsLimits.maxPrio,
6324 + cur_class == new_class
6325 + ? (int)tsInfo->ts_uprilim : tsLimits.maxPrio);
6326 + tsInfo->ts_upri = scale ? scale_to_lwp_priority(tsLimits.minPrio,
6327 + maxClamped, newPrio)
6328 + : newPrio;
6329 + tsInfo->ts_uprilim = cur_class == new_class
6330 + ? TS_NOCHANGE : (pri_t)tsLimits.maxPrio;
6331 + } else if (new_class == fxLimits.schedPolicy) {
6332 + fxparms_t* fxInfo = (fxparms_t*)ParmInfo.pc_clparms;
6333 + int maxClamped = MIN2(fxLimits.maxPrio,
6334 + cur_class == new_class
6335 + ? (int)fxInfo->fx_uprilim : fxLimits.maxPrio);
6336 + fxInfo->fx_upri = scale ? scale_to_lwp_priority(fxLimits.minPrio,
6337 + maxClamped, newPrio)
6338 + : newPrio;
6339 + fxInfo->fx_uprilim = cur_class == new_class
6340 + ? FX_NOCHANGE : (pri_t)fxLimits.maxPrio;
6341 + fxInfo->fx_tqsecs = FX_NOCHANGE;
6342 + fxInfo->fx_tqnsecs = FX_NOCHANGE;
6343 + } else {
6344 + return EINVAL; // no clue, punt
6347 + rslt = priocntl(P_LWPID, lwpid, PC_SETPARMS, (caddr_t)&ParmInfo);
6348 + if (rslt < 0) return errno;
6350 +#ifdef ASSERT
6351 + // Sanity check: read back what we just attempted to set.
6352 + // In theory it could have changed in the interim ...
6353 + //
6354 + // The priocntl system call is tricky.
6355 + // Sometimes it'll validate the priority value argument and
6356 + // return EINVAL if unhappy. At other times it fails silently.
6357 + // Readbacks are prudent.
6359 + if (!ReadBackValidate) return 0;
6361 + memset(&ReadBack, 0, sizeof(pcparms_t));
6362 + ReadBack.pc_cid = PC_CLNULL;
6363 + rslt = priocntl(P_LWPID, lwpid, PC_GETPARMS, (caddr_t)&ReadBack);
6364 + assert(rslt >= 0, "priocntl failed");
6365 + Actual = Expected = 0xBAD;
6366 + assert(ParmInfo.pc_cid == ReadBack.pc_cid, "cid's don't match");
6367 + if (ParmInfo.pc_cid == rtLimits.schedPolicy) {
6368 + Actual = RTPRI(ReadBack)->rt_pri;
6369 + Expected = RTPRI(ParmInfo)->rt_pri;
6370 + } else if (ParmInfo.pc_cid == iaLimits.schedPolicy) {
6371 + Actual = IAPRI(ReadBack)->ia_upri;
6372 + Expected = IAPRI(ParmInfo)->ia_upri;
6373 + } else if (ParmInfo.pc_cid == tsLimits.schedPolicy) {
6374 + Actual = TSPRI(ReadBack)->ts_upri;
6375 + Expected = TSPRI(ParmInfo)->ts_upri;
6376 + } else if (ParmInfo.pc_cid == fxLimits.schedPolicy) {
6377 + Actual = FXPRI(ReadBack)->fx_upri;
6378 + Expected = FXPRI(ParmInfo)->fx_upri;
6380 +#endif
6382 + return 0;
6385 +// Solaris only gives access to 128 real priorities at a time,
6386 +// so we expand Java's ten to fill this range. This would be better
6387 +// if we dynamically adjusted relative priorities.
6389 +// The ThreadPriorityPolicy option allows us to select 2 different
6390 +// priority scales.
6392 +// ThreadPriorityPolicy=0
6393 +// Since the Solaris' default priority is MaximumPriority, we do not
6394 +// set a priority lower than Max unless a priority lower than
6395 +// NormPriority is requested.
6397 +// ThreadPriorityPolicy=1
6398 +// This mode causes the priority table to get filled with
6399 +// linear values. NormPriority get's mapped to 50% of the
6400 +// Maximum priority an so on. This will cause VM threads
6401 +// to get unfair treatment against other Solaris processes
6402 +// which do not explicitly alter their thread priorities.
6404 +int os::java_to_os_priority[CriticalPriority + 1] = {
6405 + -99999, // 0 Entry should never be used
6407 + 0, // 1 MinPriority
6408 + 32, // 2
6409 + 64, // 3
6411 + 96, // 4
6412 + 127, // 5 NormPriority
6413 + 127, // 6
6415 + 127, // 7
6416 + 127, // 8
6417 + 127, // 9 NearMaxPriority
6419 + 127, // 10 MaxPriority
6421 + -criticalPrio // 11 CriticalPriority
6424 +OSReturn os::set_native_priority(Thread* thread, int newpri) {
6425 + OSThread* osthread = thread->osthread();
6427 + // Save requested priority in case the thread hasn't been started
6428 + osthread->set_native_priority(newpri);
6430 + // Check for critical priority request
6431 + bool fxcritical = false;
6432 + if (newpri == -criticalPrio) {
6433 + fxcritical = true;
6434 + newpri = criticalPrio;
6437 + assert(newpri >= MinimumPriority && newpri <= MaximumPriority, "bad priority mapping");
6438 + if (!UseThreadPriorities) return OS_OK;
6440 + int status = 0;
6442 + if (!fxcritical) {
6443 + // Use thr_setprio only if we have a priority that thr_setprio understands
6444 + status = thr_setprio(thread->osthread()->thread_id(), newpri);
6447 + int lwp_status =
6448 + set_lwp_class_and_priority(osthread->thread_id(),
6449 + osthread->lwp_id(),
6450 + newpri,
6451 + fxcritical ? fxLimits.schedPolicy : myClass,
6452 + !fxcritical);
6453 + if (lwp_status != 0 && fxcritical) {
6454 + // Try again, this time without changing the scheduling class
6455 + newpri = java_MaxPriority_to_os_priority;
6456 + lwp_status = set_lwp_class_and_priority(osthread->thread_id(),
6457 + osthread->lwp_id(),
6458 + newpri, myClass, false);
6460 + status |= lwp_status;
6461 + return (status == 0) ? OS_OK : OS_ERR;
6465 +OSReturn os::get_native_priority(const Thread* const thread,
6466 + int *priority_ptr) {
6467 + int p;
6468 + if (!UseThreadPriorities) {
6469 + *priority_ptr = NormalPriority;
6470 + return OS_OK;
6472 + int status = thr_getprio(thread->osthread()->thread_id(), &p);
6473 + if (status != 0) {
6474 + return OS_ERR;
6476 + *priority_ptr = p;
6477 + return OS_OK;
6480 +////////////////////////////////////////////////////////////////////////////////
6482 +// This does not do anything on Solaris. This is basically a hook for being
6483 +// able to use structured exception handling (thread-local exception filters) on, e.g., Win32.
6484 +void os::os_exception_wrapper(java_call_t f, JavaValue* value,
6485 + const methodHandle& method, JavaCallArguments* args,
6486 + JavaThread* thread) {
6487 + f(value, method, args, thread);
6490 +void report_error(const char* file_name, int line_no, const char* title,
6491 + const char* format, ...);
6493 +// (Static) wrappers for the liblgrp API
6494 +os::Solaris::lgrp_home_func_t os::Solaris::_lgrp_home;
6495 +os::Solaris::lgrp_init_func_t os::Solaris::_lgrp_init;
6496 +os::Solaris::lgrp_fini_func_t os::Solaris::_lgrp_fini;
6497 +os::Solaris::lgrp_root_func_t os::Solaris::_lgrp_root;
6498 +os::Solaris::lgrp_children_func_t os::Solaris::_lgrp_children;
6499 +os::Solaris::lgrp_resources_func_t os::Solaris::_lgrp_resources;
6500 +os::Solaris::lgrp_nlgrps_func_t os::Solaris::_lgrp_nlgrps;
6501 +os::Solaris::lgrp_cookie_stale_func_t os::Solaris::_lgrp_cookie_stale;
6502 +os::Solaris::lgrp_cookie_t os::Solaris::_lgrp_cookie = 0;
6504 +static address resolve_symbol_lazy(const char* name) {
6505 + address addr = (address) dlsym(RTLD_DEFAULT, name);
6506 + if (addr == NULL) {
6507 + // RTLD_DEFAULT was not defined on some early versions of 2.5.1
6508 + addr = (address) dlsym(RTLD_NEXT, name);
6510 + return addr;
6513 +static address resolve_symbol(const char* name) {
6514 + address addr = resolve_symbol_lazy(name);
6515 + if (addr == NULL) {
6516 + fatal("resolve_symbol failed (%s)", dlerror());
6518 + return addr;
6521 +void os::Solaris::libthread_init() {
6522 + address func = (address)dlsym(RTLD_DEFAULT, "_thr_suspend_allmutators");
6524 + lwp_priocntl_init();
6526 + // RTLD_DEFAULT was not defined on some early versions of 5.5.1
6527 + if (func == NULL) {
6528 + func = (address) dlsym(RTLD_NEXT, "_thr_suspend_allmutators");
6529 + // Guarantee that this VM is running on an new enough OS (5.6 or
6530 + // later) that it will have a new enough libthread.so.
6531 + guarantee(func != NULL, "libthread.so is too old.");
6534 + int size;
6535 + void (*handler_info_func)(address *, int *);
6536 + handler_info_func = CAST_TO_FN_PTR(void (*)(address *, int *), resolve_symbol("thr_sighndlrinfo"));
6537 + handler_info_func(&handler_start, &size);
6538 + handler_end = handler_start + size;
6542 +bool os::Solaris::_synchronization_initialized;
6544 +void os::Solaris::synchronization_init() {
6545 + _synchronization_initialized = true;
6548 +bool os::Solaris::liblgrp_init() {
6549 + void *handle = dlopen("liblgrp.so.1", RTLD_LAZY);
6550 + if (handle != NULL) {
6551 + os::Solaris::set_lgrp_home(CAST_TO_FN_PTR(lgrp_home_func_t, dlsym(handle, "lgrp_home")));
6552 + os::Solaris::set_lgrp_init(CAST_TO_FN_PTR(lgrp_init_func_t, dlsym(handle, "lgrp_init")));
6553 + os::Solaris::set_lgrp_fini(CAST_TO_FN_PTR(lgrp_fini_func_t, dlsym(handle, "lgrp_fini")));
6554 + os::Solaris::set_lgrp_root(CAST_TO_FN_PTR(lgrp_root_func_t, dlsym(handle, "lgrp_root")));
6555 + os::Solaris::set_lgrp_children(CAST_TO_FN_PTR(lgrp_children_func_t, dlsym(handle, "lgrp_children")));
6556 + os::Solaris::set_lgrp_resources(CAST_TO_FN_PTR(lgrp_resources_func_t, dlsym(handle, "lgrp_resources")));
6557 + os::Solaris::set_lgrp_nlgrps(CAST_TO_FN_PTR(lgrp_nlgrps_func_t, dlsym(handle, "lgrp_nlgrps")));
6558 + os::Solaris::set_lgrp_cookie_stale(CAST_TO_FN_PTR(lgrp_cookie_stale_func_t,
6559 + dlsym(handle, "lgrp_cookie_stale")));
6561 + lgrp_cookie_t c = lgrp_init(LGRP_VIEW_CALLER);
6562 + set_lgrp_cookie(c);
6563 + return true;
6565 + return false;
6568 +// int pset_getloadavg(psetid_t pset, double loadavg[], int nelem);
6569 +typedef long (*pset_getloadavg_type)(psetid_t pset, double loadavg[], int nelem);
6570 +static pset_getloadavg_type pset_getloadavg_ptr = NULL;
6572 +void init_pset_getloadavg_ptr(void) {
6573 + pset_getloadavg_ptr =
6574 + (pset_getloadavg_type)dlsym(RTLD_DEFAULT, "pset_getloadavg");
6575 + if (pset_getloadavg_ptr == NULL) {
6576 + log_warning(os)("pset_getloadavg function not found");
6580 +int os::Solaris::_dev_zero_fd = -1;
6582 +// this is called _before_ the global arguments have been parsed
6583 +void os::init(void) {
6584 + _initial_pid = getpid();
6586 + max_hrtime = first_hrtime = gethrtime();
6588 + init_random(1234567);
6590 + int page_size = sysconf(_SC_PAGESIZE);
6591 + OSInfo::set_vm_page_size(page_size);
6592 + OSInfo::set_vm_allocation_granularity(page_size);
6593 + if (os::vm_page_size() <= 0) {
6594 + fatal("os_solaris.cpp: os::init: sysconf failed (%s)", os::strerror(errno));
6596 + _page_sizes.add(os::vm_page_size());
6598 + Solaris::initialize_system_info();
6600 + int fd = ::open("/dev/zero", O_RDWR);
6601 + if (fd < 0) {
6602 + fatal("os::init: cannot open /dev/zero (%s)", os::strerror(errno));
6603 + } else {
6604 + Solaris::set_dev_zero_fd(fd);
6606 + // Close on exec, child won't inherit.
6607 + fcntl(fd, F_SETFD, FD_CLOEXEC);
6610 + clock_tics_per_sec = CLK_TCK;
6612 + // check if dladdr1() exists; dladdr1 can provide more information than
6613 + // dladdr for os::dll_address_to_function_name. It comes with SunOS 5.9
6614 + // and is available on linker patches for 5.7 and 5.8.
6615 + // libdl.so must have been loaded, this call is just an entry lookup
6616 + void * hdl = dlopen("libdl.so", RTLD_NOW);
6617 + if (hdl) {
6618 + dladdr1_func = CAST_TO_FN_PTR(dladdr1_func_type, dlsym(hdl, "dladdr1"));
6621 + // main_thread points to the thread that created/loaded the JVM.
6622 + main_thread = thr_self();
6624 + // dynamic lookup of functions that may not be available in our lowest
6625 + // supported Solaris release
6626 + void * handle = dlopen("libc.so.1", RTLD_LAZY);
6627 + if (handle != NULL) {
6628 + Solaris::_pthread_setname_np = // from 11.3
6629 + (Solaris::pthread_setname_np_func_t)dlsym(handle, "pthread_setname_np");
6632 + // Shared Posix initialization
6633 + os::Posix::init();
6636 +// To install functions for atexit system call
6637 +extern "C" {
6638 + static void perfMemory_exit_helper() {
6639 + perfMemory_exit();
6643 +// this is called _after_ the global arguments have been parsed
6644 +jint os::init_2(void) {
6645 + Solaris::libthread_init();
6647 + if (UseNUMA) {
6648 + if (!Solaris::liblgrp_init()) {
6649 + FLAG_SET_ERGO(UseNUMA, false);
6650 + } else {
6651 + size_t lgrp_limit = os::numa_get_groups_num();
6652 + int *lgrp_ids = NEW_C_HEAP_ARRAY(int, lgrp_limit, mtInternal);
6653 + size_t lgrp_num = os::numa_get_leaf_groups(lgrp_ids, lgrp_limit);
6654 + FREE_C_HEAP_ARRAY(int, lgrp_ids);
6655 + if (lgrp_num < 2) {
6656 + // There's only one locality group, disable NUMA
6657 + UseNUMA = false;
6662 + // When NUMA requested, not-NUMA-aware allocations default to interleaving.
6663 + if (UseNUMA && !UseNUMAInterleaving) {
6664 + FLAG_SET_ERGO_IF_DEFAULT(UseNUMAInterleaving, true);
6667 + if (PosixSignals::init() == JNI_ERR) {
6668 + return JNI_ERR;
6671 + // initialize synchronization primitives
6672 + Solaris::synchronization_init();
6673 + DEBUG_ONLY(os::set_mutex_init_done();)
6675 + if (MaxFDLimit) {
6676 + // set the number of file descriptors to max. print out error
6677 + // if getrlimit/setrlimit fails but continue regardless.
6678 + struct rlimit nbr_files;
6679 + int status = getrlimit(RLIMIT_NOFILE, &nbr_files);
6680 + if (status != 0) {
6681 + log_info(os)("os::init_2 getrlimit failed: %s", os::strerror(errno));
6682 + } else {
6683 + nbr_files.rlim_cur = nbr_files.rlim_max;
6684 + status = setrlimit(RLIMIT_NOFILE, &nbr_files);
6685 + if (status != 0) {
6686 + log_info(os)("os::init_2 setrlimit failed: %s", os::strerror(errno));
6691 + // Calculate theoretical max. size of Threads to guard gainst
6692 + // artifical out-of-memory situations, where all available address-
6693 + // space has been reserved by thread stacks. Default stack size is 1Mb.
6694 + size_t pre_thread_stack_size = (JavaThread::stack_size_at_create()) ?
6695 + JavaThread::stack_size_at_create() : (1*K*K);
6696 + assert(pre_thread_stack_size != 0, "Must have a stack");
6697 + // Solaris has a maximum of 4Gb of user programs. Calculate the thread limit when
6698 + // we should start doing Virtual Memory banging. Currently when the threads will
6699 + // have used all but 200Mb of space.
6700 + size_t max_address_space = ((unsigned int)4 * K * K * K) - (200 * K * K);
6701 + Solaris::_os_thread_limit = max_address_space / pre_thread_stack_size;
6703 + // at-exit methods are called in the reverse order of their registration.
6704 + // In Solaris 7 and earlier, atexit functions are called on return from
6705 + // main or as a result of a call to exit(3C). There can be only 32 of
6706 + // these functions registered and atexit() does not set errno. In Solaris
6707 + // 8 and later, there is no limit to the number of functions registered
6708 + // and atexit() sets errno. In addition, in Solaris 8 and later, atexit
6709 + // functions are called upon dlclose(3DL) in addition to return from main
6710 + // and exit(3C).
6712 + if (PerfAllowAtExitRegistration) {
6713 + // only register atexit functions if PerfAllowAtExitRegistration is set.
6714 + // atexit functions can be delayed until process exit time, which
6715 + // can be problematic for embedded VM situations. Embedded VMs should
6716 + // call DestroyJavaVM() to assure that VM resources are released.
6718 + // note: perfMemory_exit_helper atexit function may be removed in
6719 + // the future if the appropriate cleanup code can be added to the
6720 + // VM_Exit VMOperation's doit method.
6721 + if (atexit(perfMemory_exit_helper) != 0) {
6722 + warning("os::init2 atexit(perfMemory_exit_helper) failed");
6726 + // Init pset_loadavg function pointer
6727 + init_pset_getloadavg_ptr();
6729 + // Shared Posix initialization
6730 + os::Posix::init_2();
6732 + return JNI_OK;
6735 +// This code originates from JDK's sysOpen and open64_w
6736 +// from src/solaris/hpi/src/system_md.c
6738 +int os::open(const char *path, int oflag, int mode) {
6739 + if (strlen(path) > MAX_PATH - 1) {
6740 + errno = ENAMETOOLONG;
6741 + return -1;
6743 + int fd;
6745 + fd = ::open64(path, oflag, mode);
6746 + if (fd == -1) return -1;
6748 + // If the open succeeded, the file might still be a directory
6750 + struct stat64 buf64;
6751 + int ret = ::fstat64(fd, &buf64);
6752 + int st_mode = buf64.st_mode;
6754 + if (ret != -1) {
6755 + if ((st_mode & S_IFMT) == S_IFDIR) {
6756 + errno = EISDIR;
6757 + ::close(fd);
6758 + return -1;
6760 + } else {
6761 + ::close(fd);
6762 + return -1;
6766 + // All file descriptors that are opened in the JVM and not
6767 + // specifically destined for a subprocess should have the
6768 + // close-on-exec flag set. If we don't set it, then careless 3rd
6769 + // party native code might fork and exec without closing all
6770 + // appropriate file descriptors (e.g. as we do in closeDescriptors in
6771 + // UNIXProcess.c), and this in turn might:
6772 + //
6773 + // - cause end-of-file to fail to be detected on some file
6774 + // descriptors, resulting in mysterious hangs, or
6775 + //
6776 + // - might cause an fopen in the subprocess to fail on a system
6777 + // suffering from bug 1085341.
6778 + //
6779 + // (Yes, the default setting of the close-on-exec flag is a Unix
6780 + // design flaw)
6781 + //
6782 + // See:
6783 + // 1085341: 32-bit stdio routines should support file descriptors >255
6784 + // 4843136: (process) pipe file descriptor from Runtime.exec not being closed
6785 + // 6339493: (process) Runtime.exec does not close all file descriptors on Solaris 9
6786 + //
6787 +#ifdef FD_CLOEXEC
6789 + int flags = ::fcntl(fd, F_GETFD);
6790 + if (flags != -1) {
6791 + ::fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
6794 +#endif
6796 + return fd;
6799 +// create binary file, rewriting existing file if required
6800 +int os::create_binary_file(const char* path, bool rewrite_existing) {
6801 + int oflags = O_WRONLY | O_CREAT;
6802 + if (!rewrite_existing) {
6803 + oflags |= O_EXCL;
6805 + return ::open64(path, oflags, S_IREAD | S_IWRITE);
6808 +// return current position of file pointer
6809 +jlong os::current_file_offset(int fd) {
6810 + return (jlong)::lseek64(fd, (off64_t)0, SEEK_CUR);
6813 +// move file pointer to the specified offset
6814 +jlong os::seek_to_file_offset(int fd, jlong offset) {
6815 + return (jlong)::lseek64(fd, (off64_t)offset, SEEK_SET);
6818 +// Map a block of memory.
6819 +char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset,
6820 + char *addr, size_t bytes, bool read_only,
6821 + bool allow_exec) {
6822 + int prot;
6823 + int flags;
6825 + if (read_only) {
6826 + prot = PROT_READ;
6827 + flags = MAP_SHARED;
6828 + } else {
6829 + prot = PROT_READ | PROT_WRITE;
6830 + flags = MAP_PRIVATE;
6833 + if (allow_exec) {
6834 + prot |= PROT_EXEC;
6837 + if (addr != NULL) {
6838 + flags |= MAP_FIXED;
6841 + char* mapped_address = (char*)mmap(addr, (size_t)bytes, prot, flags,
6842 + fd, file_offset);
6843 + if (mapped_address == MAP_FAILED) {
6844 + return NULL;
6846 + return mapped_address;
6850 +// Remap a block of memory.
6851 +char* os::pd_remap_memory(int fd, const char* file_name, size_t file_offset,
6852 + char *addr, size_t bytes, bool read_only,
6853 + bool allow_exec) {
6854 + // same as map_memory() on this OS
6855 + return os::map_memory(fd, file_name, file_offset, addr, bytes, read_only,
6856 + allow_exec);
6860 +// Unmap a block of memory.
6861 +bool os::pd_unmap_memory(char* addr, size_t bytes) {
6862 + return munmap(addr, bytes) == 0;
6865 +const intptr_t thr_time_off = (intptr_t)(&((prusage_t *)(NULL))->pr_utime);
6866 +const intptr_t thr_time_size = (intptr_t)(&((prusage_t *)(NULL))->pr_ttime) -
6867 + (intptr_t)(&((prusage_t *)(NULL))->pr_utime);
6870 +// JVMTI & JVM monitoring and management support
6871 +// The thread_cpu_time() and current_thread_cpu_time() are only
6872 +// supported if is_thread_cpu_time_supported() returns true.
6873 +// They are not supported on Solaris T1.
6875 +// current_thread_cpu_time(bool) and thread_cpu_time(Thread*, bool)
6876 +// are used by JVM M&M and JVMTI to get user+sys or user CPU time
6877 +// of a thread.
6879 +// current_thread_cpu_time() and thread_cpu_time(Thread *)
6880 +// returns the fast estimate available on the platform.
6882 +// hrtime_t gethrvtime() return value includes
6883 +// user time but does not include system time
6884 +jlong os::current_thread_cpu_time() {
6885 + return (jlong) gethrvtime();
6888 +jlong os::thread_cpu_time(Thread *thread) {
6889 + // return user level CPU time only to be consistent with
6890 + // what current_thread_cpu_time returns.
6891 + // thread_cpu_time_info() must be changed if this changes
6892 + return os::thread_cpu_time(thread, false /* user time only */);
6895 +jlong os::current_thread_cpu_time(bool user_sys_cpu_time) {
6896 + if (user_sys_cpu_time) {
6897 + return os::thread_cpu_time(Thread::current(), user_sys_cpu_time);
6898 + } else {
6899 + return os::current_thread_cpu_time();
6903 +jlong os::thread_cpu_time(Thread *thread, bool user_sys_cpu_time) {
6904 + char proc_name[64];
6905 + int count;
6906 + prusage_t prusage;
6907 + jlong lwp_time;
6908 + int fd;
6910 + sprintf(proc_name, "/proc/%d/lwp/%d/lwpusage",
6911 + getpid(),
6912 + thread->osthread()->lwp_id());
6913 + fd = ::open(proc_name, O_RDONLY);
6914 + if (fd == -1) return -1;
6916 + do {
6917 + count = ::pread(fd,
6918 + (void *)&prusage.pr_utime,
6919 + thr_time_size,
6920 + thr_time_off);
6921 + } while (count < 0 && errno == EINTR);
6922 + ::close(fd);
6923 + if (count < 0) return -1;
6925 + if (user_sys_cpu_time) {
6926 + // user + system CPU time
6927 + lwp_time = (((jlong)prusage.pr_stime.tv_sec +
6928 + (jlong)prusage.pr_utime.tv_sec) * (jlong)1000000000) +
6929 + (jlong)prusage.pr_stime.tv_nsec +
6930 + (jlong)prusage.pr_utime.tv_nsec;
6931 + } else {
6932 + // user level CPU time only
6933 + lwp_time = ((jlong)prusage.pr_utime.tv_sec * (jlong)1000000000) +
6934 + (jlong)prusage.pr_utime.tv_nsec;
6937 + return (lwp_time);
6940 +void os::current_thread_cpu_time_info(jvmtiTimerInfo *info_ptr) {
6941 + info_ptr->max_value = ALL_64_BITS; // will not wrap in less than 64 bits
6942 + info_ptr->may_skip_backward = false; // elapsed time not wall time
6943 + info_ptr->may_skip_forward = false; // elapsed time not wall time
6944 + info_ptr->kind = JVMTI_TIMER_USER_CPU; // only user time is returned
6947 +void os::thread_cpu_time_info(jvmtiTimerInfo *info_ptr) {
6948 + info_ptr->max_value = ALL_64_BITS; // will not wrap in less than 64 bits
6949 + info_ptr->may_skip_backward = false; // elapsed time not wall time
6950 + info_ptr->may_skip_forward = false; // elapsed time not wall time
6951 + info_ptr->kind = JVMTI_TIMER_USER_CPU; // only user time is returned
6954 +bool os::is_thread_cpu_time_supported() {
6955 + return true;
6958 +// System loadavg support. Returns -1 if load average cannot be obtained.
6959 +// Return the load average for our processor set if the primitive exists
6960 +// (Solaris 9 and later). Otherwise just return system wide loadavg.
6961 +int os::loadavg(double loadavg[], int nelem) {
6962 + if (pset_getloadavg_ptr != NULL) {
6963 + return (*pset_getloadavg_ptr)(PS_MYID, loadavg, nelem);
6964 + } else {
6965 + return ::getloadavg(loadavg, nelem);
6969 +//---------------------------------------------------------------------------------
6971 +bool os::find(address addr, outputStream* st) {
6972 + Dl_info dlinfo;
6973 + memset(&dlinfo, 0, sizeof(dlinfo));
6974 + if (dladdr(addr, &dlinfo) != 0) {
6975 + st->print(PTR_FORMAT ": ", p2i(addr));
6976 + if (dlinfo.dli_sname != NULL && dlinfo.dli_saddr != NULL) {
6977 + st->print("%s+" PTR_FORMAT, dlinfo.dli_sname,
6978 + p2i(addr) - p2i(dlinfo.dli_saddr));
6979 + } else if (dlinfo.dli_fbase != NULL) {
6980 + st->print("<offset " PTR_FORMAT ">", p2i(addr) - p2i(dlinfo.dli_fbase));
6981 + } else {
6982 + st->print("<absolute address>");
6984 + if (dlinfo.dli_fname != NULL) {
6985 + st->print(" in %s", dlinfo.dli_fname);
6987 + if (dlinfo.dli_fbase != NULL) {
6988 + st->print(" at " PTR_FORMAT, p2i(dlinfo.dli_fbase));
6990 + st->cr();
6992 + if (Verbose) {
6993 + // decode some bytes around the PC
6994 + address begin = clamp_address_in_page(addr-40, addr, os::vm_page_size());
6995 + address end = clamp_address_in_page(addr+40, addr, os::vm_page_size());
6996 + address lowest = (address) dlinfo.dli_sname;
6997 + if (!lowest) lowest = (address) dlinfo.dli_fbase;
6998 + if (begin < lowest) begin = lowest;
6999 + Dl_info dlinfo2;
7000 + if (dladdr(end, &dlinfo2) != 0 && dlinfo2.dli_saddr != dlinfo.dli_saddr
7001 + && end > dlinfo2.dli_saddr && dlinfo2.dli_saddr > begin) {
7002 + end = (address) dlinfo2.dli_saddr;
7004 + Disassembler::decode(begin, end, st);
7006 + return true;
7008 + return false;
7011 +// Following function has been added to support HotSparc's libjvm.so running
7012 +// under Solaris production JDK 1.2.2 / 1.3.0. These came from
7013 +// src/solaris/hpi/native_threads in the EVM codebase.
7015 +// NOTE: This is no longer needed in the 1.3.1 and 1.4 production release
7016 +// libraries and should thus be removed. We will leave it behind for a while
7017 +// until we no longer want to able to run on top of 1.3.0 Solaris production
7018 +// JDK. See 4341971.
7020 +#define STACK_SLACK 0x800
7022 +extern "C" {
7023 + intptr_t sysThreadAvailableStackWithSlack() {
7024 + stack_t st;
7025 + intptr_t retval, stack_top;
7026 + retval = thr_stksegment(&st);
7027 + assert(retval == 0, "incorrect return value from thr_stksegment");
7028 + assert((address)&st < (address)st.ss_sp, "Invalid stack base returned");
7029 + assert((address)&st > (address)st.ss_sp-st.ss_size, "Invalid stack size returned");
7030 + stack_top=(intptr_t)st.ss_sp-st.ss_size;
7031 + return ((intptr_t)&stack_top - stack_top - STACK_SLACK);
7035 +// ObjectMonitor park-unpark infrastructure ...
7037 +// We implement Solaris and Linux PlatformEvents with the
7038 +// obvious condvar-mutex-flag triple.
7039 +// Another alternative that works quite well is pipes:
7040 +// Each PlatformEvent consists of a pipe-pair.
7041 +// The thread associated with the PlatformEvent
7042 +// calls park(), which reads from the input end of the pipe.
7043 +// Unpark() writes into the other end of the pipe.
7044 +// The write-side of the pipe must be set NDELAY.
7045 +// Unfortunately pipes consume a large # of handles.
7046 +// Native solaris lwp_park() and lwp_unpark() work nicely, too.
7047 +// Using pipes for the 1st few threads might be workable, however.
7049 +// park() is permitted to return spuriously.
7050 +// Callers of park() should wrap the call to park() in
7051 +// an appropriate loop. A litmus test for the correct
7052 +// usage of park is the following: if park() were modified
7053 +// to immediately return 0 your code should still work,
7054 +// albeit degenerating to a spin loop.
7056 +// In a sense, park()-unpark() just provides more polite spinning
7057 +// and polling with the key difference over naive spinning being
7058 +// that a parked thread needs to be explicitly unparked() in order
7059 +// to wake up and to poll the underlying condition.
7061 +// Assumption:
7062 +// Only one parker can exist on an event, which is why we allocate
7063 +// them per-thread. Multiple unparkers can coexist.
7065 +// _event transitions in park()
7066 +// -1 => -1 : illegal
7067 +// 1 => 0 : pass - return immediately
7068 +// 0 => -1 : block; then set _event to 0 before returning
7070 +// _event transitions in unpark()
7071 +// 0 => 1 : just return
7072 +// 1 => 1 : just return
7073 +// -1 => either 0 or 1; must signal target thread
7074 +// That is, we can safely transition _event from -1 to either
7075 +// 0 or 1.
7077 +// _event serves as a restricted-range semaphore.
7078 +// -1 : thread is blocked, i.e. there is a waiter
7079 +// 0 : neutral: thread is running or ready,
7080 +// could have been signaled after a wait started
7081 +// 1 : signaled - thread is running or ready
7083 +// Another possible encoding of _event would be with
7084 +// explicit "PARKED" == 01b and "SIGNALED" == 10b bits.
7086 +// TODO-FIXME: add DTRACE probes for:
7087 +// 1. Tx parks
7088 +// 2. Ty unparks Tx
7089 +// 3. Tx resumes from park
7091 +// JSR166
7092 +// -------------------------------------------------------
7094 +// The solaris and linux implementations of park/unpark are fairly
7095 +// conservative for now, but can be improved. They currently use a
7096 +// mutex/condvar pair, plus _counter.
7097 +// Park decrements _counter if > 0, else does a condvar wait. Unpark
7098 +// sets count to 1 and signals condvar. Only one thread ever waits
7099 +// on the condvar. Contention seen when trying to park implies that someone
7100 +// is unparking you, so don't wait. And spurious returns are fine, so there
7101 +// is no need to track notifications.
7103 +// Get the default path to the core file
7104 +// Returns the length of the string
7105 +int os::get_core_path(char* buffer, size_t bufferSize) {
7106 + const char* p = get_current_directory(buffer, bufferSize);
7108 + if (p == NULL) {
7109 + assert(p != NULL, "failed to get current directory");
7110 + return 0;
7113 + jio_snprintf(buffer, bufferSize, "%s/core or core.%d",
7114 + p, current_process_id());
7116 + return strlen(buffer);
7119 +bool os::supports_map_sync() {
7120 + return false;
7123 +#ifndef PRODUCT
7124 +void TestReserveMemorySpecial_test() {
7125 + // No tests available for this platform
7127 +#endif
7129 +bool os::start_debugging(char *buf, int buflen) {
7130 + int len = (int)strlen(buf);
7131 + char *p = &buf[len];
7133 + jio_snprintf(p, buflen-len,
7134 + "\n\n"
7135 + "Do you want to debug the problem?\n\n"
7136 + "To debug, run 'dbx - %d'; then switch to thread " INTX_FORMAT "\n"
7137 + "Enter 'yes' to launch dbx automatically (PATH must include dbx)\n"
7138 + "Otherwise, press RETURN to abort...",
7139 + os::current_process_id(), os::current_thread_id());
7141 + bool yes = os::message_box("Unexpected Error", buf);
7143 + if (yes) {
7144 + // yes, user asked VM to launch debugger
7145 + jio_snprintf(buf, sizeof(buf), "dbx - %d", os::current_process_id());
7147 + os::fork_and_exec(buf);
7148 + yes = false;
7150 + return yes;
7153 +void os::print_memory_mappings(char* addr, size_t bytes, outputStream* st) {}
7155 +#if INCLUDE_JFR
7157 +void os::jfr_report_memory_info() {}
7159 +#endif // INCLUDE_JFR
7161 +bool os::pd_dll_unload(void* libhandle, char* ebuf, int ebuflen) {
7163 + if (ebuf && ebuflen > 0) {
7164 + ebuf[0] = '\0';
7165 + ebuf[ebuflen - 1] = '\0';
7168 + bool res = (0 == ::dlclose(libhandle));
7169 + if (!res) {
7170 + // error analysis when dlopen fails
7171 + const char* error_report = ::dlerror();
7172 + if (error_report == nullptr) {
7173 + error_report = "dlerror returned no error description";
7175 + if (ebuf != nullptr && ebuflen > 0) {
7176 + snprintf(ebuf, ebuflen - 1, "%s", error_report);
7180 + return res;
7181 +} // end: os::pd_dll_unload()
7182 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os/solaris/os_solaris.hpp jdk21u-jdk-21.0.4-ga/src/hotspot/os/solaris/os_solaris.hpp
7183 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os/solaris/os_solaris.hpp 1970-01-01 01:00:00.000000000 +0100
7184 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/os/solaris/os_solaris.hpp 2024-08-17 19:13:01.449654922 +0200
7185 @@ -0,0 +1,198 @@
7187 + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
7188 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7190 + * This code is free software; you can redistribute it and/or modify it
7191 + * under the terms of the GNU General Public License version 2 only, as
7192 + * published by the Free Software Foundation.
7194 + * This code is distributed in the hope that it will be useful, but WITHOUT
7195 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7196 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7197 + * version 2 for more details (a copy is included in the LICENSE file that
7198 + * accompanied this code).
7200 + * You should have received a copy of the GNU General Public License version
7201 + * 2 along with this work; if not, write to the Free Software Foundation,
7202 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7204 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7205 + * or visit www.oracle.com if you need additional information or have any
7206 + * questions.
7208 + */
7210 +#ifndef OS_SOLARIS_OS_SOLARIS_HPP
7211 +#define OS_SOLARIS_OS_SOLARIS_HPP
7213 +#include "runtime/os.hpp"
7215 +// Solaris_OS defines the interface to Solaris operating systems
7217 +// see thr_setprio(3T) for the basis of these numbers
7218 +#define MinimumPriority 0
7219 +#define NormalPriority 64
7220 +#define MaximumPriority 127
7222 +// FX/60 is critical thread class/priority on T4
7223 +#define FXCriticalPriority 60
7225 +class os::Solaris {
7226 + friend class os;
7228 + private:
7230 + static bool _synchronization_initialized;
7232 + typedef uintptr_t lgrp_cookie_t;
7233 + typedef id_t lgrp_id_t;
7234 + typedef int lgrp_rsrc_t;
7235 + typedef enum lgrp_view {
7236 + LGRP_VIEW_CALLER, // what's available to the caller
7237 + LGRP_VIEW_OS // what's available to operating system
7238 + } lgrp_view_t;
7240 + typedef lgrp_id_t (*lgrp_home_func_t)(idtype_t idtype, id_t id);
7241 + typedef lgrp_cookie_t (*lgrp_init_func_t)(lgrp_view_t view);
7242 + typedef int (*lgrp_fini_func_t)(lgrp_cookie_t cookie);
7243 + typedef lgrp_id_t (*lgrp_root_func_t)(lgrp_cookie_t cookie);
7244 + typedef int (*lgrp_children_func_t)(lgrp_cookie_t cookie, lgrp_id_t parent,
7245 + lgrp_id_t *lgrp_array, uint_t lgrp_array_size);
7246 + typedef int (*lgrp_resources_func_t)(lgrp_cookie_t cookie, lgrp_id_t lgrp,
7247 + lgrp_id_t *lgrp_array, uint_t lgrp_array_size,
7248 + lgrp_rsrc_t type);
7249 + typedef int (*lgrp_nlgrps_func_t)(lgrp_cookie_t cookie);
7250 + typedef int (*lgrp_cookie_stale_func_t)(lgrp_cookie_t cookie);
7252 + static lgrp_home_func_t _lgrp_home;
7253 + static lgrp_init_func_t _lgrp_init;
7254 + static lgrp_fini_func_t _lgrp_fini;
7255 + static lgrp_root_func_t _lgrp_root;
7256 + static lgrp_children_func_t _lgrp_children;
7257 + static lgrp_resources_func_t _lgrp_resources;
7258 + static lgrp_nlgrps_func_t _lgrp_nlgrps;
7259 + static lgrp_cookie_stale_func_t _lgrp_cookie_stale;
7260 + static lgrp_cookie_t _lgrp_cookie;
7262 + // Large Page Support
7263 + static bool is_valid_page_size(size_t bytes);
7264 + static size_t page_size_for_alignment(size_t alignment);
7265 + static bool setup_large_pages(caddr_t start, size_t bytes, size_t align);
7267 + typedef int (*pthread_setname_np_func_t)(pthread_t, const char*);
7268 + static pthread_setname_np_func_t _pthread_setname_np;
7270 + public:
7271 + // Large Page Support--ISM.
7272 + static bool largepage_range(char* addr, size_t size);
7274 + static address handler_start, handler_end; // start and end pc of thr_sighndlrinfo
7276 + static bool valid_ucontext(Thread* thread, const ucontext_t* valid, const ucontext_t* suspect);
7277 + static const ucontext_t* get_valid_uc_in_signal_handler(Thread* thread,
7278 + const ucontext_t* uc);
7280 + static intptr_t* ucontext_get_sp(const ucontext_t* uc);
7281 + // ucontext_get_fp() is only used by Solaris X86 (see note below)
7282 + static intptr_t* ucontext_get_fp(const ucontext_t* uc);
7284 + static bool get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr);
7286 + static void init_thread_fpu_state(void);
7288 + protected:
7289 + // Solaris-specific interface goes here
7290 + static julong available_memory();
7291 + static julong free_memory();
7292 + static julong physical_memory() { return _physical_memory; }
7293 + static julong _physical_memory;
7294 + static void initialize_system_info();
7295 + static int _dev_zero_fd;
7296 + static int get_dev_zero_fd() { return _dev_zero_fd; }
7297 + static void set_dev_zero_fd(int fd) { _dev_zero_fd = fd; }
7298 + static int commit_memory_impl(char* addr, size_t bytes, bool exec);
7299 + static int commit_memory_impl(char* addr, size_t bytes,
7300 + size_t alignment_hint, bool exec);
7301 + static char* mmap_chunk(char *addr, size_t size, int flags, int prot);
7302 + static char* anon_mmap(char* requested_addr, size_t bytes);
7303 + static bool mpss_sanity_check(bool warn, size_t * page_size);
7305 + // Workaround for 4352906. thr_stksegment sometimes returns
7306 + // a bad value for the primordial thread's stack base when
7307 + // it is called more than one time.
7308 + // Workaround is to cache the initial value to avoid further
7309 + // calls to thr_stksegment.
7310 + // It appears that someone (Hotspot?) is trashing the user's
7311 + // proc_t structure (note that this is a system struct).
7312 + static address _main_stack_base;
7314 + static void print_distro_info(outputStream* st);
7315 + static void print_libversion_info(outputStream* st);
7317 + public:
7318 + static void libthread_init();
7319 + static void synchronization_init();
7320 + static bool liblgrp_init();
7322 + // alignment with os_posix means we use pthreads
7323 + static int mutex_lock(pthread_mutex_t *mx) { return pthread_mutex_lock(mx); }
7324 + static int mutex_trylock(pthread_mutex_t *mx) { return pthread_mutex_trylock(mx); }
7325 + static int mutex_unlock(pthread_mutex_t *mx) { return pthread_mutex_unlock(mx); }
7326 + static int mutex_init(pthread_mutex_t *mx) { return pthread_mutex_init(mx, NULL); }
7327 + static int mutex_destroy(pthread_mutex_t *mx) { return pthread_mutex_destroy(mx); }
7329 + static int cond_timedwait(pthread_cond_t *cv, pthread_mutex_t *mx, timestruc_t *abst) { return pthread_cond_timedwait(cv, mx, abst); }
7330 + static int cond_wait(pthread_cond_t *cv, pthread_mutex_t *mx) { return pthread_cond_wait(cv, mx); }
7331 + static int cond_signal(pthread_cond_t *cv) { return pthread_cond_signal(cv); }
7332 + static int cond_broadcast(pthread_cond_t *cv) { return pthread_cond_broadcast(cv); }
7333 + static int cond_init(pthread_cond_t *cv) { return pthread_cond_init(cv, NULL); }
7334 + static int cond_destroy(pthread_cond_t *cv) { return pthread_cond_destroy(cv); }
7336 + static bool synchronization_initialized() { return _synchronization_initialized; }
7338 + static void set_lgrp_home(lgrp_home_func_t func) { _lgrp_home = func; }
7339 + static void set_lgrp_init(lgrp_init_func_t func) { _lgrp_init = func; }
7340 + static void set_lgrp_fini(lgrp_fini_func_t func) { _lgrp_fini = func; }
7341 + static void set_lgrp_root(lgrp_root_func_t func) { _lgrp_root = func; }
7342 + static void set_lgrp_children(lgrp_children_func_t func) { _lgrp_children = func; }
7343 + static void set_lgrp_resources(lgrp_resources_func_t func) { _lgrp_resources = func; }
7344 + static void set_lgrp_nlgrps(lgrp_nlgrps_func_t func) { _lgrp_nlgrps = func; }
7345 + static void set_lgrp_cookie_stale(lgrp_cookie_stale_func_t func) { _lgrp_cookie_stale = func; }
7346 + static void set_lgrp_cookie(lgrp_cookie_t cookie) { _lgrp_cookie = cookie; }
7348 + static id_t lgrp_home(idtype_t type, id_t id) { return _lgrp_home != NULL ? _lgrp_home(type, id) : -1; }
7349 + static lgrp_cookie_t lgrp_init(lgrp_view_t view) { return _lgrp_init != NULL ? _lgrp_init(view) : 0; }
7350 + static int lgrp_fini(lgrp_cookie_t cookie) { return _lgrp_fini != NULL ? _lgrp_fini(cookie) : -1; }
7351 + static lgrp_id_t lgrp_root(lgrp_cookie_t cookie) { return _lgrp_root != NULL ? _lgrp_root(cookie) : -1; }
7352 + static int lgrp_children(lgrp_cookie_t cookie, lgrp_id_t parent,
7353 + lgrp_id_t *lgrp_array, uint_t lgrp_array_size) {
7354 + return _lgrp_children != NULL ? _lgrp_children(cookie, parent, lgrp_array, lgrp_array_size) : -1;
7356 + static int lgrp_resources(lgrp_cookie_t cookie, lgrp_id_t lgrp,
7357 + lgrp_id_t *lgrp_array, uint_t lgrp_array_size,
7358 + lgrp_rsrc_t type) {
7359 + return _lgrp_resources != NULL ? _lgrp_resources(cookie, lgrp, lgrp_array, lgrp_array_size, type) : -1;
7362 + static int lgrp_nlgrps(lgrp_cookie_t cookie) { return _lgrp_nlgrps != NULL ? _lgrp_nlgrps(cookie) : -1; }
7363 + static int lgrp_cookie_stale(lgrp_cookie_t cookie) {
7364 + return _lgrp_cookie_stale != NULL ? _lgrp_cookie_stale(cookie) : -1;
7366 + static lgrp_cookie_t lgrp_cookie() { return _lgrp_cookie; }
7368 + static sigset_t* unblocked_signals();
7369 + static sigset_t* vm_signals();
7371 + // %%% Following should be promoted to os.hpp:
7372 + // Trace number of created threads
7373 + static jint _os_thread_limit;
7374 + static volatile jint _os_thread_count;
7376 + static void correct_stack_boundaries_for_primordial_thread(Thread* thr);
7378 + // Stack repair handling
7380 + // none present
7383 +#endif // OS_SOLARIS_OS_SOLARIS_HPP
7384 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os/solaris/os_solaris.inline.hpp jdk21u-jdk-21.0.4-ga/src/hotspot/os/solaris/os_solaris.inline.hpp
7385 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os/solaris/os_solaris.inline.hpp 1970-01-01 01:00:00.000000000 +0100
7386 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/os/solaris/os_solaris.inline.hpp 2024-08-17 19:13:01.449980029 +0200
7387 @@ -0,0 +1,72 @@
7389 + * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
7390 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7392 + * This code is free software; you can redistribute it and/or modify it
7393 + * under the terms of the GNU General Public License version 2 only, as
7394 + * published by the Free Software Foundation.
7396 + * This code is distributed in the hope that it will be useful, but WITHOUT
7397 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7398 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7399 + * version 2 for more details (a copy is included in the LICENSE file that
7400 + * accompanied this code).
7402 + * You should have received a copy of the GNU General Public License version
7403 + * 2 along with this work; if not, write to the Free Software Foundation,
7404 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7406 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7407 + * or visit www.oracle.com if you need additional information or have any
7408 + * questions.
7410 + */
7412 +#ifndef OS_SOLARIS_OS_SOLARIS_INLINE_HPP
7413 +#define OS_SOLARIS_OS_SOLARIS_INLINE_HPP
7415 +#include "os_solaris.hpp"
7417 +#include "runtime/os.hpp"
7418 +#include "os_posix.inline.hpp"
7420 +// System includes
7421 +#include <sys/param.h>
7422 +#include <dlfcn.h>
7423 +#include <sys/socket.h>
7424 +#include <poll.h>
7425 +#include <sys/filio.h>
7426 +#include <unistd.h>
7427 +#include <netdb.h>
7428 +#include <setjmp.h>
7430 +inline bool os::zero_page_read_protected() {
7431 + return true;
7434 +inline bool os::uses_stack_guard_pages() {
7435 + return true;
7438 +inline bool os::must_commit_stack_guard_pages() {
7439 + assert(uses_stack_guard_pages(), "sanity check");
7440 + int r = thr_main() ;
7441 + guarantee (r == 0 || r == 1, "CR6501650 or CR6493689") ;
7442 + return r;
7446 +// Bang the shadow pages if they need to be touched to be mapped.
7447 +inline void os::map_stack_shadow_pages(address sp) {
7450 +// Trim-native support, stubbed out for now, may be enabled later
7451 +inline bool os::can_trim_native_heap() { return false; }
7452 +inline bool os::trim_native_heap(os::size_change_t* rss_change) { return false; }
7454 +//////////////////////////////////////////////////////////////////////////////
7455 +////////////////////////////////////////////////////////////////////////////////
7457 +inline bool os::numa_has_group_homing() { return true; }
7459 +#endif // OS_SOLARIS_OS_SOLARIS_INLINE_HPP
7460 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os/solaris/osThread_solaris.cpp jdk21u-jdk-21.0.4-ga/src/hotspot/os/solaris/osThread_solaris.cpp
7461 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os/solaris/osThread_solaris.cpp 1970-01-01 01:00:00.000000000 +0100
7462 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/os/solaris/osThread_solaris.cpp 2024-08-17 19:13:01.445893448 +0200
7463 @@ -0,0 +1,47 @@
7465 + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
7466 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7468 + * This code is free software; you can redistribute it and/or modify it
7469 + * under the terms of the GNU General Public License version 2 only, as
7470 + * published by the Free Software Foundation.
7472 + * This code is distributed in the hope that it will be useful, but WITHOUT
7473 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7474 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7475 + * version 2 for more details (a copy is included in the LICENSE file that
7476 + * accompanied this code).
7478 + * You should have received a copy of the GNU General Public License version
7479 + * 2 along with this work; if not, write to the Free Software Foundation,
7480 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7482 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7483 + * or visit www.oracle.com if you need additional information or have any
7484 + * questions.
7486 + */
7488 +// no precompiled headers
7489 +#include "runtime/handles.inline.hpp"
7490 +#include "runtime/mutexLocker.hpp"
7491 +#include "runtime/os.hpp"
7492 +#include "runtime/osThread.hpp"
7493 +#include "runtime/safepoint.hpp"
7494 +#include "runtime/vmThread.hpp"
7496 +#include <signal.h>
7498 + // ***************************************************************
7499 + // Platform dependent initialization and cleanup
7500 + // ***************************************************************
7502 +void OSThread::pd_initialize() {
7503 + _thread_id = 0;
7504 + sigemptyset(&_caller_sigmask);
7506 + _vm_created_thread = false;
7509 +void OSThread::pd_destroy() {
7511 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os/solaris/osThread_solaris.hpp jdk21u-jdk-21.0.4-ga/src/hotspot/os/solaris/osThread_solaris.hpp
7512 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os/solaris/osThread_solaris.hpp 1970-01-01 01:00:00.000000000 +0100
7513 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/os/solaris/osThread_solaris.hpp 2024-08-17 19:13:01.446222084 +0200
7514 @@ -0,0 +1,93 @@
7516 + * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
7517 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7519 + * This code is free software; you can redistribute it and/or modify it
7520 + * under the terms of the GNU General Public License version 2 only, as
7521 + * published by the Free Software Foundation.
7523 + * This code is distributed in the hope that it will be useful, but WITHOUT
7524 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7525 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7526 + * version 2 for more details (a copy is included in the LICENSE file that
7527 + * accompanied this code).
7529 + * You should have received a copy of the GNU General Public License version
7530 + * 2 along with this work; if not, write to the Free Software Foundation,
7531 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7533 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7534 + * or visit www.oracle.com if you need additional information or have any
7535 + * questions.
7537 + */
7539 +#ifndef OS_SOLARIS_OSTHREAD_SOLARIS_HPP
7540 +#define OS_SOLARIS_OSTHREAD_SOLARIS_HPP
7542 +// This is embedded via include into the class OSThread
7543 + public:
7544 + typedef thread_t thread_id_t;
7546 + private:
7547 + uint _lwp_id; // lwp ID, only used with bound threads
7548 + int _native_priority; // Saved native priority when starting
7549 + // a bound thread
7550 + sigset_t _caller_sigmask; // Caller's signal mask
7551 + bool _vm_created_thread; // true if the VM created this thread,
7552 + // false if primary thread or attached thread
7553 + public:
7554 + uint lwp_id() const { return _lwp_id; }
7555 + int native_priority() const { return _native_priority; }
7557 + // Set and get state of _vm_created_thread flag
7558 + void set_vm_created() { _vm_created_thread = true; }
7559 + bool is_vm_created() { return _vm_created_thread; }
7561 + // Methods to save/restore caller's signal mask
7562 + sigset_t caller_sigmask() const { return _caller_sigmask; }
7563 + void set_caller_sigmask(sigset_t sigmask) { _caller_sigmask = sigmask; }
7565 +#ifndef PRODUCT
7566 + // Used for debugging, return a unique integer for each thread.
7567 + int thread_identifier() const { return _thread_id; }
7568 +#endif
7569 +#ifdef ASSERT
7570 + // On solaris reposition can fail in two ways:
7571 + // 1: a mismatched pc, because signal is delivered too late, target thread
7572 + // is resumed.
7573 + // 2: on a timeout where signal is lost, target thread is resumed.
7574 + bool valid_reposition_failure() {
7575 + // only 1 and 2 can happen and we can handle both of them
7576 + return true;
7578 +#endif
7579 + void set_lwp_id(uint id) { _lwp_id = id; }
7580 + void set_native_priority(int prio) { _native_priority = prio; }
7582 + public:
7583 + pthread_t pthread_id() const {
7584 + // Here: same as OSThread::thread_id()
7585 + return _thread_id;
7587 + SuspendResume sr;
7589 + private:
7590 + void* _siginfo;
7591 + ucontext_t* _ucontext;
7593 + public:
7594 + void set_siginfo(void* ptr) { _siginfo = ptr; }
7595 + ucontext_t* ucontext() const { return _ucontext; }
7596 + void set_ucontext(ucontext_t* ptr) { _ucontext = ptr; }
7598 + // ***************************************************************
7599 + // Platform dependent initialization and cleanup
7600 + // ***************************************************************
7602 +private:
7604 + void pd_initialize();
7605 + void pd_destroy();
7607 +#endif // OS_SOLARIS_OSTHREAD_SOLARIS_HPP
7608 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os/solaris/vmStructs_solaris.hpp jdk21u-jdk-21.0.4-ga/src/hotspot/os/solaris/vmStructs_solaris.hpp
7609 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os/solaris/vmStructs_solaris.hpp 1970-01-01 01:00:00.000000000 +0100
7610 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/os/solaris/vmStructs_solaris.hpp 2024-08-17 19:13:01.450287894 +0200
7611 @@ -0,0 +1,44 @@
7613 + * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
7614 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7616 + * This code is free software; you can redistribute it and/or modify it
7617 + * under the terms of the GNU General Public License version 2 only, as
7618 + * published by the Free Software Foundation.
7620 + * This code is distributed in the hope that it will be useful, but WITHOUT
7621 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7622 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7623 + * version 2 for more details (a copy is included in the LICENSE file that
7624 + * accompanied this code).
7626 + * You should have received a copy of the GNU General Public License version
7627 + * 2 along with this work; if not, write to the Free Software Foundation,
7628 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7630 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7631 + * or visit www.oracle.com if you need additional information or have any
7632 + * questions.
7634 + */
7636 +#ifndef OS_SOLARIS_VMSTRUCTS_SOLARIS_HPP
7637 +#define OS_SOLARIS_VMSTRUCTS_SOLARIS_HPP
7639 +// These are the OS-specific fields, types and integer
7640 +// constants required by the Serviceability Agent. This file is
7641 +// referenced by vmStructs.cpp.
7643 +#define VM_STRUCTS_OS(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \
7644 + nonstatic_field(OSThread, _thread_id, OSThread::thread_id_t)
7646 +#define VM_TYPES_OS(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \
7647 + declare_unsigned_integer_type(OSThread::thread_id_t)
7649 +#define VM_INT_CONSTANTS_OS(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
7651 +#define VM_LONG_CONSTANTS_OS(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
7653 +#define VM_ADDRESSES_OS(declare_address, declare_preprocessor_address, declare_function)
7655 +#endif // OS_SOLARIS_VMSTRUCTS_SOLARIS_HPP
7656 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os_cpu/solaris_x86/assembler_solaris_x86.cpp jdk21u-jdk-21.0.4-ga/src/hotspot/os_cpu/solaris_x86/assembler_solaris_x86.cpp
7657 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os_cpu/solaris_x86/assembler_solaris_x86.cpp 1970-01-01 01:00:00.000000000 +0100
7658 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/os_cpu/solaris_x86/assembler_solaris_x86.cpp 2024-08-17 19:13:01.450717403 +0200
7659 @@ -0,0 +1,37 @@
7661 + * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
7662 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7664 + * This code is free software; you can redistribute it and/or modify it
7665 + * under the terms of the GNU General Public License version 2 only, as
7666 + * published by the Free Software Foundation.
7668 + * This code is distributed in the hope that it will be useful, but WITHOUT
7669 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7670 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7671 + * version 2 for more details (a copy is included in the LICENSE file that
7672 + * accompanied this code).
7674 + * You should have received a copy of the GNU General Public License version
7675 + * 2 along with this work; if not, write to the Free Software Foundation,
7676 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7678 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7679 + * or visit www.oracle.com if you need additional information or have any
7680 + * questions.
7682 + */
7684 +#include "precompiled.hpp"
7685 +#include "asm/macroAssembler.inline.hpp"
7686 +#include "runtime/os.hpp"
7688 +void MacroAssembler::int3() {
7689 + push(rax);
7690 + push(rdx);
7691 + push(rcx);
7692 + call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint)));
7693 + pop(rcx);
7694 + pop(rdx);
7695 + pop(rax);
7697 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os_cpu/solaris_x86/atomic_solaris_x86.hpp jdk21u-jdk-21.0.4-ga/src/hotspot/os_cpu/solaris_x86/atomic_solaris_x86.hpp
7698 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os_cpu/solaris_x86/atomic_solaris_x86.hpp 1970-01-01 01:00:00.000000000 +0100
7699 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/os_cpu/solaris_x86/atomic_solaris_x86.hpp 2024-08-17 19:13:01.451108983 +0200
7700 @@ -0,0 +1,182 @@
7702 + * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
7703 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7705 + * This code is free software; you can redistribute it and/or modify it
7706 + * under the terms of the GNU General Public License version 2 only, as
7707 + * published by the Free Software Foundation.
7709 + * This code is distributed in the hope that it will be useful, but WITHOUT
7710 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7711 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7712 + * version 2 for more details (a copy is included in the LICENSE file that
7713 + * accompanied this code).
7715 + * You should have received a copy of the GNU General Public License version
7716 + * 2 along with this work; if not, write to the Free Software Foundation,
7717 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7719 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7720 + * or visit www.oracle.com if you need additional information or have any
7721 + * questions.
7723 + */
7725 +#ifndef OS_CPU_SOLARIS_X86_ATOMIC_SOLARIS_X86_HPP
7726 +#define OS_CPU_SOLARIS_X86_ATOMIC_SOLARIS_X86_HPP
7728 +inline int32_t _Atomic_add(int32_t add_value, volatile int32_t* dest) {
7729 + int32_t rv = add_value;
7730 + __asm__ volatile ("lock xaddl %0,(%2)"
7731 + : "=r" (rv)
7732 + : "0" (rv), "r" (dest)
7733 + : "cc", "memory");
7734 + return rv + add_value;
7736 +inline int64_t _Atomic_add_long(int64_t add_value, volatile int64_t* dest) {
7737 + int64_t rv = add_value;
7738 + __asm__ volatile ("lock xaddq %0,(%2)"
7739 + : "=r" (rv)
7740 + : "0" (rv), "r" (dest)
7741 + : "cc", "memory");
7742 + return rv + add_value;
7744 +inline int32_t _Atomic_xchg(int32_t exchange_value, volatile int32_t* dest) {
7745 + __asm__ __volatile__ ("xchgl (%2),%0"
7746 + : "=r" (exchange_value)
7747 + : "0" (exchange_value), "r" (dest)
7748 + : "memory");
7749 + return exchange_value;
7751 +inline int64_t _Atomic_xchg_long(int64_t exchange_value, volatile int64_t* dest) {
7752 + __asm__ __volatile__ ("xchgq (%2),%0"
7753 + : "=r" (exchange_value)
7754 + : "0" (exchange_value), "r" (dest)
7755 + : "memory");
7756 + return exchange_value;
7758 +inline int8_t _Atomic_cmpxchg_byte(int8_t exchange_value, volatile int8_t* dest, int8_t compare_value) {
7759 + __asm__ volatile ("lock cmpxchgb %1,(%3)"
7760 + : "=a" (exchange_value)
7761 + : "q" (exchange_value), "a" (compare_value), "r" (dest)
7762 + : "cc", "memory");
7763 + return exchange_value;
7765 +inline int32_t _Atomic_cmpxchg(int32_t exchange_value, volatile int32_t* dest, int32_t compare_value) {
7766 + __asm__ volatile ("lock cmpxchgl %1,(%3)"
7767 + : "=a" (exchange_value)
7768 + : "q" (exchange_value), "a" (compare_value), "r" (dest)
7769 + : "cc", "memory");
7770 + return exchange_value;
7772 +inline int64_t _Atomic_cmpxchg_long(int64_t exchange_value, volatile int64_t* dest, int64_t compare_value) {
7773 + __asm__ volatile ("lock cmpxchgq %1,(%3)"
7774 + : "=a" (exchange_value)
7775 + : "q" (exchange_value), "a" (compare_value), "r" (dest)
7776 + : "cc", "memory");
7777 + return exchange_value;
7780 +template<size_t byte_size>
7781 +struct Atomic::PlatformAdd {
7782 + template<typename D, typename I>
7783 + D add_then_fetch(D volatile* dest, I add_value, atomic_memory_order order) const;
7785 + template<typename D, typename I>
7786 + D fetch_then_add(D volatile* dest, I add_value, atomic_memory_order order) const {
7787 + return add_then_fetch(dest, add_value, order) - add_value;
7791 +// Not using add_using_helper; see comment for cmpxchg.
7792 +template<>
7793 +template<typename D, typename I>
7794 +inline D Atomic::PlatformAdd<4>::add_then_fetch(D volatile* dest, I add_value,
7795 + atomic_memory_order order) const {
7796 + STATIC_ASSERT(4 == sizeof(I));
7797 + STATIC_ASSERT(4 == sizeof(D));
7798 + return PrimitiveConversions::cast<D>(
7799 + _Atomic_add(PrimitiveConversions::cast<int32_t>(add_value),
7800 + reinterpret_cast<int32_t volatile*>(dest)));
7803 +// Not using add_using_helper; see comment for cmpxchg.
7804 +template<>
7805 +template<typename D, typename I>
7806 +inline D Atomic::PlatformAdd<8>::add_then_fetch(D volatile* dest, I add_value,
7807 + atomic_memory_order order) const {
7808 + STATIC_ASSERT(8 == sizeof(I));
7809 + STATIC_ASSERT(8 == sizeof(D));
7810 + return PrimitiveConversions::cast<D>(
7811 + _Atomic_add_long(PrimitiveConversions::cast<int64_t>(add_value),
7812 + reinterpret_cast<int64_t volatile*>(dest)));
7815 +template<>
7816 +template<typename T>
7817 +inline T Atomic::PlatformXchg<4>::operator()(T volatile* dest,
7818 + T exchange_value,
7819 + atomic_memory_order order) const {
7820 + STATIC_ASSERT(4 == sizeof(T));
7821 + return PrimitiveConversions::cast<T>(
7822 + _Atomic_xchg(PrimitiveConversions::cast<int32_t>(exchange_value),
7823 + reinterpret_cast<int32_t volatile*>(dest)));
7826 +template<>
7827 +template<typename T>
7828 +inline T Atomic::PlatformXchg<8>::operator()(T volatile* dest,
7829 + T exchange_value,
7830 + atomic_memory_order order) const {
7831 + STATIC_ASSERT(8 == sizeof(T));
7832 + return PrimitiveConversions::cast<T>(
7833 + _Atomic_xchg_long(PrimitiveConversions::cast<int64_t>(exchange_value),
7834 + reinterpret_cast<int64_t volatile*>(dest)));
7837 +// Not using cmpxchg_using_helper here, because some configurations of
7838 +// Solaris compiler don't deal well with passing a "defined in .il"
7839 +// function as an argument. We *should* switch to using gcc-style
7840 +// inline assembly, but attempting to do so with Studio 12.4 ran into
7841 +// segfaults.
7843 +template<>
7844 +template<typename T>
7845 +inline T Atomic::PlatformCmpxchg<1>::operator()(T volatile* dest,
7846 + T compare_value,
7847 + T exchange_value,
7848 + atomic_memory_order order) const {
7849 + STATIC_ASSERT(1 == sizeof(T));
7850 + return PrimitiveConversions::cast<T>(
7851 + _Atomic_cmpxchg_byte(PrimitiveConversions::cast<int8_t>(exchange_value),
7852 + reinterpret_cast<int8_t volatile*>(dest),
7853 + PrimitiveConversions::cast<int8_t>(compare_value)));
7856 +template<>
7857 +template<typename T>
7858 +inline T Atomic::PlatformCmpxchg<4>::operator()(T volatile* dest,
7859 + T compare_value,
7860 + T exchange_value,
7861 + atomic_memory_order order) const {
7862 + STATIC_ASSERT(4 == sizeof(T));
7863 + return PrimitiveConversions::cast<T>(
7864 + _Atomic_cmpxchg(PrimitiveConversions::cast<int32_t>(exchange_value),
7865 + reinterpret_cast<int32_t volatile*>(dest),
7866 + PrimitiveConversions::cast<int32_t>(compare_value)));
7869 +template<>
7870 +template<typename T>
7871 +inline T Atomic::PlatformCmpxchg<8>::operator()(T volatile* dest,
7872 + T compare_value,
7873 + T exchange_value,
7874 + atomic_memory_order order) const {
7875 + STATIC_ASSERT(8 == sizeof(T));
7876 + return PrimitiveConversions::cast<T>(
7877 + _Atomic_cmpxchg_long(PrimitiveConversions::cast<int64_t>(exchange_value),
7878 + reinterpret_cast<int64_t volatile*>(dest),
7879 + PrimitiveConversions::cast<int64_t>(compare_value)));
7882 +#endif // OS_CPU_SOLARIS_X86_ATOMIC_SOLARIS_X86_HPP
7883 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os_cpu/solaris_x86/bytes_solaris_x86.hpp jdk21u-jdk-21.0.4-ga/src/hotspot/os_cpu/solaris_x86/bytes_solaris_x86.hpp
7884 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os_cpu/solaris_x86/bytes_solaris_x86.hpp 1970-01-01 01:00:00.000000000 +0100
7885 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/os_cpu/solaris_x86/bytes_solaris_x86.hpp 2024-08-17 19:13:01.451426037 +0200
7886 @@ -0,0 +1,60 @@
7888 + * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
7889 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7891 + * This code is free software; you can redistribute it and/or modify it
7892 + * under the terms of the GNU General Public License version 2 only, as
7893 + * published by the Free Software Foundation.
7895 + * This code is distributed in the hope that it will be useful, but WITHOUT
7896 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7897 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7898 + * version 2 for more details (a copy is included in the LICENSE file that
7899 + * accompanied this code).
7901 + * You should have received a copy of the GNU General Public License version
7902 + * 2 along with this work; if not, write to the Free Software Foundation,
7903 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7905 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7906 + * or visit www.oracle.com if you need additional information or have any
7907 + * questions.
7909 + */
7911 +#ifndef OS_CPU_SOLARIS_X86_BYTES_SOLARIS_X86_HPP
7912 +#define OS_CPU_SOLARIS_X86_BYTES_SOLARIS_X86_HPP
7914 +extern "C" {
7915 + inline u2 _raw_swap_u2(u2 x) {
7916 + unsigned short int __dest;
7917 + __asm__ ("rorw $8, %w0": "=r" (__dest): "0" (x): "cc");
7918 + return __dest;
7920 + inline u4 _raw_swap_u4(u4 x) {
7921 + unsigned int __dest;
7922 + __asm__ ("bswap %0" : "=r" (__dest) : "0" (x));
7923 + return __dest;
7925 + inline u8 _raw_swap_u8(u8 x) {
7926 + unsigned long __dest;
7927 + __asm__ ("bswap %q0" : "=r" (__dest) : "0" (x));
7928 + return __dest;
7932 +// Efficient swapping of data bytes from Java byte
7933 +// ordering to native byte ordering and vice versa.
7934 +inline u2 Bytes::swap_u2(u2 x) {
7935 + return _raw_swap_u2(x);
7938 +inline u4 Bytes::swap_u4(u4 x) {
7939 + return _raw_swap_u4(x);
7942 +inline u8 Bytes::swap_u8(u8 x) {
7943 + return _raw_swap_u8(x);
7946 +#endif // OS_CPU_SOLARIS_X86_BYTES_SOLARIS_X86_HPP
7947 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os_cpu/solaris_x86/copy_solaris_x86.hpp jdk21u-jdk-21.0.4-ga/src/hotspot/os_cpu/solaris_x86/copy_solaris_x86.hpp
7948 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os_cpu/solaris_x86/copy_solaris_x86.hpp 1970-01-01 01:00:00.000000000 +0100
7949 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/os_cpu/solaris_x86/copy_solaris_x86.hpp 2024-08-17 19:13:01.451714872 +0200
7950 @@ -0,0 +1,30 @@
7952 + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
7953 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7955 + * This code is free software; you can redistribute it and/or modify it
7956 + * under the terms of the GNU General Public License version 2 only, as
7957 + * published by the Free Software Foundation.
7959 + * This code is distributed in the hope that it will be useful, but WITHOUT
7960 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7961 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7962 + * version 2 for more details (a copy is included in the LICENSE file that
7963 + * accompanied this code).
7965 + * You should have received a copy of the GNU General Public License version
7966 + * 2 along with this work; if not, write to the Free Software Foundation,
7967 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7969 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7970 + * or visit www.oracle.com if you need additional information or have any
7971 + * questions.
7973 + */
7975 +#ifndef OS_CPU_SOLARIS_X86_COPY_SOLARIS_X86_HPP
7976 +#define OS_CPU_SOLARIS_X86_COPY_SOLARIS_X86_HPP
7978 +// now in central copy_x86.hpp
7980 +#endif // OS_CPU_SOLARIS_X86_COPY_SOLARIS_X86_HPP
7981 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os_cpu/solaris_x86/globals_solaris_x86.hpp jdk21u-jdk-21.0.4-ga/src/hotspot/os_cpu/solaris_x86/globals_solaris_x86.hpp
7982 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os_cpu/solaris_x86/globals_solaris_x86.hpp 1970-01-01 01:00:00.000000000 +0100
7983 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/os_cpu/solaris_x86/globals_solaris_x86.hpp 2024-08-17 19:13:01.452006572 +0200
7984 @@ -0,0 +1,40 @@
7986 + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
7987 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7989 + * This code is free software; you can redistribute it and/or modify it
7990 + * under the terms of the GNU General Public License version 2 only, as
7991 + * published by the Free Software Foundation.
7993 + * This code is distributed in the hope that it will be useful, but WITHOUT
7994 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7995 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7996 + * version 2 for more details (a copy is included in the LICENSE file that
7997 + * accompanied this code).
7999 + * You should have received a copy of the GNU General Public License version
8000 + * 2 along with this work; if not, write to the Free Software Foundation,
8001 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
8003 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
8004 + * or visit www.oracle.com if you need additional information or have any
8005 + * questions.
8007 + */
8009 +#ifndef OS_CPU_SOLARIS_X86_GLOBALS_SOLARIS_X86_HPP
8010 +#define OS_CPU_SOLARIS_X86_GLOBALS_SOLARIS_X86_HPP
8012 +// Sets the default values for platform dependent flags used by the runtime system.
8013 +// (see globals.hpp)
8015 +define_pd_global(bool, DontYieldALot, true); // Determined in the design center
8016 +define_pd_global(intx, CompilerThreadStackSize, 1024);
8017 +define_pd_global(intx, ThreadStackSize, 1024); // 0 => use system default
8018 +define_pd_global(intx, VMThreadStackSize, 1024);
8019 +define_pd_global(size_t, JVMInvokeMethodSlack, 8*K);
8021 +// Used on 64 bit platforms for UseCompressedOops base address
8022 +define_pd_global(size_t, HeapBaseMinAddress, 2*G);
8024 +#endif // OS_CPU_SOLARIS_X86_GLOBALS_SOLARIS_X86_HPP
8025 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os_cpu/solaris_x86/javaThread_solaris_x86.cpp jdk21u-jdk-21.0.4-ga/src/hotspot/os_cpu/solaris_x86/javaThread_solaris_x86.cpp
8026 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os_cpu/solaris_x86/javaThread_solaris_x86.cpp 1970-01-01 01:00:00.000000000 +0100
8027 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/os_cpu/solaris_x86/javaThread_solaris_x86.cpp 2024-08-17 19:13:01.454660318 +0200
8028 @@ -0,0 +1,97 @@
8030 + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
8031 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8033 + * This code is free software; you can redistribute it and/or modify it
8034 + * under the terms of the GNU General Public License version 2 only, as
8035 + * published by the Free Software Foundation.
8037 + * This code is distributed in the hope that it will be useful, but WITHOUT
8038 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8039 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
8040 + * version 2 for more details (a copy is included in the LICENSE file that
8041 + * accompanied this code).
8043 + * You should have received a copy of the GNU General Public License version
8044 + * 2 along with this work; if not, write to the Free Software Foundation,
8045 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
8047 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
8048 + * or visit www.oracle.com if you need additional information or have any
8049 + * questions.
8051 + */
8053 +#include "precompiled.hpp"
8054 +#include "runtime/frame.inline.hpp"
8055 +#include "runtime/javaThread.hpp"
8057 +frame JavaThread::pd_last_frame() {
8058 + assert(has_last_Java_frame(), "must have last_Java_sp() when suspended");
8059 + vmassert(_anchor.last_Java_pc() != NULL, "not walkable");
8060 + return frame(_anchor.last_Java_sp(), _anchor.last_Java_fp(), _anchor.last_Java_pc());
8063 +// For Forte Analyzer AsyncGetCallTrace profiling support - thread is
8064 +// currently interrupted by SIGPROF
8065 +bool JavaThread::pd_get_top_frame_for_signal_handler(frame* fr_addr,
8066 + void* ucontext, bool isInJava) {
8067 + assert(Thread::current() == this, "caller must be current thread");
8068 + return pd_get_top_frame(fr_addr, ucontext, isInJava);
8071 +bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr,
8072 + void* ucontext, bool isInJava) {
8073 + return pd_get_top_frame(fr_addr, ucontext, isInJava);
8076 +bool JavaThread::pd_get_top_frame(frame* fr_addr,
8077 + void* ucontext, bool isInJava) {
8078 + assert(this->is_Java_thread(), "must be JavaThread");
8079 + JavaThread* jt = (JavaThread *)this;
8081 + // There is small window where last_Java_frame is not walkable or safe
8082 + if (jt->has_last_Java_frame() && jt->frame_anchor()->walkable()) {
8083 + *fr_addr = jt->pd_last_frame();
8084 + return true;
8087 + ucontext_t* uc = (ucontext_t*) ucontext;
8089 + // We always want to use the initial frame we create from the ucontext as
8090 + // it certainly signals where we currently are. However that frame may not
8091 + // be safe for calling sender. In that case if we have a last_Java_frame
8092 + // then the forte walker will switch to that frame as the virtual sender
8093 + // for the frame we create here which is not sender safe.
8095 + intptr_t* ret_fp;
8096 + intptr_t* ret_sp;
8097 + address addr = os::fetch_frame_from_context(uc, &ret_sp, &ret_fp);
8099 + // Something would really have to be screwed up to get a NULL pc
8101 + if (addr == NULL) {
8102 + // ucontext wasn't useful
8103 + return false;
8106 + // If sp and fp are nonsense just leave them out
8108 + if (!jt->is_in_full_stack((address)ret_sp)) {
8109 + ret_sp = NULL;
8110 + ret_fp = NULL;
8111 + } else {
8112 + // sp is reasonable is fp reasonable?
8113 + if (!jt->is_in_stack_range_incl((address)ret_fp, (address)ret_sp)) {
8114 + ret_fp = NULL;
8118 + frame ret_frame(ret_sp, ret_fp, addr);
8120 + *fr_addr = ret_frame;
8121 + return true;
8125 +void JavaThread::cache_global_variables() { }
8126 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os_cpu/solaris_x86/javaThread_solaris_x86.hpp jdk21u-jdk-21.0.4-ga/src/hotspot/os_cpu/solaris_x86/javaThread_solaris_x86.hpp
8127 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os_cpu/solaris_x86/javaThread_solaris_x86.hpp 1970-01-01 01:00:00.000000000 +0100
8128 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/os_cpu/solaris_x86/javaThread_solaris_x86.hpp 2024-08-17 19:13:01.454966776 +0200
8129 @@ -0,0 +1,59 @@
8131 + * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
8132 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8134 + * This code is free software; you can redistribute it and/or modify it
8135 + * under the terms of the GNU General Public License version 2 only, as
8136 + * published by the Free Software Foundation.
8138 + * This code is distributed in the hope that it will be useful, but WITHOUT
8139 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8140 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
8141 + * version 2 for more details (a copy is included in the LICENSE file that
8142 + * accompanied this code).
8144 + * You should have received a copy of the GNU General Public License version
8145 + * 2 along with this work; if not, write to the Free Software Foundation,
8146 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
8148 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
8149 + * or visit www.oracle.com if you need additional information or have any
8150 + * questions.
8152 + */
8154 +#ifndef OS_CPU_SOLARIS_X86_JAVATHREAD_SOLARIS_X86_HPP
8155 +#define OS_CPU_SOLARIS_X86_JAVATHREAD_SOLARIS_X86_HPP
8157 + private:
8158 + void pd_initialize() { _anchor.clear(); }
8160 + frame pd_last_frame();
8162 + public:
8164 + void set_base_of_stack_pointer(intptr_t* base_sp) {}
8166 + static ByteSize last_Java_fp_offset() {
8167 + return byte_offset_of(JavaThread, _anchor) + JavaFrameAnchor::last_Java_fp_offset();
8170 + intptr_t* base_of_stack_pointer() { return NULL; }
8171 + void record_base_of_stack_pointer() {}
8173 + bool pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext,
8174 + bool isInJava);
8175 + bool pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext,
8176 + bool isInJava);
8177 +private:
8178 + bool pd_get_top_frame(frame* fr_addr, void* ucontext,
8179 + bool isInJava);
8180 +public:
8182 + // These routines are only used on cpu architectures that
8183 + // have separate register stacks (Itanium).
8184 + static bool register_stack_overflow() { return false; }
8185 + static void enable_register_stack_guard() {}
8186 + static void disable_register_stack_guard() {}
8188 +#endif // OS_CPU_SOLARIS_X86_JAVATHREAD_SOLARIS_X86_HPP
8189 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os_cpu/solaris_x86/orderAccess_solaris_x86.hpp jdk21u-jdk-21.0.4-ga/src/hotspot/os_cpu/solaris_x86/orderAccess_solaris_x86.hpp
8190 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os_cpu/solaris_x86/orderAccess_solaris_x86.hpp 1970-01-01 01:00:00.000000000 +0100
8191 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/os_cpu/solaris_x86/orderAccess_solaris_x86.hpp 2024-08-17 19:13:01.452307723 +0200
8192 @@ -0,0 +1,58 @@
8194 + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
8195 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8197 + * This code is free software; you can redistribute it and/or modify it
8198 + * under the terms of the GNU General Public License version 2 only, as
8199 + * published by the Free Software Foundation.
8201 + * This code is distributed in the hope that it will be useful, but WITHOUT
8202 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8203 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
8204 + * version 2 for more details (a copy is included in the LICENSE file that
8205 + * accompanied this code).
8207 + * You should have received a copy of the GNU General Public License version
8208 + * 2 along with this work; if not, write to the Free Software Foundation,
8209 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
8211 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
8212 + * or visit www.oracle.com if you need additional information or have any
8213 + * questions.
8215 + */
8217 +#ifndef OS_CPU_SOLARIS_X86_ORDERACCESS_SOLARIS_X86_HPP
8218 +#define OS_CPU_SOLARIS_X86_ORDERACCESS_SOLARIS_X86_HPP
8220 +// Included in orderAccess.hpp header file.
8222 +// Compiler version last used for testing: solaris studio 12u3
8223 +// Please update this information when this file changes
8225 +// Implementation of class OrderAccess.
8227 +// A compiler barrier, forcing the C++ compiler to invalidate all memory assumptions
8228 +inline void compiler_barrier() {
8229 + __asm__ volatile ("" : : : "memory");
8232 +inline void OrderAccess::loadload() { compiler_barrier(); }
8233 +inline void OrderAccess::storestore() { compiler_barrier(); }
8234 +inline void OrderAccess::loadstore() { compiler_barrier(); }
8235 +inline void OrderAccess::storeload() { fence(); }
8237 +inline void OrderAccess::acquire() { compiler_barrier(); }
8238 +inline void OrderAccess::release() { compiler_barrier(); }
8240 +inline void OrderAccess::fence() {
8241 + __asm__ volatile ("lock; addl $0,0(%%rsp)" : : : "cc", "memory");
8242 + compiler_barrier();
8245 +inline void OrderAccess::cross_modify_fence_impl() {
8246 + int idx = 0;
8247 + __asm__ volatile ("cpuid " : "+a" (idx) : : "ebx", "ecx", "edx", "memory");
8250 +#endif // OS_CPU_SOLARIS_X86_ORDERACCESS_SOLARIS_X86_HPP
8251 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.cpp jdk21u-jdk-21.0.4-ga/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.cpp
8252 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.cpp 1970-01-01 01:00:00.000000000 +0100
8253 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.cpp 2024-08-17 19:13:01.452956809 +0200
8254 @@ -0,0 +1,662 @@
8256 + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.
8257 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8259 + * This code is free software; you can redistribute it and/or modify it
8260 + * under the terms of the GNU General Public License version 2 only, as
8261 + * published by the Free Software Foundation.
8263 + * This code is distributed in the hope that it will be useful, but WITHOUT
8264 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8265 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
8266 + * version 2 for more details (a copy is included in the LICENSE file that
8267 + * accompanied this code).
8269 + * You should have received a copy of the GNU General Public License version
8270 + * 2 along with this work; if not, write to the Free Software Foundation,
8271 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
8273 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
8274 + * or visit www.oracle.com if you need additional information or have any
8275 + * questions.
8277 + */
8279 +// no precompiled headers
8280 +#include "jvm.h"
8281 +#include "asm/macroAssembler.hpp"
8282 +#include "classfile/classLoader.hpp"
8283 +#include "classfile/systemDictionary.hpp"
8284 +#include "classfile/vmSymbols.hpp"
8285 +#include "code/codeCache.hpp"
8286 +#include "code/icBuffer.hpp"
8287 +#include "code/vtableStubs.hpp"
8288 +#include "interpreter/interpreter.hpp"
8289 +#include "logging/log.hpp"
8290 +#include "memory/allocation.inline.hpp"
8291 +#include "os_solaris.hpp"
8292 +#include "os_posix.hpp"
8293 +#include "prims/jniFastGetField.hpp"
8294 +#include "prims/jvm_misc.hpp"
8295 +#include "runtime/arguments.hpp"
8296 +#include "runtime/frame.inline.hpp"
8297 +#include "runtime/interfaceSupport.inline.hpp"
8298 +#include "runtime/java.hpp"
8299 +#include "runtime/javaCalls.hpp"
8300 +#include "runtime/mutexLocker.hpp"
8301 +#include "runtime/osThread.hpp"
8302 +#include "runtime/safepointMechanism.hpp"
8303 +#include "runtime/sharedRuntime.hpp"
8304 +#include "runtime/stubRoutines.hpp"
8305 +#include "runtime/thread.inline.hpp"
8306 +#include "runtime/timer.hpp"
8307 +#include "signals_posix.hpp"
8308 +#include "utilities/align.hpp"
8309 +#include "utilities/events.hpp"
8310 +#include "utilities/vmError.hpp"
8312 +// put OS-includes here
8313 +# include <sys/types.h>
8314 +# include <sys/mman.h>
8315 +# include <pthread.h>
8316 +# include <signal.h>
8317 +# include <setjmp.h>
8318 +# include <errno.h>
8319 +# include <dlfcn.h>
8320 +# include <stdio.h>
8321 +# include <unistd.h>
8322 +# include <sys/resource.h>
8323 +# include <thread.h>
8324 +# include <sys/stat.h>
8325 +# include <sys/time.h>
8326 +# include <sys/filio.h>
8327 +# include <sys/utsname.h>
8328 +# include <sys/systeminfo.h>
8329 +# include <sys/socket.h>
8330 +# include <sys/trap.h>
8331 +# include <sys/lwp.h>
8332 +# include <poll.h>
8333 +# include <sys/lwp.h>
8334 +# include <procfs.h>
8337 +#define MAX_PATH (2 * K)
8339 +// Minimum usable stack sizes required to get to user code. Space for
8340 +// HotSpot guard pages is added later.
8341 +#ifdef _LP64
8342 +// The adlc generated method 'State::MachNodeGenerator(int)' used by the C2 compiler
8343 +// threads requires a large stack with the Solaris Studio C++ compiler version 5.13
8344 +// and product VM builds (debug builds require significantly less stack space).
8345 +size_t os::_compiler_thread_min_stack_allowed = 325 * K;
8346 +size_t os::_java_thread_min_stack_allowed = 48 * K;
8347 +size_t os::_vm_internal_thread_min_stack_allowed = 224 * K;
8348 +#else
8349 +size_t os::_compiler_thread_min_stack_allowed = 32 * K;
8350 +size_t os::_java_thread_min_stack_allowed = 32 * K;
8351 +size_t os::_vm_internal_thread_min_stack_allowed = 64 * K;
8352 +#endif // _LP64
8354 +#ifdef AMD64
8355 +#define REG_SP REG_RSP
8356 +#define REG_PC REG_RIP
8357 +#define REG_FP REG_RBP
8358 +#else
8359 +#define REG_SP UESP
8360 +#define REG_PC EIP
8361 +#define REG_FP EBP
8362 +// 4900493 counter to prevent runaway LDTR refresh attempt
8364 +static volatile int ldtr_refresh = 0;
8365 +// the libthread instruction that faults because of the stale LDTR
8367 +static const unsigned char movlfs[] = { 0x8e, 0xe0 // movl %eax,%fs
8368 + };
8369 +#endif // AMD64
8371 +char* os::non_memory_address_word() {
8372 + // Must never look like an address returned by reserve_memory,
8373 + // even in its subfields (as defined by the CPU immediate fields,
8374 + // if the CPU splits constants across multiple instructions).
8375 + return (char*) -1;
8379 +// Validate a ucontext retrieved from walking a uc_link of a ucontext.
8380 +// There are issues with libthread giving out uc_links for different threads
8381 +// on the same uc_link chain and bad or circular links.
8383 +bool os::Solaris::valid_ucontext(Thread* thread, const ucontext_t* valid, const ucontext_t* suspect) {
8384 + if (valid >= suspect ||
8385 + valid->uc_stack.ss_flags != suspect->uc_stack.ss_flags ||
8386 + valid->uc_stack.ss_sp != suspect->uc_stack.ss_sp ||
8387 + valid->uc_stack.ss_size != suspect->uc_stack.ss_size) {
8388 + DEBUG_ONLY(tty->print_cr("valid_ucontext: failed test 1");)
8389 + return false;
8392 + if (thread->is_Java_thread()) {
8393 + if (!thread->is_in_full_stack_checked((address)suspect)) {
8394 + DEBUG_ONLY(tty->print_cr("valid_ucontext: uc_link not in thread stack");)
8395 + return false;
8397 + if (!thread->is_in_full_stack_checked((address) suspect->uc_mcontext.gregs[REG_SP])) {
8398 + DEBUG_ONLY(tty->print_cr("valid_ucontext: stackpointer not in thread stack");)
8399 + return false;
8402 + return true;
8405 +// We will only follow one level of uc_link since there are libthread
8406 +// issues with ucontext linking and it is better to be safe and just
8407 +// let caller retry later.
8408 +const ucontext_t* os::Solaris::get_valid_uc_in_signal_handler(Thread *thread,
8409 + const ucontext_t *uc) {
8411 + const ucontext_t *retuc = NULL;
8413 + if (uc != NULL) {
8414 + if (uc->uc_link == NULL) {
8415 + // cannot validate without uc_link so accept current ucontext
8416 + retuc = uc;
8417 + } else if (os::Solaris::valid_ucontext(thread, uc, uc->uc_link)) {
8418 + // first ucontext is valid so try the next one
8419 + uc = uc->uc_link;
8420 + if (uc->uc_link == NULL) {
8421 + // cannot validate without uc_link so accept current ucontext
8422 + retuc = uc;
8423 + } else if (os::Solaris::valid_ucontext(thread, uc, uc->uc_link)) {
8424 + // the ucontext one level down is also valid so return it
8425 + retuc = uc;
8429 + return retuc;
8432 +void os::Posix::ucontext_set_pc(ucontext_t* uc, address pc) {
8433 + uc->uc_mcontext.gregs [REG_PC] = (greg_t) pc;
8436 +// Assumes ucontext is valid
8437 +intptr_t* os::Solaris::ucontext_get_sp(const ucontext_t *uc) {
8438 + return (intptr_t*)uc->uc_mcontext.gregs[REG_SP];
8441 +// Assumes ucontext is valid
8442 +intptr_t* os::Solaris::ucontext_get_fp(const ucontext_t *uc) {
8443 + return (intptr_t*)uc->uc_mcontext.gregs[REG_FP];
8446 +address os::Posix::ucontext_get_pc(const ucontext_t *uc) {
8447 + return (address) uc->uc_mcontext.gregs[REG_PC];
8450 +address os::fetch_frame_from_context(const void* ucVoid,
8451 + intptr_t** ret_sp, intptr_t** ret_fp) {
8453 + address epc;
8454 + const ucontext_t *uc = (const ucontext_t*)ucVoid;
8456 + if (uc != NULL) {
8457 + epc = os::Posix::ucontext_get_pc(uc);
8458 + if (ret_sp) *ret_sp = os::Solaris::ucontext_get_sp(uc);
8459 + if (ret_fp) *ret_fp = os::Solaris::ucontext_get_fp(uc);
8460 + } else {
8461 + epc = NULL;
8462 + if (ret_sp) *ret_sp = (intptr_t *)NULL;
8463 + if (ret_fp) *ret_fp = (intptr_t *)NULL;
8466 + return epc;
8469 +frame os::fetch_frame_from_context(const void* ucVoid) {
8470 + intptr_t* sp;
8471 + intptr_t* fp;
8472 + address epc = fetch_frame_from_context(ucVoid, &sp, &fp);
8473 + return frame(sp, fp, epc);
8476 +bool os::Solaris::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr) {
8477 + address pc = (address) os::Solaris::ucontext_get_pc(uc);
8478 + if (Interpreter::contains(pc)) {
8479 + // interpreter performs stack banging after the fixed frame header has
8480 + // been generated while the compilers perform it before. To maintain
8481 + // semantic consistency between interpreted and compiled frames, the
8482 + // method returns the Java sender of the current frame.
8483 + *fr = os::fetch_frame_from_context(uc);
8484 + if (!fr->is_first_java_frame()) {
8485 + // get_frame_at_stack_banging_point() is only called when we
8486 + // have well defined stacks so java_sender() calls do not need
8487 + // to assert safe_for_sender() first.
8488 + *fr = fr->java_sender();
8490 + } else {
8491 + // more complex code with compiled code
8492 + assert(!Interpreter::contains(pc), "Interpreted methods should have been handled above");
8493 + CodeBlob* cb = CodeCache::find_blob(pc);
8494 + if (cb == NULL || !cb->is_nmethod() || cb->is_frame_complete_at(pc)) {
8495 + // Not sure where the pc points to, fallback to default
8496 + // stack overflow handling
8497 + return false;
8498 + } else {
8499 + // in compiled code, the stack banging is performed just after the return pc
8500 + // has been pushed on the stack
8501 + intptr_t* fp = os::Solaris::ucontext_get_fp(uc);
8502 + intptr_t* sp = os::Solaris::ucontext_get_sp(uc);
8503 + *fr = frame(sp + 1, fp, (address)*sp);
8504 + if (!fr->is_java_frame()) {
8505 + // See java_sender() comment above.
8506 + *fr = fr->java_sender();
8510 + assert(fr->is_java_frame(), "Safety check");
8511 + return true;
8514 +frame os::get_sender_for_C_frame(frame* fr) {
8515 + return frame(fr->sender_sp(), fr->link(), fr->sender_pc());
8518 +extern "C" intptr_t *_get_current_sp() {
8519 + register intptr_t *rsp __asm__ ("rsp");
8520 + return rsp;
8523 +address os::current_stack_pointer() {
8524 + return (address)_get_current_sp();
8527 +extern "C" intptr_t *_get_current_fp() {
8528 + register intptr_t **rbp __asm__ ("rbp");
8529 + return (intptr_t*) *rbp;
8532 +frame os::current_frame() {
8533 + intptr_t* fp = _get_current_fp(); // it's inlined so want current fp
8534 + // fp is for os::current_frame. We want the fp for our caller.
8535 + frame myframe((intptr_t*)os::current_stack_pointer(),
8536 + (intptr_t*)fp,
8537 + CAST_FROM_FN_PTR(address, os::current_frame));
8538 + frame caller_frame = os::get_sender_for_C_frame(&myframe);
8540 + if (os::is_first_C_frame(&caller_frame)) {
8541 + // stack is not walkable
8542 + frame ret; // This will be a null useless frame
8543 + return ret;
8544 + } else {
8545 + // return frame for our caller's caller
8546 + return os::get_sender_for_C_frame(&caller_frame);
8551 +bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info,
8552 + ucontext_t* uc, JavaThread* thread) {
8554 + if (info == NULL || info->si_code <= 0 || info->si_code == SI_NOINFO) {
8555 + // can't decode this kind of signal
8556 + info = NULL;
8557 + } else {
8558 + assert(sig == info->si_signo, "bad siginfo");
8561 + // decide if this trap can be handled by a stub
8562 + address stub = NULL;
8564 + address pc = NULL;
8566 + //%note os_trap_1
8567 + if (info != NULL && uc != NULL && thread != NULL) {
8568 + // factor me: getPCfromContext
8569 + pc = (address) uc->uc_mcontext.gregs[REG_PC];
8571 + // Handle ALL stack overflow variations here
8572 + if (sig == SIGSEGV && info->si_code == SEGV_ACCERR) {
8573 + address addr = (address) info->si_addr;
8574 + if (thread->in_stack_yellow_reserved_zone(addr)) {
8575 + if (thread->thread_state() == _thread_in_Java) {
8576 + if (thread->in_stack_reserved_zone(addr)) {
8577 + frame fr;
8578 + if (os::Solaris::get_frame_at_stack_banging_point(thread, uc, &fr)) {
8579 + assert(fr.is_java_frame(), "Must be Java frame");
8580 + frame activation = SharedRuntime::look_for_reserved_stack_annotated_method(thread, fr);
8581 + if (activation.sp() != NULL) {
8582 + thread->disable_stack_reserved_zone();
8583 + if (activation.is_interpreted_frame()) {
8584 + thread->set_reserved_stack_activation((address)(
8585 + activation.fp() + frame::interpreter_frame_initial_sp_offset));
8586 + } else {
8587 + thread->set_reserved_stack_activation((address)activation.unextended_sp());
8589 + return true;
8593 + // Throw a stack overflow exception. Guard pages will be reenabled
8594 + // while unwinding the stack.
8595 + thread->disable_stack_yellow_reserved_zone();
8596 + stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW);
8597 + } else {
8598 + // Thread was in the vm or native code. Return and try to finish.
8599 + thread->disable_stack_yellow_reserved_zone();
8600 + return true;
8602 + } else if (thread->in_stack_red_zone(addr)) {
8603 + // Fatal red zone violation. Disable the guard pages and fall through
8604 + // to handle_unexpected_exception way down below.
8605 + thread->disable_stack_red_zone();
8606 + tty->print_raw_cr("An irrecoverable stack overflow has occurred.");
8610 + if ((sig == SIGSEGV) && VM_Version::is_cpuinfo_segv_addr(pc)) {
8611 + // Verify that OS save/restore AVX registers.
8612 + stub = VM_Version::cpuinfo_cont_addr();
8615 + if (thread->thread_state() == _thread_in_vm ||
8616 + thread->thread_state() == _thread_in_native) {
8617 + if (sig == SIGBUS && info->si_code == BUS_OBJERR && thread->doing_unsafe_access()) {
8618 + address next_pc = Assembler::locate_next_instruction(pc);
8619 + if (UnsafeCopyMemory::contains_pc(pc)) {
8620 + next_pc = UnsafeCopyMemory::page_error_continue_pc(pc);
8622 + stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
8626 + if (thread->thread_state() == _thread_in_Java) {
8627 + // Support Safepoint Polling
8628 + if ( sig == SIGSEGV && SafepointMechanism::is_poll_address((address)info->si_addr)) {
8629 + stub = SharedRuntime::get_poll_stub(pc);
8631 + else if (sig == SIGBUS && info->si_code == BUS_OBJERR) {
8632 + // BugId 4454115: A read from a MappedByteBuffer can fault
8633 + // here if the underlying file has been truncated.
8634 + // Do not crash the VM in such a case.
8635 + CodeBlob* cb = CodeCache::find_blob(pc);
8636 + if (cb != NULL) {
8637 + CompiledMethod* nm = cb->as_compiled_method_or_null();
8638 + bool is_unsafe_arraycopy = thread->doing_unsafe_access() && UnsafeCopyMemory::contains_pc(pc);
8639 + if ((nm != NULL && nm->has_unsafe_access()) || is_unsafe_arraycopy) {
8640 + address next_pc = Assembler::locate_next_instruction(pc);
8641 + if (is_unsafe_arraycopy) {
8642 + next_pc = UnsafeCopyMemory::page_error_continue_pc(pc);
8644 + stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
8648 + else
8649 + if (sig == SIGFPE && info->si_code == FPE_INTDIV) {
8650 + // integer divide by zero
8651 + stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_DIVIDE_BY_ZERO);
8653 +#ifndef AMD64
8654 + else if (sig == SIGFPE && info->si_code == FPE_FLTDIV) {
8655 + // floating-point divide by zero
8656 + stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_DIVIDE_BY_ZERO);
8658 + else if (sig == SIGFPE && info->si_code == FPE_FLTINV) {
8659 + // The encoding of D2I in i486.ad can cause an exception prior
8660 + // to the fist instruction if there was an invalid operation
8661 + // pending. We want to dismiss that exception. From the win_32
8662 + // side it also seems that if it really was the fist causing
8663 + // the exception that we do the d2i by hand with different
8664 + // rounding. Seems kind of weird. QQQ TODO
8665 + // Note that we take the exception at the NEXT floating point instruction.
8666 + if (pc[0] == 0xDB) {
8667 + assert(pc[0] == 0xDB, "not a FIST opcode");
8668 + assert(pc[1] == 0x14, "not a FIST opcode");
8669 + assert(pc[2] == 0x24, "not a FIST opcode");
8670 + return true;
8671 + } else {
8672 + assert(pc[-3] == 0xDB, "not an flt invalid opcode");
8673 + assert(pc[-2] == 0x14, "not an flt invalid opcode");
8674 + assert(pc[-1] == 0x24, "not an flt invalid opcode");
8677 + else if (sig == SIGFPE ) {
8678 + tty->print_cr("caught SIGFPE, info 0x%x.", info->si_code);
8680 +#endif // !AMD64
8682 + // QQQ It doesn't seem that we need to do this on x86 because we should be able
8683 + // to return properly from the handler without this extra stuff on the back side.
8685 + else if (sig == SIGSEGV && info->si_code > 0 &&
8686 + MacroAssembler::uses_implicit_null_check(info->si_addr)) {
8687 + // Determination of interpreter/vtable stub/compiled code null exception
8688 + stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL);
8692 + // jni_fast_Get<Primitive>Field can trap at certain pc's if a GC kicks in
8693 + // and the heap gets shrunk before the field access.
8694 + if ((sig == SIGSEGV) || (sig == SIGBUS)) {
8695 + address addr = JNI_FastGetField::find_slowcase_pc(pc);
8696 + if (addr != (address)-1) {
8697 + stub = addr;
8702 + // Execution protection violation
8703 + //
8704 + // Preventative code for future versions of Solaris which may
8705 + // enable execution protection when running the 32-bit VM on AMD64.
8706 + //
8707 + // This should be kept as the last step in the triage. We don't
8708 + // have a dedicated trap number for a no-execute fault, so be
8709 + // conservative and allow other handlers the first shot.
8710 + //
8711 + // Note: We don't test that info->si_code == SEGV_ACCERR here.
8712 + // this si_code is so generic that it is almost meaningless; and
8713 + // the si_code for this condition may change in the future.
8714 + // Furthermore, a false-positive should be harmless.
8715 + if (UnguardOnExecutionViolation > 0 &&
8716 + (sig == SIGSEGV || sig == SIGBUS) &&
8717 + uc->uc_mcontext.gregs[TRAPNO] == T_PGFLT) { // page fault
8718 + int page_size = os::vm_page_size();
8719 + address addr = (address) info->si_addr;
8720 + address pc = (address) uc->uc_mcontext.gregs[REG_PC];
8721 + // Make sure the pc and the faulting address are sane.
8722 + //
8723 + // If an instruction spans a page boundary, and the page containing
8724 + // the beginning of the instruction is executable but the following
8725 + // page is not, the pc and the faulting address might be slightly
8726 + // different - we still want to unguard the 2nd page in this case.
8727 + //
8728 + // 15 bytes seems to be a (very) safe value for max instruction size.
8729 + bool pc_is_near_addr =
8730 + (pointer_delta((void*) addr, (void*) pc, sizeof(char)) < 15);
8731 + bool instr_spans_page_boundary =
8732 + (align_down((intptr_t) pc ^ (intptr_t) addr,
8733 + (intptr_t) page_size) > 0);
8735 + if (pc == addr || (pc_is_near_addr && instr_spans_page_boundary)) {
8736 + static volatile address last_addr =
8737 + (address) os::non_memory_address_word();
8739 + // In conservative mode, don't unguard unless the address is in the VM
8740 + if (addr != last_addr &&
8741 + (UnguardOnExecutionViolation > 1 || os::address_is_in_vm(addr))) {
8743 + // Make memory rwx and retry
8744 + address page_start = align_down(addr, page_size);
8745 + bool res = os::protect_memory((char*) page_start, page_size,
8746 + os::MEM_PROT_RWX);
8748 + log_debug(os)("Execution protection violation "
8749 + "at " INTPTR_FORMAT
8750 + ", unguarding " INTPTR_FORMAT ": %s, errno=%d", p2i(addr),
8751 + p2i(page_start), (res ? "success" : "failed"), errno);
8752 + stub = pc;
8754 + // Set last_addr so if we fault again at the same address, we don't end
8755 + // up in an endless loop.
8756 + //
8757 + // There are two potential complications here. Two threads trapping at
8758 + // the same address at the same time could cause one of the threads to
8759 + // think it already unguarded, and abort the VM. Likely very rare.
8760 + //
8761 + // The other race involves two threads alternately trapping at
8762 + // different addresses and failing to unguard the page, resulting in
8763 + // an endless loop. This condition is probably even more unlikely than
8764 + // the first.
8765 + //
8766 + // Although both cases could be avoided by using locks or thread local
8767 + // last_addr, these solutions are unnecessary complication: this
8768 + // handler is a best-effort safety net, not a complete solution. It is
8769 + // disabled by default and should only be used as a workaround in case
8770 + // we missed any no-execute-unsafe VM code.
8772 + last_addr = addr;
8777 + if (stub != NULL) {
8778 + // save all thread context in case we need to restore it
8780 + if (thread != NULL) thread->set_saved_exception_pc(pc);
8781 + // 12/02/99: On Sparc it appears that the full context is also saved
8782 + // but as yet, no one looks at or restores that saved context
8783 + os::Posix::ucontext_set_pc(uc, stub);
8784 + return true;
8787 + return false;
8790 +void os::print_context(outputStream *st, const void *context) {
8791 + if (context == NULL) return;
8793 + const ucontext_t *uc = (const ucontext_t*)context;
8794 + st->print_cr("Registers:");
8795 +#ifdef AMD64
8796 + st->print( "RAX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RAX]);
8797 + st->print(", RBX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RBX]);
8798 + st->print(", RCX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RCX]);
8799 + st->print(", RDX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RDX]);
8800 + st->cr();
8801 + st->print( "RSP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RSP]);
8802 + st->print(", RBP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RBP]);
8803 + st->print(", RSI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RSI]);
8804 + st->print(", RDI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RDI]);
8805 + st->cr();
8806 + st->print( "R8 =" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R8]);
8807 + st->print(", R9 =" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R9]);
8808 + st->print(", R10=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R10]);
8809 + st->print(", R11=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R11]);
8810 + st->cr();
8811 + st->print( "R12=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R12]);
8812 + st->print(", R13=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R13]);
8813 + st->print(", R14=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R14]);
8814 + st->print(", R15=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R15]);
8815 + st->cr();
8816 + st->print( "RIP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RIP]);
8817 + st->print(", RFLAGS=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RFL]);
8818 +#else
8819 + st->print( "EAX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EAX]);
8820 + st->print(", EBX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EBX]);
8821 + st->print(", ECX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[ECX]);
8822 + st->print(", EDX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EDX]);
8823 + st->cr();
8824 + st->print( "ESP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[UESP]);
8825 + st->print(", EBP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EBP]);
8826 + st->print(", ESI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[ESI]);
8827 + st->print(", EDI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EDI]);
8828 + st->cr();
8829 + st->print( "EIP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EIP]);
8830 + st->print(", EFLAGS=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EFL]);
8831 +#endif // AMD64
8832 + st->cr();
8833 + st->cr();
8836 +void os::print_tos_pc(outputStream *st, const void *context) {
8837 + if (context == NULL) return;
8839 + const ucontext_t* uc = (const ucontext_t*)context;
8841 + intptr_t *sp = (intptr_t *)os::Solaris::ucontext_get_sp(uc);
8842 + st->print_cr("Top of Stack: (sp=" INTPTR_FORMAT ")", (intptr_t)sp);
8843 + print_hex_dump(st, (address)sp, (address)(sp + 8*sizeof(intptr_t)), sizeof(intptr_t));
8844 + st->cr();
8846 + // Note: it may be unsafe to inspect memory near pc. For example, pc may
8847 + // point to garbage if entry point in an nmethod is corrupted. Leave
8848 + // this at the end, and hope for the best.
8849 + address pc = os::Posix::ucontext_get_pc(uc);
8850 + print_instructions(st, pc, sizeof(char));
8851 + st->cr();
8854 +void os::print_register_info(outputStream *st, const void *context, int& continuation) {
8855 + const int register_count = AMD64_ONLY(16) NOT_AMD64(8);
8856 + int n = continuation;
8857 + assert(n >= 0 && n <= register_count, "Invalid continuation value");
8858 + if (context == nullptr || n == register_count) {
8859 + return;
8862 + const ucontext_t *uc = (const ucontext_t*)context;
8863 + while (n < register_count) {
8864 + // Update continuation with next index before printing location
8865 + continuation = n + 1;
8866 +# define CASE_PRINT_REG(n, str, id) case n: st->print(str); print_location(st, uc->uc_mcontext.gregs[REG_##id]);
8867 + switch (n) {
8868 +#ifdef AMD64
8869 + CASE_PRINT_REG( 0, "RAX=", RAX); break;
8870 + CASE_PRINT_REG( 1, "RBX=", RBX); break;
8871 + CASE_PRINT_REG( 2, "RCX=", RCX); break;
8872 + CASE_PRINT_REG( 3, "RDX=", RDX); break;
8873 + CASE_PRINT_REG( 4, "RSP=", RSP); break;
8874 + CASE_PRINT_REG( 5, "RBP=", RBP); break;
8875 + CASE_PRINT_REG( 6, "RSI=", RSI); break;
8876 + CASE_PRINT_REG( 7, "RDI=", RDI); break;
8877 + CASE_PRINT_REG( 8, "R8 =", R8); break;
8878 + CASE_PRINT_REG( 9, "R9 =", R9); break;
8879 + CASE_PRINT_REG(10, "R10=", R10); break;
8880 + CASE_PRINT_REG(11, "R11=", R11); break;
8881 + CASE_PRINT_REG(12, "R12=", R12); break;
8882 + CASE_PRINT_REG(13, "R13=", R13); break;
8883 + CASE_PRINT_REG(14, "R14=", R14); break;
8884 + CASE_PRINT_REG(15, "R15=", R15); break;
8885 +#else
8886 + CASE_PRINT_REG(0, "EAX=", EAX); break;
8887 + CASE_PRINT_REG(1, "EBX=", EBX); break;
8888 + CASE_PRINT_REG(2, "ECX=", ECX); break;
8889 + CASE_PRINT_REG(3, "EDX=", EDX); break;
8890 + CASE_PRINT_REG(4, "ESP=", ESP); break;
8891 + CASE_PRINT_REG(5, "EBP=", EBP); break;
8892 + CASE_PRINT_REG(6, "ESI=", ESI); break;
8893 + CASE_PRINT_REG(7, "EDI=", EDI); break;
8894 +#endif // AMD64
8896 +# undef CASE_PRINT_REG
8897 + ++n;
8902 +void os::Solaris::init_thread_fpu_state(void) {
8903 + // Nothing to do
8905 +void os::setup_fpu() {}
8907 +#ifndef PRODUCT
8908 +void os::verify_stack_alignment() {
8909 + assert(((intptr_t)os::current_stack_pointer() & (StackAlignmentInBytes-1)) == 0, "incorrect stack alignment");
8911 +#endif
8913 +int os::extra_bang_size_in_bytes() {
8914 + // JDK-8050147 requires the full cache line bang for x86.
8915 + return VM_Version::L1_line_size();
8917 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.hpp jdk21u-jdk-21.0.4-ga/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.hpp
8918 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.hpp 1970-01-01 01:00:00.000000000 +0100
8919 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.hpp 2024-08-17 19:13:01.453265149 +0200
8920 @@ -0,0 +1,55 @@
8922 + * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
8923 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8925 + * This code is free software; you can redistribute it and/or modify it
8926 + * under the terms of the GNU General Public License version 2 only, as
8927 + * published by the Free Software Foundation.
8929 + * This code is distributed in the hope that it will be useful, but WITHOUT
8930 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8931 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
8932 + * version 2 for more details (a copy is included in the LICENSE file that
8933 + * accompanied this code).
8935 + * You should have received a copy of the GNU General Public License version
8936 + * 2 along with this work; if not, write to the Free Software Foundation,
8937 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
8939 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
8940 + * or visit www.oracle.com if you need additional information or have any
8941 + * questions.
8943 + */
8945 +#ifndef OS_CPU_SOLARIS_X86_OS_SOLARIS_X86_HPP
8946 +#define OS_CPU_SOLARIS_X86_OS_SOLARIS_X86_HPP
8948 + //
8949 + // NOTE: we are back in class os here, not Solaris
8950 + //
8951 +#ifdef AMD64
8952 + static void setup_fpu() {}
8953 +#else
8954 + static int32_t (*atomic_xchg_func) (int32_t, volatile int32_t*);
8955 + static int32_t (*atomic_cmpxchg_func) (int32_t, volatile int32_t*, int32_t);
8956 + static int64_t (*atomic_cmpxchg_long_func)(int64_t, volatile int64_t*, int64_t);
8957 + static int32_t (*atomic_add_func) (int32_t, volatile int32_t*);
8959 + static int32_t atomic_xchg_bootstrap (int32_t, volatile int32_t*);
8960 + static int32_t atomic_cmpxchg_bootstrap (int32_t, volatile int32_t*, int32_t);
8961 + static int64_t atomic_cmpxchg_long_bootstrap(int64_t, volatile int64_t*, int64_t);
8962 + static int32_t atomic_add_bootstrap (int32_t, volatile int32_t*);
8964 + static void setup_fpu();
8965 +#endif // AMD64
8967 + static jlong rdtsc();
8969 + static bool is_allocatable(size_t bytes);
8971 + // Used to register dynamic code cache area with the OS
8972 + // Note: Currently only used in 64 bit Windows implementations
8973 + static bool register_code_area(char *low, char *high) { return true; }
8975 +#endif // OS_CPU_SOLARIS_X86_OS_SOLARIS_X86_HPP
8976 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.inline.hpp jdk21u-jdk-21.0.4-ga/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.inline.hpp
8977 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.inline.hpp 1970-01-01 01:00:00.000000000 +0100
8978 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.inline.hpp 2024-08-17 19:13:01.453558413 +0200
8979 @@ -0,0 +1,39 @@
8981 + * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
8982 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8984 + * This code is free software; you can redistribute it and/or modify it
8985 + * under the terms of the GNU General Public License version 2 only, as
8986 + * published by the Free Software Foundation.
8988 + * This code is distributed in the hope that it will be useful, but WITHOUT
8989 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8990 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
8991 + * version 2 for more details (a copy is included in the LICENSE file that
8992 + * accompanied this code).
8994 + * You should have received a copy of the GNU General Public License version
8995 + * 2 along with this work; if not, write to the Free Software Foundation,
8996 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
8998 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
8999 + * or visit www.oracle.com if you need additional information or have any
9000 + * questions.
9002 + */
9004 +#ifndef OS_CPU_SOLARIS_X86_OS_SOLARIS_X86_INLINE_HPP
9005 +#define OS_CPU_SOLARIS_X86_OS_SOLARIS_X86_INLINE_HPP
9007 +#include "runtime/os.hpp"
9009 +// See http://www.technovelty.org/code/c/reading-rdtsc.htl for details
9010 +inline jlong os::rdtsc() {
9011 + uint64_t res;
9012 + uint32_t ts1, ts2;
9013 + __asm__ __volatile__ ("rdtsc" : "=a" (ts1), "=d" (ts2));
9014 + res = ((uint64_t)ts1 | (uint64_t)ts2 << 32);
9015 + return (jlong)res;
9018 +#endif // OS_CPU_SOLARIS_X86_OS_SOLARIS_X86_INLINE_HPP
9019 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os_cpu/solaris_x86/prefetch_solaris_x86.inline.hpp jdk21u-jdk-21.0.4-ga/src/hotspot/os_cpu/solaris_x86/prefetch_solaris_x86.inline.hpp
9020 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os_cpu/solaris_x86/prefetch_solaris_x86.inline.hpp 1970-01-01 01:00:00.000000000 +0100
9021 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/os_cpu/solaris_x86/prefetch_solaris_x86.inline.hpp 2024-08-17 19:13:01.453852002 +0200
9022 @@ -0,0 +1,42 @@
9024 + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
9025 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
9027 + * This code is free software; you can redistribute it and/or modify it
9028 + * under the terms of the GNU General Public License version 2 only, as
9029 + * published by the Free Software Foundation.
9031 + * This code is distributed in the hope that it will be useful, but WITHOUT
9032 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
9033 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
9034 + * version 2 for more details (a copy is included in the LICENSE file that
9035 + * accompanied this code).
9037 + * You should have received a copy of the GNU General Public License version
9038 + * 2 along with this work; if not, write to the Free Software Foundation,
9039 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
9041 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
9042 + * or visit www.oracle.com if you need additional information or have any
9043 + * questions.
9045 + */
9047 +#ifndef OS_CPU_SOLARIS_X86_PREFETCH_SOLARIS_X86_INLINE_HPP
9048 +#define OS_CPU_SOLARIS_X86_PREFETCH_SOLARIS_X86_INLINE_HPP
9050 +#include "runtime/prefetch.hpp"
9052 +inline void Prefetch::read (const void *loc, intx interval) {
9053 +#ifdef AMD64
9054 + __asm__ ("prefetcht0 (%0,%1,1)" : : "r" (loc), "r" (interval));
9055 +#endif // AMD64
9058 +inline void Prefetch::write(void *loc, intx interval) {
9059 +#ifdef AMD64
9060 + __asm__ ("prefetcht0 (%0,%1,1)" : : "r" (loc), "r" (interval));
9061 +#endif // AMD64
9064 +#endif // OS_CPU_SOLARIS_X86_PREFETCH_SOLARIS_X86_INLINE_HPP
9065 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os_cpu/solaris_x86/solaris_x86_64.S jdk21u-jdk-21.0.4-ga/src/hotspot/os_cpu/solaris_x86/solaris_x86_64.S
9066 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os_cpu/solaris_x86/solaris_x86_64.S 1970-01-01 01:00:00.000000000 +0100
9067 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/os_cpu/solaris_x86/solaris_x86_64.S 2024-08-17 19:13:01.454319702 +0200
9068 @@ -0,0 +1,386 @@
9070 +# Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
9071 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
9073 +# This code is free software; you can redistribute it and/or modify it
9074 +# under the terms of the GNU General Public License version 2 only, as
9075 +# published by the Free Software Foundation.
9077 +# This code is distributed in the hope that it will be useful, but WITHOUT
9078 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
9079 +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
9080 +# version 2 for more details (a copy is included in the LICENSE file that
9081 +# accompanied this code).
9083 +# You should have received a copy of the GNU General Public License version
9084 +# 2 along with this work; if not, write to the Free Software Foundation,
9085 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
9087 +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
9088 +# or visit www.oracle.com if you need additional information or have any
9089 +# questions.
9092 + .globl fs_load
9093 + .globl fs_thread
9095 + ## NOTE WELL! The _Copy functions are called directly
9096 + ## from server-compiler-generated code via CallLeafNoFP,
9097 + ## which means that they *must* either not use floating
9098 + ## point or use it in the same manner as does the server
9099 + ## compiler.
9101 + .globl _Copy_arrayof_conjoint_bytes
9102 + .globl _Copy_conjoint_jshorts_atomic
9103 + .globl _Copy_arrayof_conjoint_jshorts
9104 + .globl _Copy_conjoint_jints_atomic
9105 + .globl _Copy_arrayof_conjoint_jints
9106 + .globl _Copy_conjoint_jlongs_atomic
9107 + .globl _Copy_arrayof_conjoint_jlongs
9109 + .section .text,"ax"
9111 + # Fast thread accessors, used by threadLS_solaris_amd64.cpp
9112 + .align 16
9113 +fs_load:
9114 + movq %fs:(%rdi),%rax
9115 + ret
9117 + .align 16
9118 +fs_thread:
9119 + movq %fs:0x0,%rax
9120 + ret
9122 + .globl SpinPause
9123 + .align 16
9124 +SpinPause:
9125 + rep
9126 + nop
9127 + movq $1, %rax
9128 + ret
9131 + # Support for void Copy::arrayof_conjoint_bytes(void* from,
9132 + # void* to,
9133 + # size_t count)
9134 + # rdi - from
9135 + # rsi - to
9136 + # rdx - count, treated as ssize_t
9138 + .align 16
9139 +_Copy_arrayof_conjoint_bytes:
9140 + movq %rdx,%r8 # byte count
9141 + shrq $3,%rdx # qword count
9142 + cmpq %rdi,%rsi
9143 + leaq -1(%rdi,%r8,1),%rax # from + bcount*1 - 1
9144 + jbe acb_CopyRight
9145 + cmpq %rax,%rsi
9146 + jbe acb_CopyLeft
9147 +acb_CopyRight:
9148 + leaq -8(%rdi,%rdx,8),%rax # from + qcount*8 - 8
9149 + leaq -8(%rsi,%rdx,8),%rcx # to + qcount*8 - 8
9150 + negq %rdx
9151 + jmp 7f
9152 + .align 16
9153 +1: movq 8(%rax,%rdx,8),%rsi
9154 + movq %rsi,8(%rcx,%rdx,8)
9155 + addq $1,%rdx
9156 + jnz 1b
9157 +2: testq $4,%r8 # check for trailing dword
9158 + jz 3f
9159 + movl 8(%rax),%esi # copy trailing dword
9160 + movl %esi,8(%rcx)
9161 + addq $4,%rax
9162 + addq $4,%rcx # original %rsi is trashed, so we
9163 + # can't use it as a base register
9164 +3: testq $2,%r8 # check for trailing word
9165 + jz 4f
9166 + movw 8(%rax),%si # copy trailing word
9167 + movw %si,8(%rcx)
9168 + addq $2,%rcx
9169 +4: testq $1,%r8 # check for trailing byte
9170 + jz 5f
9171 + movb -1(%rdi,%r8,1),%al # copy trailing byte
9172 + movb %al,8(%rcx)
9173 +5: ret
9174 + .align 16
9175 +6: movq -24(%rax,%rdx,8),%rsi
9176 + movq %rsi,-24(%rcx,%rdx,8)
9177 + movq -16(%rax,%rdx,8),%rsi
9178 + movq %rsi,-16(%rcx,%rdx,8)
9179 + movq -8(%rax,%rdx,8),%rsi
9180 + movq %rsi,-8(%rcx,%rdx,8)
9181 + movq (%rax,%rdx,8),%rsi
9182 + movq %rsi,(%rcx,%rdx,8)
9183 +7: addq $4,%rdx
9184 + jle 6b
9185 + subq $4,%rdx
9186 + jl 1b
9187 + jmp 2b
9188 +acb_CopyLeft:
9189 + testq $1,%r8 # check for trailing byte
9190 + jz 1f
9191 + movb -1(%rdi,%r8,1),%cl # copy trailing byte
9192 + movb %cl,-1(%rsi,%r8,1)
9193 + subq $1,%r8 # adjust for possible trailing word
9194 +1: testq $2,%r8 # check for trailing word
9195 + jz 2f
9196 + movw -2(%rdi,%r8,1),%cx # copy trailing word
9197 + movw %cx,-2(%rsi,%r8,1)
9198 +2: testq $4,%r8 # check for trailing dword
9199 + jz 5f
9200 + movl (%rdi,%rdx,8),%ecx # copy trailing dword
9201 + movl %ecx,(%rsi,%rdx,8)
9202 + jmp 5f
9203 + .align 16
9204 +3: movq -8(%rdi,%rdx,8),%rcx
9205 + movq %rcx,-8(%rsi,%rdx,8)
9206 + subq $1,%rdx
9207 + jnz 3b
9208 + ret
9209 + .align 16
9210 +4: movq 24(%rdi,%rdx,8),%rcx
9211 + movq %rcx,24(%rsi,%rdx,8)
9212 + movq 16(%rdi,%rdx,8),%rcx
9213 + movq %rcx,16(%rsi,%rdx,8)
9214 + movq 8(%rdi,%rdx,8),%rcx
9215 + movq %rcx,8(%rsi,%rdx,8)
9216 + movq (%rdi,%rdx,8),%rcx
9217 + movq %rcx,(%rsi,%rdx,8)
9218 +5: subq $4,%rdx
9219 + jge 4b
9220 + addq $4,%rdx
9221 + jg 3b
9222 + ret
9224 + # Support for void Copy::arrayof_conjoint_jshorts(void* from,
9225 + # void* to,
9226 + # size_t count)
9227 + # Equivalent to
9228 + # conjoint_jshorts_atomic
9230 + # If 'from' and/or 'to' are aligned on 4- or 2-byte boundaries, we
9231 + # let the hardware handle it. The tow or four words within dwords
9232 + # or qwords that span cache line boundaries will still be loaded
9233 + # and stored atomically.
9235 + # rdi - from
9236 + # rsi - to
9237 + # rdx - count, treated as ssize_t
9239 + .align 16
9240 +_Copy_arrayof_conjoint_jshorts:
9241 +_Copy_conjoint_jshorts_atomic:
9242 + movq %rdx,%r8 # word count
9243 + shrq $2,%rdx # qword count
9244 + cmpq %rdi,%rsi
9245 + leaq -2(%rdi,%r8,2),%rax # from + wcount*2 - 2
9246 + jbe acs_CopyRight
9247 + cmpq %rax,%rsi
9248 + jbe acs_CopyLeft
9249 +acs_CopyRight:
9250 + leaq -8(%rdi,%rdx,8),%rax # from + qcount*8 - 8
9251 + leaq -8(%rsi,%rdx,8),%rcx # to + qcount*8 - 8
9252 + negq %rdx
9253 + jmp 6f
9254 +1: movq 8(%rax,%rdx,8),%rsi
9255 + movq %rsi,8(%rcx,%rdx,8)
9256 + addq $1,%rdx
9257 + jnz 1b
9258 +2: testq $2,%r8 # check for trailing dword
9259 + jz 3f
9260 + movl 8(%rax),%esi # copy trailing dword
9261 + movl %esi,8(%rcx)
9262 + addq $4,%rcx # original %rsi is trashed, so we
9263 + # can't use it as a base register
9264 +3: testq $1,%r8 # check for trailing word
9265 + jz 4f
9266 + movw -2(%rdi,%r8,2),%si # copy trailing word
9267 + movw %si,8(%rcx)
9268 +4: ret
9269 + .align 16
9270 +5: movq -24(%rax,%rdx,8),%rsi
9271 + movq %rsi,-24(%rcx,%rdx,8)
9272 + movq -16(%rax,%rdx,8),%rsi
9273 + movq %rsi,-16(%rcx,%rdx,8)
9274 + movq -8(%rax,%rdx,8),%rsi
9275 + movq %rsi,-8(%rcx,%rdx,8)
9276 + movq (%rax,%rdx,8),%rsi
9277 + movq %rsi,(%rcx,%rdx,8)
9278 +6: addq $4,%rdx
9279 + jle 5b
9280 + subq $4,%rdx
9281 + jl 1b
9282 + jmp 2b
9283 +acs_CopyLeft:
9284 + testq $1,%r8 # check for trailing word
9285 + jz 1f
9286 + movw -2(%rdi,%r8,2),%cx # copy trailing word
9287 + movw %cx,-2(%rsi,%r8,2)
9288 +1: testq $2,%r8 # check for trailing dword
9289 + jz 4f
9290 + movl (%rdi,%rdx,8),%ecx # copy trailing dword
9291 + movl %ecx,(%rsi,%rdx,8)
9292 + jmp 4f
9293 +2: movq -8(%rdi,%rdx,8),%rcx
9294 + movq %rcx,-8(%rsi,%rdx,8)
9295 + subq $1,%rdx
9296 + jnz 2b
9297 + ret
9298 + .align 16
9299 +3: movq 24(%rdi,%rdx,8),%rcx
9300 + movq %rcx,24(%rsi,%rdx,8)
9301 + movq 16(%rdi,%rdx,8),%rcx
9302 + movq %rcx,16(%rsi,%rdx,8)
9303 + movq 8(%rdi,%rdx,8),%rcx
9304 + movq %rcx,8(%rsi,%rdx,8)
9305 + movq (%rdi,%rdx,8),%rcx
9306 + movq %rcx,(%rsi,%rdx,8)
9307 +4: subq $4,%rdx
9308 + jge 3b
9309 + addq $4,%rdx
9310 + jg 2b
9311 + ret
9313 + # Support for void Copy::arrayof_conjoint_jints(jint* from,
9314 + # jint* to,
9315 + # size_t count)
9316 + # Equivalent to
9317 + # conjoint_jints_atomic
9319 + # If 'from' and/or 'to' are aligned on 4-byte boundaries, we let
9320 + # the hardware handle it. The two dwords within qwords that span
9321 + # cache line boundaries will still be loaded and stored atomically.
9323 + # rdi - from
9324 + # rsi - to
9325 + # rdx - count, treated as ssize_t
9327 + .align 16
9328 +_Copy_arrayof_conjoint_jints:
9329 +_Copy_conjoint_jints_atomic:
9330 + movq %rdx,%r8 # dword count
9331 + shrq %rdx # qword count
9332 + cmpq %rdi,%rsi
9333 + leaq -4(%rdi,%r8,4),%rax # from + dcount*4 - 4
9334 + jbe aci_CopyRight
9335 + cmpq %rax,%rsi
9336 + jbe aci_CopyLeft
9337 +aci_CopyRight:
9338 + leaq -8(%rdi,%rdx,8),%rax # from + qcount*8 - 8
9339 + leaq -8(%rsi,%rdx,8),%rcx # to + qcount*8 - 8
9340 + negq %rdx
9341 + jmp 5f
9342 + .align 16
9343 +1: movq 8(%rax,%rdx,8),%rsi
9344 + movq %rsi,8(%rcx,%rdx,8)
9345 + addq $1,%rdx
9346 + jnz 1b
9347 +2: testq $1,%r8 # check for trailing dword
9348 + jz 3f
9349 + movl 8(%rax),%esi # copy trailing dword
9350 + movl %esi,8(%rcx)
9351 +3: ret
9352 + .align 16
9353 +4: movq -24(%rax,%rdx,8),%rsi
9354 + movq %rsi,-24(%rcx,%rdx,8)
9355 + movq -16(%rax,%rdx,8),%rsi
9356 + movq %rsi,-16(%rcx,%rdx,8)
9357 + movq -8(%rax,%rdx,8),%rsi
9358 + movq %rsi,-8(%rcx,%rdx,8)
9359 + movq (%rax,%rdx,8),%rsi
9360 + movq %rsi,(%rcx,%rdx,8)
9361 +5: addq $4,%rdx
9362 + jle 4b
9363 + subq $4,%rdx
9364 + jl 1b
9365 + jmp 2b
9366 +aci_CopyLeft:
9367 + testq $1,%r8 # check for trailing dword
9368 + jz 3f
9369 + movl -4(%rdi,%r8,4),%ecx # copy trailing dword
9370 + movl %ecx,-4(%rsi,%r8,4)
9371 + jmp 3f
9372 +1: movq -8(%rdi,%rdx,8),%rcx
9373 + movq %rcx,-8(%rsi,%rdx,8)
9374 + subq $1,%rdx
9375 + jnz 1b
9376 + ret
9377 + .align 16
9378 +2: movq 24(%rdi,%rdx,8),%rcx
9379 + movq %rcx,24(%rsi,%rdx,8)
9380 + movq 16(%rdi,%rdx,8),%rcx
9381 + movq %rcx,16(%rsi,%rdx,8)
9382 + movq 8(%rdi,%rdx,8),%rcx
9383 + movq %rcx,8(%rsi,%rdx,8)
9384 + movq (%rdi,%rdx,8),%rcx
9385 + movq %rcx,(%rsi,%rdx,8)
9386 +3: subq $4,%rdx
9387 + jge 2b
9388 + addq $4,%rdx
9389 + jg 1b
9390 + ret
9392 + # Support for void Copy::arrayof_conjoint_jlongs(jlong* from,
9393 + # jlong* to,
9394 + # size_t count)
9395 + # Equivalent to
9396 + # conjoint_jlongs_atomic
9397 + # arrayof_conjoint_oops
9398 + # conjoint_oops_atomic
9400 + # rdi - from
9401 + # rsi - to
9402 + # rdx - count, treated as ssize_t
9404 + .align 16
9405 +_Copy_arrayof_conjoint_jlongs:
9406 +_Copy_conjoint_jlongs_atomic:
9407 + cmpq %rdi,%rsi
9408 + leaq -8(%rdi,%rdx,8),%rax # from + count*8 - 8
9409 + jbe acl_CopyRight
9410 + cmpq %rax,%rsi
9411 + jbe acl_CopyLeft
9412 +acl_CopyRight:
9413 + leaq -8(%rsi,%rdx,8),%rcx # to + count*8 - 8
9414 + negq %rdx
9415 + jmp 3f
9416 +1: movq 8(%rax,%rdx,8),%rsi
9417 + movq %rsi,8(%rcx,%rdx,8)
9418 + addq $1,%rdx
9419 + jnz 1b
9420 + ret
9421 + .align 16
9422 +2: movq -24(%rax,%rdx,8),%rsi
9423 + movq %rsi,-24(%rcx,%rdx,8)
9424 + movq -16(%rax,%rdx,8),%rsi
9425 + movq %rsi,-16(%rcx,%rdx,8)
9426 + movq -8(%rax,%rdx,8),%rsi
9427 + movq %rsi,-8(%rcx,%rdx,8)
9428 + movq (%rax,%rdx,8),%rsi
9429 + movq %rsi,(%rcx,%rdx,8)
9430 +3: addq $4,%rdx
9431 + jle 2b
9432 + subq $4,%rdx
9433 + jl 1b
9434 + ret
9435 +4: movq -8(%rdi,%rdx,8),%rcx
9436 + movq %rcx,-8(%rsi,%rdx,8)
9437 + subq $1,%rdx
9438 + jnz 4b
9439 + ret
9440 + .align 16
9441 +5: movq 24(%rdi,%rdx,8),%rcx
9442 + movq %rcx,24(%rsi,%rdx,8)
9443 + movq 16(%rdi,%rdx,8),%rcx
9444 + movq %rcx,16(%rsi,%rdx,8)
9445 + movq 8(%rdi,%rdx,8),%rcx
9446 + movq %rcx,8(%rsi,%rdx,8)
9447 + movq (%rdi,%rdx,8),%rcx
9448 + movq %rcx,(%rsi,%rdx,8)
9449 +acl_CopyLeft:
9450 + subq $4,%rdx
9451 + jge 5b
9452 + addq $4,%rdx
9453 + jg 4b
9454 + ret
9455 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os_cpu/solaris_x86/vm_version_solaris_x86.cpp jdk21u-jdk-21.0.4-ga/src/hotspot/os_cpu/solaris_x86/vm_version_solaris_x86.cpp
9456 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os_cpu/solaris_x86/vm_version_solaris_x86.cpp 1970-01-01 01:00:00.000000000 +0100
9457 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/os_cpu/solaris_x86/vm_version_solaris_x86.cpp 2024-08-17 19:13:01.455559627 +0200
9458 @@ -0,0 +1,28 @@
9460 + * Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved.
9461 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
9463 + * This code is free software; you can redistribute it and/or modify it
9464 + * under the terms of the GNU General Public License version 2 only, as
9465 + * published by the Free Software Foundation.
9467 + * This code is distributed in the hope that it will be useful, but WITHOUT
9468 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
9469 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
9470 + * version 2 for more details (a copy is included in the LICENSE file that
9471 + * accompanied this code).
9473 + * You should have received a copy of the GNU General Public License version
9474 + * 2 along with this work; if not, write to the Free Software Foundation,
9475 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
9477 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
9478 + * or visit www.oracle.com if you need additional information or have any
9479 + * questions.
9481 + */
9483 +#include "precompiled.hpp"
9484 +#include "runtime/os.hpp"
9485 +#include "runtime/vm_version.hpp"
9487 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os_cpu/solaris_x86/vmStructs_solaris_x86.hpp jdk21u-jdk-21.0.4-ga/src/hotspot/os_cpu/solaris_x86/vmStructs_solaris_x86.hpp
9488 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/os_cpu/solaris_x86/vmStructs_solaris_x86.hpp 1970-01-01 01:00:00.000000000 +0100
9489 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/os_cpu/solaris_x86/vmStructs_solaris_x86.hpp 2024-08-17 19:13:01.455265890 +0200
9490 @@ -0,0 +1,40 @@
9492 + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
9493 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
9495 + * This code is free software; you can redistribute it and/or modify it
9496 + * under the terms of the GNU General Public License version 2 only, as
9497 + * published by the Free Software Foundation.
9499 + * This code is distributed in the hope that it will be useful, but WITHOUT
9500 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
9501 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
9502 + * version 2 for more details (a copy is included in the LICENSE file that
9503 + * accompanied this code).
9505 + * You should have received a copy of the GNU General Public License version
9506 + * 2 along with this work; if not, write to the Free Software Foundation,
9507 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
9509 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
9510 + * or visit www.oracle.com if you need additional information or have any
9511 + * questions.
9513 + */
9515 +#ifndef OS_CPU_SOLARIS_X86_VMSTRUCTS_SOLARIS_X86_HPP
9516 +#define OS_CPU_SOLARIS_X86_VMSTRUCTS_SOLARIS_X86_HPP
9518 +// These are the OS and CPU-specific fields, types and integer
9519 +// constants required by the Serviceability Agent. This file is
9520 +// referenced by vmStructs.cpp.
9522 +#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field)
9524 +#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type)
9526 +#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
9528 +#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
9530 +#endif // OS_CPU_SOLARIS_X86_VMSTRUCTS_SOLARIS_X86_HPP
9531 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/share/c1/c1_LIR.cpp jdk21u-jdk-21.0.4-ga/src/hotspot/share/c1/c1_LIR.cpp
9532 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/share/c1/c1_LIR.cpp 2024-07-09 10:07:16.000000000 +0200
9533 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/share/c1/c1_LIR.cpp 2024-08-17 19:13:01.388323773 +0200
9534 @@ -446,6 +446,8 @@
9535 case lir_monaddr: // input and result always valid, info always invalid
9536 case lir_null_check: // input and info always valid, result always invalid
9537 case lir_move: // input and result always valid, may have info
9538 + case lir_pack64: // input and result always valid
9539 + case lir_unpack64: // input and result always valid
9541 assert(op->as_Op1() != nullptr, "must be");
9542 LIR_Op1* op1 = (LIR_Op1*)op;
9543 @@ -1726,6 +1728,8 @@
9544 case lir_convert: s = "convert"; break;
9545 case lir_alloc_object: s = "alloc_obj"; break;
9546 case lir_monaddr: s = "mon_addr"; break;
9547 + case lir_pack64: s = "pack64"; break;
9548 + case lir_unpack64: s = "unpack64"; break;
9549 // LIR_Op2
9550 case lir_cmp: s = "cmp"; break;
9551 case lir_cmp_l2i: s = "cmp_l2i"; break;
9552 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/share/c1/c1_LIR.hpp jdk21u-jdk-21.0.4-ga/src/hotspot/share/c1/c1_LIR.hpp
9553 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/share/c1/c1_LIR.hpp 2024-07-09 10:07:16.000000000 +0200
9554 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/share/c1/c1_LIR.hpp 2024-08-17 19:13:01.389332668 +0200
9555 @@ -939,6 +939,8 @@
9556 , lir_monaddr
9557 , lir_roundfp
9558 , lir_safepoint
9559 + , lir_pack64
9560 + , lir_unpack64
9561 , lir_unwind
9562 , lir_load_klass
9563 , end_op1
9564 @@ -2234,6 +2236,9 @@
9565 void logical_or (LIR_Opr left, LIR_Opr right, LIR_Opr dst) { append(new LIR_Op2(lir_logic_or, left, right, dst)); }
9566 void logical_xor (LIR_Opr left, LIR_Opr right, LIR_Opr dst) { append(new LIR_Op2(lir_logic_xor, left, right, dst)); }
9568 + void pack64(LIR_Opr src, LIR_Opr dst) { append(new LIR_Op1(lir_pack64, src, dst, T_LONG, lir_patch_none, NULL)); }
9569 + void unpack64(LIR_Opr src, LIR_Opr dst) { append(new LIR_Op1(lir_unpack64, src, dst, T_LONG, lir_patch_none, NULL)); }
9571 void null_check(LIR_Opr opr, CodeEmitInfo* info, bool deoptimize_on_null = false);
9572 void throw_exception(LIR_Opr exceptionPC, LIR_Opr exceptionOop, CodeEmitInfo* info) {
9573 append(new LIR_Op2(lir_throw, exceptionPC, exceptionOop, LIR_OprFact::illegalOpr, info));
9574 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/share/cds/classListParser.cpp jdk21u-jdk-21.0.4-ga/src/hotspot/share/cds/classListParser.cpp
9575 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/share/cds/classListParser.cpp 2024-07-09 10:07:16.000000000 +0200
9576 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/share/cds/classListParser.cpp 2024-08-17 19:13:01.389962760 +0200
9577 @@ -452,7 +452,7 @@
9578 // This function is used for loading classes for customized class loaders
9579 // during archive dumping.
9580 InstanceKlass* ClassListParser::load_class_from_source(Symbol* class_name, TRAPS) {
9581 -#if !(defined(_LP64) && (defined(LINUX) || defined(__APPLE__) || defined(_WINDOWS)))
9582 +#if !(defined(_LP64) && (defined(LINUX)|| defined(SOLARIS) || defined(__APPLE__) || defined(_WINDOWS)))
9583 // The only supported platforms are: (1) Linux/64-bit and (2) Solaris/64-bit and
9584 // (3) MacOSX/64-bit and (4) Windowss/64-bit
9585 // This #if condition should be in sync with the areCustomLoadersSupportedForCDS
9586 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/share/runtime/abstract_vm_version.cpp jdk21u-jdk-21.0.4-ga/src/hotspot/share/runtime/abstract_vm_version.cpp
9587 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/share/runtime/abstract_vm_version.cpp 2024-07-09 10:07:16.000000000 +0200
9588 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/share/runtime/abstract_vm_version.cpp 2024-08-17 19:13:01.390660848 +0200
9589 @@ -167,6 +167,7 @@
9591 #define OS LINUX_ONLY("linux") \
9592 WINDOWS_ONLY("windows") \
9593 + SOLARIS_ONLY("solaris") \
9594 AIX_ONLY("aix") \
9595 BSD_ONLY("bsd")
9597 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/share/runtime/globals.hpp jdk21u-jdk-21.0.4-ga/src/hotspot/share/runtime/globals.hpp
9598 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/share/runtime/globals.hpp 2024-07-09 10:07:16.000000000 +0200
9599 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/share/runtime/globals.hpp 2024-08-17 19:13:01.392044254 +0200
9600 @@ -1596,8 +1596,10 @@
9601 product(int, ThreadPriorityPolicy, 0, \
9602 "0 : Normal. "\
9603 " VM chooses priorities that are appropriate for normal "\
9604 - " applications. "\
9605 - " On Windows applications are allowed to use higher native "\
9606 + " applications. On Solaris NORM_PRIORITY and above are mapped "\
9607 + " to normal native priority. Java priorities below " \
9608 + " NORM_PRIORITY map to lower native priority values. On "\
9609 + " Windows applications are allowed to use higher native "\
9610 " priorities. However, with ThreadPriorityPolicy=0, VM will "\
9611 " not use the highest possible native priority, "\
9612 " THREAD_PRIORITY_TIME_CRITICAL, as it may interfere with "\
9613 @@ -1879,7 +1881,8 @@
9614 product(bool, WhiteBoxAPI, false, DIAGNOSTIC, \
9615 "Enable internal testing APIs") \
9617 - product(size_t, ArrayAllocatorMallocLimit, SIZE_MAX, EXPERIMENTAL, \
9618 + product(size_t, ArrayAllocatorMallocLimit, \
9619 + SOLARIS_ONLY(64*K) NOT_SOLARIS(SIZE_MAX), EXPERIMENTAL, \
9620 "Allocation less than this value will be allocated " \
9621 "using malloc. Larger allocations will use mmap.") \
9623 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/share/runtime/semaphore.hpp jdk21u-jdk-21.0.4-ga/src/hotspot/share/runtime/semaphore.hpp
9624 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/share/runtime/semaphore.hpp 2024-07-09 10:07:16.000000000 +0200
9625 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/share/runtime/semaphore.hpp 2024-08-17 19:13:01.392481217 +0200
9626 @@ -28,7 +28,7 @@
9627 #include "memory/allocation.hpp"
9628 #include "utilities/globalDefinitions.hpp"
9630 -#if defined(LINUX) || defined(AIX)
9631 +#if defined(LINUX) || defined(SOLARIS) || defined(AIX)
9632 # include "semaphore_posix.hpp"
9633 #else
9634 # include OS_HEADER(semaphore)
9635 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/share/services/dtraceAttacher.cpp jdk21u-jdk-21.0.4-ga/src/hotspot/share/services/dtraceAttacher.cpp
9636 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/share/services/dtraceAttacher.cpp 1970-01-01 01:00:00.000000000 +0100
9637 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/share/services/dtraceAttacher.cpp 2024-08-17 19:13:01.455891763 +0200
9638 @@ -0,0 +1,99 @@
9640 + * Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved.
9641 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
9643 + * This code is free software; you can redistribute it and/or modify it
9644 + * under the terms of the GNU General Public License version 2 only, as
9645 + * published by the Free Software Foundation.
9647 + * This code is distributed in the hope that it will be useful, but WITHOUT
9648 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
9649 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
9650 + * version 2 for more details (a copy is included in the LICENSE file that
9651 + * accompanied this code).
9653 + * You should have received a copy of the GNU General Public License version
9654 + * 2 along with this work; if not, write to the Free Software Foundation,
9655 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
9657 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
9658 + * or visit www.oracle.com if you need additional information or have any
9659 + * questions.
9661 + */
9663 +#include "precompiled.hpp"
9664 +#include "code/codeCache.hpp"
9665 +#include "memory/resourceArea.hpp"
9666 +#include "runtime/deoptimization.hpp"
9667 +#include "runtime/flags/jvmFlag.hpp"
9668 +#include "runtime/vmThread.hpp"
9669 +#include "runtime/vmOperations.hpp"
9670 +#include "services/dtraceAttacher.hpp"
9671 +#include "runtime/flags/jvmFlagAccess.hpp"
9673 +#ifdef SOLARIS
9675 +static void set_bool_flag(const char* name, bool value) {
9676 + JVMFlag* flag = JVMFlag::find_flag(name);
9677 + JVMFlagAccess::set_bool(flag, &value, JVMFlagOrigin::ATTACH_ON_DEMAND);
9680 +// Enable the "fine grained" flags.
9681 +void DTrace::enable_dprobes(int probes) {
9682 + bool changed = false;
9683 + if (!DTraceAllocProbes && (probes & DTRACE_ALLOC_PROBES)) {
9684 + set_bool_flag("DTraceAllocProbes", true);
9685 + changed = true;
9687 + if (!DTraceMethodProbes && (probes & DTRACE_METHOD_PROBES)) {
9688 + set_bool_flag("DTraceMethodProbes", true);
9689 + changed = true;
9691 + if (!DTraceMonitorProbes && (probes & DTRACE_MONITOR_PROBES)) {
9692 + set_bool_flag("DTraceMonitorProbes", true);
9693 + changed = true;
9696 + if (changed) {
9697 + // one or more flags changed, need to deoptimize
9698 + DeoptimizationScope deopt_scope;
9699 + CodeCache::mark_all_nmethods_for_deoptimization(&deopt_scope);
9700 + deopt_scope.deoptimize_marked();
9704 +// Disable the "fine grained" flags.
9705 +void DTrace::disable_dprobes(int probes) {
9706 + bool changed = false;
9707 + if (DTraceAllocProbes && (probes & DTRACE_ALLOC_PROBES)) {
9708 + set_bool_flag("DTraceAllocProbes", false);
9709 + changed = true;
9711 + if (DTraceMethodProbes && (probes & DTRACE_METHOD_PROBES)) {
9712 + set_bool_flag("DTraceMethodProbes", false);
9713 + changed = true;
9715 + if (DTraceMonitorProbes && (probes & DTRACE_MONITOR_PROBES)) {
9716 + set_bool_flag("DTraceMonitorProbes", false);
9717 + changed = true;
9719 + if (changed) {
9720 + // one or more flags changed, need to deoptimize
9721 + DeoptimizationScope deopt_scope;
9722 + CodeCache::mark_all_nmethods_for_deoptimization(&deopt_scope);
9723 + deopt_scope.deoptimize_marked();
9727 +// Do clean-up on "all door clients detached" event.
9728 +void DTrace::detach_all_clients() {
9729 + disable_dprobes(DTRACE_ALL_PROBES);
9732 +void DTrace::set_monitor_dprobes(bool flag) {
9733 + // explicit setting of DTraceMonitorProbes flag
9734 + set_bool_flag("DTraceMonitorProbes", flag);
9737 +#endif /* SOLARIS */
9738 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/share/services/memTracker.cpp jdk21u-jdk-21.0.4-ga/src/hotspot/share/services/memTracker.cpp
9739 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/share/services/memTracker.cpp 2024-07-09 10:07:16.000000000 +0200
9740 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/share/services/memTracker.cpp 2024-08-17 19:13:01.392977560 +0200
9741 @@ -48,6 +48,12 @@
9742 #include <windows.h>
9743 #endif
9745 +#ifdef SOLARIS
9746 + volatile bool NMT_stack_walkable = false;
9747 +#else
9748 + volatile bool NMT_stack_walkable = true;
9749 +#endif
9751 NMT_TrackingLevel MemTracker::_tracking_level = NMT_unknown;
9753 MemBaseline MemTracker::_baseline;
9754 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/share/services/memTracker.hpp jdk21u-jdk-21.0.4-ga/src/hotspot/share/services/memTracker.hpp
9755 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/share/services/memTracker.hpp 2024-07-09 10:07:16.000000000 +0200
9756 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/share/services/memTracker.hpp 2024-08-17 19:13:01.393405425 +0200
9757 @@ -34,9 +34,11 @@
9758 #include "utilities/debug.hpp"
9759 #include "utilities/nativeCallStack.hpp"
9761 -#define CURRENT_PC ((MemTracker::tracking_level() == NMT_detail) ? \
9762 +extern volatile bool NMT_stack_walkable;
9764 +#define CURRENT_PC ((MemTracker::tracking_level() == NMT_detail && NMT_stack_walkable) ? \
9765 NativeCallStack(0) : FAKE_CALLSTACK)
9766 -#define CALLER_PC ((MemTracker::tracking_level() == NMT_detail) ? \
9767 +#define CALLER_PC ((MemTracker::tracking_level() == NMT_detail && NMT_stack_walkable) ? \
9768 NativeCallStack(1) : FAKE_CALLSTACK)
9770 class MemBaseline;
9771 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/share/utilities/debug.cpp jdk21u-jdk-21.0.4-ga/src/hotspot/share/utilities/debug.cpp
9772 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/share/utilities/debug.cpp 2024-07-09 10:07:16.000000000 +0200
9773 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/share/utilities/debug.cpp 2024-08-17 19:13:01.394074594 +0200
9774 @@ -612,11 +612,12 @@
9775 tty->print_cr(" findm(intptr_t pc) - finds Method*");
9776 tty->print_cr(" find(intptr_t x) - finds & prints nmethod/stub/bytecode/oop based on pointer into it");
9777 tty->print_cr(" pns(void* sp, void* fp, void* pc) - print native (i.e. mixed) stack trace. E.g.");
9778 - tty->print_cr(" pns($sp, $rbp, $pc) on Linux/amd64 or");
9779 + tty->print_cr(" pns($sp, $rbp, $pc) on Linux/amd64 and Solaris/amd64 or");
9780 tty->print_cr(" pns($sp, $ebp, $pc) on Linux/x86 or");
9781 tty->print_cr(" pns($sp, $fp, $pc) on Linux/AArch64 or");
9782 tty->print_cr(" pns($sp, 0, $pc) on Linux/ppc64 or");
9783 tty->print_cr(" pns($sp, $s8, $pc) on Linux/mips or");
9784 + tty->print_cr(" pns($sp + 0x7ff, 0, $pc) on Solaris/SPARC");
9785 tty->print_cr(" - in gdb do 'set overload-resolution off' before calling pns()");
9786 tty->print_cr(" - in dbx do 'frame 1' before calling pns()");
9787 tty->print_cr("class metadata.");
9788 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/share/utilities/globalDefinitions_gcc.hpp jdk21u-jdk-21.0.4-ga/src/hotspot/share/utilities/globalDefinitions_gcc.hpp
9789 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/share/utilities/globalDefinitions_gcc.hpp 2024-07-09 10:07:16.000000000 +0200
9790 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/share/utilities/globalDefinitions_gcc.hpp 2024-08-17 19:13:01.394646518 +0200
9791 @@ -39,15 +39,36 @@
9792 #include <stdlib.h>
9793 #include <wchar.h>
9795 +#ifdef SOLARIS
9796 +#include <ieeefp.h>
9797 +#endif // SOLARIS
9799 #include <math.h>
9800 #include <time.h>
9801 #include <fcntl.h>
9802 #include <dlfcn.h>
9803 #include <pthread.h>
9805 +#ifdef SOLARIS
9806 +#include <thread.h>
9807 +#endif // SOLARIS
9809 #include <limits.h>
9810 #include <errno.h>
9812 +#ifdef SOLARIS
9813 +#include <sys/trap.h>
9814 +#include <sys/regset.h>
9815 +#include <sys/procset.h>
9816 +#include <ucontext.h>
9817 +#include <setjmp.h>
9818 +#include <inttypes.h>
9819 +#endif // SOLARIS
9821 +# ifdef SOLARIS_MUTATOR_LIBTHREAD
9822 +# include <sys/procfs.h>
9823 +# endif
9825 #if defined(LINUX) || defined(_ALLBSD_SOURCE)
9826 #include <inttypes.h>
9827 #include <signal.h>
9828 @@ -61,6 +82,34 @@
9829 #include <sys/time.h>
9830 #endif // LINUX || _ALLBSD_SOURCE
9832 +// 4810578: varargs unsafe on 32-bit integer/64-bit pointer architectures
9833 +// When __cplusplus is defined, NULL is defined as 0 (32-bit constant) in
9834 +// system header files. On 32-bit architectures, there is no problem.
9835 +// On 64-bit architectures, defining NULL as a 32-bit constant can cause
9836 +// problems with varargs functions: C++ integral promotion rules say for
9837 +// varargs, we pass the argument 0 as an int. So, if NULL was passed to a
9838 +// varargs function it will remain 32-bits. Depending on the calling
9839 +// convention of the machine, if the argument is passed on the stack then
9840 +// only 32-bits of the "NULL" pointer may be initialized to zero. The
9841 +// other 32-bits will be garbage. If the varargs function is expecting a
9842 +// pointer when it extracts the argument, then we have a problem.
9844 +// Solution: For 64-bit architectures, redefine NULL as 64-bit constant 0.
9846 +// Note: this fix doesn't work well on Linux because NULL will be overwritten
9847 +// whenever a system header file is included. Linux handles NULL correctly
9848 +// through a special type '__null'.
9849 +#ifdef SOLARIS
9850 + #ifdef _LP64
9851 + #undef NULL
9852 + #define NULL 0L
9853 + #else
9854 + #ifndef NULL
9855 + #define NULL 0
9856 + #endif
9857 + #endif
9858 +#endif
9860 // NULL vs NULL_WORD:
9861 // On Linux NULL is defined as a special type '__null'. Assigning __null to
9862 // integer variable will cause gcc warning. Use NULL_WORD in places where a
9863 @@ -101,8 +150,52 @@
9865 #endif // !LINUX && !_ALLBSD_SOURCE
9868 +#ifdef SOLARIS
9869 +// ANSI C++ fixes
9870 +// NOTE:In the ANSI committee's continuing attempt to make each version
9871 +// of C++ incompatible with the previous version, you can no longer cast
9872 +// pointers to functions without specifying linkage unless you want to get
9873 +// warnings.
9875 +// This also means that pointers to functions can no longer be "hidden"
9876 +// in opaque types like void * because at the invocation point warnings
9877 +// will be generated. While this makes perfect sense from a type safety
9878 +// point of view it causes a lot of warnings on old code using C header
9879 +// files. Here are some typedefs to make the job of silencing warnings
9880 +// a bit easier.
9882 +// The final kick in the teeth is that you can only have extern "C" linkage
9883 +// specified at file scope. So these typedefs are here rather than in the
9884 +// .hpp for the class (os:Solaris usually) that needs them.
9886 +extern "C" {
9887 + typedef int (*int_fnP_thread_t_iP_uP_stack_tP_gregset_t)(thread_t, int*, unsigned *, stack_t*, gregset_t);
9888 + typedef int (*int_fnP_thread_t_i_gregset_t)(thread_t, int, gregset_t);
9889 + typedef int (*int_fnP_thread_t_i)(thread_t, int);
9890 + typedef int (*int_fnP_thread_t)(thread_t);
9892 + typedef int (*int_fnP_cond_tP_mutex_tP_timestruc_tP)(cond_t *cv, mutex_t *mx, timestruc_t *abst);
9893 + typedef int (*int_fnP_cond_tP_mutex_tP)(cond_t *cv, mutex_t *mx);
9895 + // typedef for missing API in libc
9896 + typedef int (*int_fnP_mutex_tP_i_vP)(mutex_t *, int, void *);
9897 + typedef int (*int_fnP_mutex_tP)(mutex_t *);
9898 + typedef int (*int_fnP_cond_tP_i_vP)(cond_t *cv, int scope, void *arg);
9899 + typedef int (*int_fnP_cond_tP)(cond_t *cv);
9901 +#endif // SOLARIS
9903 // checking for nanness
9904 -#if defined(__APPLE__)
9905 +#ifdef SOLARIS
9906 +#ifdef SPARC
9907 +inline int g_isnan(float f) { return isnanf(f); }
9908 +#else
9909 +// isnanf() broken on Intel Solaris use isnand()
9910 +inline int g_isnan(float f) { return isnand(f); }
9911 +#endif
9912 +inline int g_isnan(double f) { return isnand(f); }
9913 +#elif defined(__APPLE__)
9914 inline int g_isnan(double f) { return isnan(f); }
9915 #elif defined(LINUX) || defined(_ALLBSD_SOURCE)
9916 inline int g_isnan(float f) { return isnan(f); }
9917 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/share/utilities/macros.hpp jdk21u-jdk-21.0.4-ga/src/hotspot/share/utilities/macros.hpp
9918 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/share/utilities/macros.hpp 2024-07-09 10:07:16.000000000 +0200
9919 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/share/utilities/macros.hpp 2024-08-17 19:13:01.395155575 +0200
9920 @@ -401,6 +401,14 @@
9921 #define NOT_AIX(code) code
9922 #endif
9924 +#ifdef SOLARIS
9925 +#define SOLARIS_ONLY(code) code
9926 +#define NOT_SOLARIS(code)
9927 +#else
9928 +#define SOLARIS_ONLY(code)
9929 +#define NOT_SOLARIS(code) code
9930 +#endif
9932 #ifdef _WINDOWS
9933 #define WINDOWS_ONLY(code) code
9934 #define NOT_WINDOWS(code)
9935 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/share/utilities/ostream.cpp jdk21u-jdk-21.0.4-ga/src/hotspot/share/utilities/ostream.cpp
9936 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/share/utilities/ostream.cpp 2024-07-09 10:07:16.000000000 +0200
9937 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/share/utilities/ostream.cpp 2024-08-17 19:13:01.395780079 +0200
9938 @@ -1082,7 +1082,7 @@
9940 #ifndef PRODUCT
9942 -#if defined(LINUX) || defined(AIX) || defined(_ALLBSD_SOURCE)
9943 +#if defined(SOLARIS) || defined(LINUX) || defined(AIX) || defined(_ALLBSD_SOURCE)
9944 #include <sys/types.h>
9945 #include <sys/socket.h>
9946 #include <netinet/in.h>
9947 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/hotspot/share/utilities/vmError.cpp jdk21u-jdk-21.0.4-ga/src/hotspot/share/utilities/vmError.cpp
9948 --- jdk21u-jdk-21.0.4-ga.orig/src/hotspot/share/utilities/vmError.cpp 2024-07-09 10:07:16.000000000 +0200
9949 +++ jdk21u-jdk-21.0.4-ga/src/hotspot/share/utilities/vmError.cpp 2024-08-17 19:13:01.396636852 +0200
9950 @@ -1890,6 +1890,8 @@
9951 out.print_raw ("# Executing ");
9952 #if defined(LINUX) || defined(_ALLBSD_SOURCE)
9953 out.print_raw ("/bin/sh -c ");
9954 +#elif defined(SOLARIS)
9955 + out.print_raw ("/usr/bin/sh -c ");
9956 #elif defined(_WINDOWS)
9957 out.print_raw ("cmd /C ");
9958 #endif
9959 @@ -1954,6 +1956,8 @@
9960 tty->print("# Executing ");
9961 #if defined(LINUX)
9962 tty->print ("/bin/sh -c ");
9963 +#elif defined(SOLARIS)
9964 + tty->print ("/usr/bin/sh -c ");
9965 #endif
9966 tty->print_cr("\"%s\"...", cmd);
9968 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/share/classes/sun/net/sdp/SdpSupport.java jdk21u-jdk-21.0.4-ga/src/java.base/share/classes/sun/net/sdp/SdpSupport.java
9969 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/share/classes/sun/net/sdp/SdpSupport.java 2024-07-09 10:07:16.000000000 +0200
9970 +++ jdk21u-jdk-21.0.4-ga/src/java.base/share/classes/sun/net/sdp/SdpSupport.java 2024-08-17 19:13:01.397259198 +0200
9971 @@ -39,7 +39,7 @@
9974 public final class SdpSupport {
9975 - private static final boolean isSupported = OperatingSystem.isLinux();
9976 + private static final boolean isSupported = (OperatingSystem.isSolaris() || OperatingSystem.isLinux());
9977 private static final JavaIOFileDescriptorAccess fdAccess =
9978 SharedSecrets.getJavaIOFileDescriptorAccess();
9980 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/share/classes/sun/nio/ch/Net.java jdk21u-jdk-21.0.4-ga/src/java.base/share/classes/sun/nio/ch/Net.java
9981 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/share/classes/sun/nio/ch/Net.java 2024-07-09 10:07:16.000000000 +0200
9982 +++ jdk21u-jdk-21.0.4-ga/src/java.base/share/classes/sun/nio/ch/Net.java 2024-08-17 19:13:01.397907866 +0200
9983 @@ -512,7 +512,7 @@
9984 private static native boolean isReusePortAvailable0();
9987 - * Returns 1 for Windows and -1 for Linux/Mac OS
9988 + * Returns 1 for Windows and -1 for Solaris/Linux/Mac OS
9990 private static native int isExclusiveBindAvailable();
9992 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/share/classes/sun/nio/ch/SocketOptionRegistry.java.template jdk21u-jdk-21.0.4-ga/src/java.base/share/classes/sun/nio/ch/SocketOptionRegistry.java.template
9993 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/share/classes/sun/nio/ch/SocketOptionRegistry.java.template 2024-07-09 10:07:16.000000000 +0200
9994 +++ jdk21u-jdk-21.0.4-ga/src/java.base/share/classes/sun/nio/ch/SocketOptionRegistry.java.template 2024-08-17 19:13:01.398371274 +0200
9995 @@ -43,6 +43,8 @@
9996 #define SO_REUSEPORT 0
9997 #elif defined(__linux__)
9998 #define SO_REUSEPORT 15
9999 +#elif defined(__solaris__)
10000 +#define SO_REUSEPORT 0x100e
10001 #elif defined(AIX) || defined(MACOSX)
10002 #define SO_REUSEPORT 0x0200
10003 #else
10004 @@ -50,6 +52,10 @@
10005 #endif
10006 #endif
10008 +/* On Solaris, "sun" is defined as a macro. Undefine to make package
10009 + declaration valid */
10010 +#undef sun
10012 /* To be able to name the Java constants the same as the C constants without
10013 having the preprocessor rewrite those identifiers, add PREFIX_ to all
10014 identifiers matching a C constant. The PREFIX_ is filtered out in the
10015 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/share/conf/security/java.security jdk21u-jdk-21.0.4-ga/src/java.base/share/conf/security/java.security
10016 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/share/conf/security/java.security 2024-07-09 10:07:16.000000000 +0200
10017 +++ jdk21u-jdk-21.0.4-ga/src/java.base/share/conf/security/java.security 2024-08-17 19:13:01.399171730 +0200
10018 @@ -83,7 +83,11 @@
10019 #ifdef macosx
10020 security.provider.tbd=Apple
10021 #endif
10022 +#ifdef solaris
10023 +security.provider.tbd=SunPKCS11 ${java.home}/conf/security/sunpkcs11-solaris.cfg
10024 +#else
10025 security.provider.tbd=SunPKCS11
10026 +#endif
10029 # A list of preferred providers for specific algorithms. These providers will
10030 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/share/native/libjli/jli_util.h jdk21u-jdk-21.0.4-ga/src/java.base/share/native/libjli/jli_util.h
10031 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/share/native/libjli/jli_util.h 2024-07-09 10:07:16.000000000 +0200
10032 +++ jdk21u-jdk-21.0.4-ga/src/java.base/share/native/libjli/jli_util.h 2024-08-17 19:13:01.399670058 +0200
10033 @@ -100,6 +100,9 @@
10034 #define JLI_StrCaseCmp(p1, p2) strcasecmp((p1), (p2))
10035 #define JLI_StrNCaseCmp(p1, p2, p3) strncasecmp((p1), (p2), (p3))
10036 #define JLI_Open open
10037 +#ifdef __solaris__
10038 +#define JLI_Lseek llseek
10039 +#endif
10040 #ifdef __linux__
10041 #define _LARGFILE64_SOURCE
10042 #define JLI_Lseek lseek64
10043 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/share/native/libnet/net_util.c jdk21u-jdk-21.0.4-ga/src/java.base/share/native/libnet/net_util.c
10044 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/share/native/libnet/net_util.c 2024-07-09 10:07:16.000000000 +0200
10045 +++ jdk21u-jdk-21.0.4-ga/src/java.base/share/native/libnet/net_util.c 2024-08-17 19:13:01.400134328 +0200
10046 @@ -81,6 +81,7 @@
10048 /* check if SO_REUSEPORT is supported on this platform */
10049 REUSEPORT_available = reuseport_supported(IPv6_available);
10050 + parseExclusiveBindProperty(env);
10052 return JNI_VERSION_1_2;
10054 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/share/native/libnet/net_util.h jdk21u-jdk-21.0.4-ga/src/java.base/share/native/libnet/net_util.h
10055 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/share/native/libnet/net_util.h 2024-07-09 10:07:16.000000000 +0200
10056 +++ jdk21u-jdk-21.0.4-ga/src/java.base/share/native/libnet/net_util.h 2024-08-17 19:13:01.400572397 +0200
10057 @@ -142,6 +142,8 @@
10058 JNIEXPORT jobject JNICALL
10059 NET_SockaddrToInetAddress(JNIEnv *env, SOCKETADDRESS *sa, int *port);
10061 +void parseExclusiveBindProperty(JNIEnv *env);
10063 JNIEXPORT jint JNICALL NET_GetPortFromSockaddr(SOCKETADDRESS *sa);
10065 JNIEXPORT jboolean JNICALL
10066 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java jdk21u-jdk-21.0.4-ga/src/java.base/solaris/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java
10067 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java 1970-01-01 01:00:00.000000000 +0100
10068 +++ jdk21u-jdk-21.0.4-ga/src/java.base/solaris/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java 2024-08-17 19:13:01.456463718 +0200
10069 @@ -0,0 +1,47 @@
10071 + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
10072 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
10074 + * This code is free software; you can redistribute it and/or modify it
10075 + * under the terms of the GNU General Public License version 2 only, as
10076 + * published by the Free Software Foundation. Oracle designates this
10077 + * particular file as subject to the "Classpath" exception as provided
10078 + * by Oracle in the LICENSE file that accompanied this code.
10080 + * This code is distributed in the hope that it will be useful, but WITHOUT
10081 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10082 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
10083 + * version 2 for more details (a copy is included in the LICENSE file that
10084 + * accompanied this code).
10086 + * You should have received a copy of the GNU General Public License version
10087 + * 2 along with this work; if not, write to the Free Software Foundation,
10088 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
10090 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
10091 + * or visit www.oracle.com if you need additional information or have any
10092 + * questions.
10093 + */
10095 +package sun.nio.ch;
10097 +import java.nio.channels.spi.AsynchronousChannelProvider;
10099 +/**
10100 + * Creates this platform's default AsynchronousChannelProvider
10101 + */
10103 +public class DefaultAsynchronousChannelProvider {
10105 + /**
10106 + * Prevent instantiation.
10107 + */
10108 + private DefaultAsynchronousChannelProvider() { }
10110 + /**
10111 + * Returns the default AsynchronousChannelProvider.
10112 + */
10113 + public static AsynchronousChannelProvider create() {
10114 + return new SolarisAsynchronousChannelProvider();
10117 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/classes/sun/nio/ch/DefaultSelectorProvider.java jdk21u-jdk-21.0.4-ga/src/java.base/solaris/classes/sun/nio/ch/DefaultSelectorProvider.java
10118 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/classes/sun/nio/ch/DefaultSelectorProvider.java 1970-01-01 01:00:00.000000000 +0100
10119 +++ jdk21u-jdk-21.0.4-ga/src/java.base/solaris/classes/sun/nio/ch/DefaultSelectorProvider.java 2024-08-17 19:13:01.456798196 +0200
10120 @@ -0,0 +1,54 @@
10122 + * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
10123 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
10125 + * This code is free software; you can redistribute it and/or modify it
10126 + * under the terms of the GNU General Public License version 2 only, as
10127 + * published by the Free Software Foundation. Oracle designates this
10128 + * particular file as subject to the "Classpath" exception as provided
10129 + * by Oracle in the LICENSE file that accompanied this code.
10131 + * This code is distributed in the hope that it will be useful, but WITHOUT
10132 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10133 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
10134 + * version 2 for more details (a copy is included in the LICENSE file that
10135 + * accompanied this code).
10137 + * You should have received a copy of the GNU General Public License version
10138 + * 2 along with this work; if not, write to the Free Software Foundation,
10139 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
10141 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
10142 + * or visit www.oracle.com if you need additional information or have any
10143 + * questions.
10144 + */
10146 +package sun.nio.ch;
10148 +import java.security.AccessController;
10149 +import java.security.PrivilegedAction;
10151 +/**
10152 + * Creates this platform's default SelectorProvider
10153 + */
10155 +@SuppressWarnings("removal")
10156 +public class DefaultSelectorProvider {
10157 + private static final SelectorProviderImpl INSTANCE;
10158 + static {
10159 + PrivilegedAction<SelectorProviderImpl> pa = DevPollSelectorProvider::new;
10160 + INSTANCE = AccessController.doPrivileged(pa);
10163 + /**
10164 + * Prevent instantiation.
10165 + */
10166 + private DefaultSelectorProvider() { }
10168 + /**
10169 + * Returns the default SelectorProvider implementation.
10170 + */
10171 + public static SelectorProviderImpl get() {
10172 + return INSTANCE;
10175 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java jdk21u-jdk-21.0.4-ga/src/java.base/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java
10176 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java 1970-01-01 01:00:00.000000000 +0100
10177 +++ jdk21u-jdk-21.0.4-ga/src/java.base/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java 2024-08-17 19:13:01.457148361 +0200
10178 @@ -0,0 +1,127 @@
10180 + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
10181 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
10183 + * This code is free software; you can redistribute it and/or modify it
10184 + * under the terms of the GNU General Public License version 2 only, as
10185 + * published by the Free Software Foundation. Oracle designates this
10186 + * particular file as subject to the "Classpath" exception as provided
10187 + * by Oracle in the LICENSE file that accompanied this code.
10189 + * This code is distributed in the hope that it will be useful, but WITHOUT
10190 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10191 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
10192 + * version 2 for more details (a copy is included in the LICENSE file that
10193 + * accompanied this code).
10195 + * You should have received a copy of the GNU General Public License version
10196 + * 2 along with this work; if not, write to the Free Software Foundation,
10197 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
10199 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
10200 + * or visit www.oracle.com if you need additional information or have any
10201 + * questions.
10202 + */
10204 +package sun.nio.ch;
10206 +import java.io.IOException;
10208 +/**
10209 + * Manipulates a native array of pollfd structs on Solaris:
10211 + * typedef struct pollfd {
10212 + * int fd;
10213 + * short events;
10214 + * short revents;
10215 + * } pollfd_t;
10217 + * @author Mike McCloskey
10218 + * @since 1.4
10219 + */
10221 +class DevPollArrayWrapper {
10223 + // special event to remove a file descriptor from the driver
10224 + static final short POLLREMOVE = 0x0800;
10226 + // struct pollfd constants
10227 + static final short SIZE_POLLFD = 8;
10228 + static final short FD_OFFSET = 0;
10229 + static final short EVENT_OFFSET = 4;
10230 + static final short REVENT_OFFSET = 6;
10232 + // maximum number of pollfd structure to poll or update at a time
10233 + // dpwrite/ioctl(DP_POLL) allows up to file descriptor limit minus 1
10234 + static final int NUM_POLLFDS = Math.min(IOUtil.fdLimit()-1, 1024);
10236 + // The pollfd array for results from devpoll driver
10237 + private final AllocatedNativeObject pollArray;
10239 + // Base address of the native pollArray
10240 + private final long pollArrayAddress;
10242 + // The fd of the devpoll driver
10243 + private int wfd;
10245 + DevPollArrayWrapper() throws IOException {
10246 + this.wfd = init();
10248 + int allocationSize = NUM_POLLFDS * SIZE_POLLFD;
10249 + this.pollArray = new AllocatedNativeObject(allocationSize, true);
10250 + this.pollArrayAddress = pollArray.address();
10253 + void close() throws IOException {
10254 + FileDispatcherImpl.closeIntFD(wfd);
10255 + pollArray.free();
10258 + void register(int fd, int ops) throws IOException {
10259 + register(wfd, fd, ops);
10262 + void registerMultiple(int numfds) throws IOException {
10263 + registerMultiple(wfd, pollArrayAddress, numfds);
10266 + int poll(long timeout) throws IOException {
10267 + return poll0(pollArrayAddress, NUM_POLLFDS, timeout, wfd);
10270 + int getDescriptor(int i) {
10271 + int offset = SIZE_POLLFD * i + FD_OFFSET;
10272 + return pollArray.getInt(offset);
10275 + short getEventOps(int i) {
10276 + int offset = SIZE_POLLFD * i + EVENT_OFFSET;
10277 + return pollArray.getShort(offset);
10280 + short getReventOps(int i) {
10281 + int offset = SIZE_POLLFD * i + REVENT_OFFSET;
10282 + return pollArray.getShort(offset);
10285 + /**
10286 + * Updates the pollfd structure at the given index
10287 + */
10288 + void putPollFD(int index, int fd, short event) {
10289 + int structIndex = SIZE_POLLFD * index;
10290 + pollArray.putInt(structIndex + FD_OFFSET, fd);
10291 + pollArray.putShort(structIndex + EVENT_OFFSET, event);
10292 + pollArray.putShort(structIndex + REVENT_OFFSET, (short)0);
10295 + private native int init() throws IOException;
10296 + private native void register(int wfd, int fd, int mask) throws IOException;
10297 + private native void registerMultiple(int wfd, long address, int len)
10298 + throws IOException;
10299 + private native int poll0(long pollAddress, int numfds, long timeout, int wfd)
10300 + throws IOException;
10302 + static {
10303 + IOUtil.load();
10306 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java jdk21u-jdk-21.0.4-ga/src/java.base/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java
10307 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java 1970-01-01 01:00:00.000000000 +0100
10308 +++ jdk21u-jdk-21.0.4-ga/src/java.base/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java 2024-08-17 19:13:01.457565949 +0200
10309 @@ -0,0 +1,263 @@
10311 + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
10312 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
10314 + * This code is free software; you can redistribute it and/or modify it
10315 + * under the terms of the GNU General Public License version 2 only, as
10316 + * published by the Free Software Foundation. Oracle designates this
10317 + * particular file as subject to the "Classpath" exception as provided
10318 + * by Oracle in the LICENSE file that accompanied this code.
10320 + * This code is distributed in the hope that it will be useful, but WITHOUT
10321 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10322 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
10323 + * version 2 for more details (a copy is included in the LICENSE file that
10324 + * accompanied this code).
10326 + * You should have received a copy of the GNU General Public License version
10327 + * 2 along with this work; if not, write to the Free Software Foundation,
10328 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
10330 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
10331 + * or visit www.oracle.com if you need additional information or have any
10332 + * questions.
10333 + */
10335 +package sun.nio.ch;
10337 +import java.io.IOException;
10338 +import java.nio.channels.ClosedSelectorException;
10339 +import java.nio.channels.SelectionKey;
10340 +import java.nio.channels.Selector;
10341 +import java.nio.channels.spi.SelectorProvider;
10342 +import java.util.ArrayDeque;
10343 +import java.util.Deque;
10344 +import java.util.HashMap;
10345 +import java.util.Map;
10346 +import java.util.concurrent.TimeUnit;
10347 +import java.util.function.Consumer;
10349 +import static sun.nio.ch.DevPollArrayWrapper.NUM_POLLFDS;
10350 +import static sun.nio.ch.DevPollArrayWrapper.POLLREMOVE;
10352 +/**
10353 + * Solaris /dev/poll based Selector implementation
10354 + */
10356 +class DevPollSelectorImpl
10357 + extends SelectorImpl
10359 + // provides access to /dev/poll driver
10360 + private final DevPollArrayWrapper pollWrapper;
10362 + // file descriptors used for interrupt
10363 + private final int fd0;
10364 + private final int fd1;
10366 + // maps file descriptor to selection key, synchronize on selector
10367 + private final Map<Integer, SelectionKeyImpl> fdToKey = new HashMap<>();
10369 + // pending new registrations/updates, queued by setEventOps
10370 + private final Object updateLock = new Object();
10371 + private final Deque<SelectionKeyImpl> updateKeys = new ArrayDeque<>();
10373 + // interrupt triggering and clearing
10374 + private final Object interruptLock = new Object();
10375 + private boolean interruptTriggered;
10377 + DevPollSelectorImpl(SelectorProvider sp) throws IOException {
10378 + super(sp);
10379 + this.pollWrapper = new DevPollArrayWrapper();
10380 + try {
10381 + long fds = IOUtil.makePipe(false);
10382 + this.fd0 = (int) (fds >>> 32);
10383 + this.fd1 = (int) fds;
10384 + } catch (IOException ioe) {
10385 + pollWrapper.close();
10386 + throw ioe;
10389 + // register one end of the socket pair for wakeups
10390 + pollWrapper.register(fd0, Net.POLLIN);
10393 + private void ensureOpen() {
10394 + if (!isOpen())
10395 + throw new ClosedSelectorException();
10398 + @Override
10399 + protected int doSelect(Consumer<SelectionKey> action, long timeout)
10400 + throws IOException
10402 + assert Thread.holdsLock(this);
10404 + long to = timeout;
10405 + boolean blocking = (to != 0);
10406 + boolean timedPoll = (to > 0);
10408 + int numEntries;
10409 + processUpdateQueue();
10410 + processDeregisterQueue();
10411 + try {
10412 + begin(blocking);
10414 + do {
10415 + long startTime = timedPoll ? System.nanoTime() : 0;
10416 + numEntries = pollWrapper.poll(to);
10417 + if (numEntries == IOStatus.INTERRUPTED && timedPoll) {
10418 + // timed poll interrupted so need to adjust timeout
10419 + long adjust = System.nanoTime() - startTime;
10420 + to -= TimeUnit.MILLISECONDS.convert(adjust, TimeUnit.NANOSECONDS);
10421 + if (to <= 0) {
10422 + // timeout expired so no retry
10423 + numEntries = 0;
10426 + } while (numEntries == IOStatus.INTERRUPTED);
10427 + assert IOStatus.check(numEntries);
10429 + } finally {
10430 + end(blocking);
10432 + processDeregisterQueue();
10433 + return processEvents(numEntries, action);
10436 + /**
10437 + * Process changes to the interest ops.
10438 + */
10439 + private void processUpdateQueue() throws IOException {
10440 + assert Thread.holdsLock(this);
10442 + synchronized (updateLock) {
10443 + SelectionKeyImpl ski;
10445 + // Translate the queued updates to changes to the set of monitored
10446 + // file descriptors. The changes are written to the /dev/poll driver
10447 + // in bulk.
10448 + int index = 0;
10449 + while ((ski = updateKeys.pollFirst()) != null) {
10450 + if (ski.isValid()) {
10451 + int fd = ski.getFDVal();
10452 + // add to fdToKey if needed
10453 + SelectionKeyImpl previous = fdToKey.putIfAbsent(fd, ski);
10454 + assert (previous == null) || (previous == ski);
10456 + int newEvents = ski.translateInterestOps();
10457 + int registeredEvents = ski.registeredEvents();
10458 + if (newEvents != registeredEvents) {
10459 + if (registeredEvents != 0)
10460 + pollWrapper.putPollFD(index++, fd, POLLREMOVE);
10461 + if (newEvents != 0)
10462 + pollWrapper.putPollFD(index++, fd, (short)newEvents);
10463 + ski.registeredEvents(newEvents);
10465 + // write to /dev/poll
10466 + if (index > (NUM_POLLFDS-2)) {
10467 + pollWrapper.registerMultiple(index);
10468 + index = 0;
10474 + // write any remaining changes
10475 + if (index > 0)
10476 + pollWrapper.registerMultiple(index);
10480 + /**
10481 + * Process the polled events.
10482 + * If the interrupt fd has been selected, drain it and clear the interrupt.
10483 + */
10484 + private int processEvents(int numEntries, Consumer<SelectionKey> action)
10485 + throws IOException
10487 + assert Thread.holdsLock(this);
10489 + boolean interrupted = false;
10490 + int numKeysUpdated = 0;
10491 + for (int i=0; i<numEntries; i++) {
10492 + int fd = pollWrapper.getDescriptor(i);
10493 + if (fd == fd0) {
10494 + interrupted = true;
10495 + } else {
10496 + SelectionKeyImpl ski = fdToKey.get(fd);
10497 + if (ski != null) {
10498 + int rOps = pollWrapper.getReventOps(i);
10499 + numKeysUpdated += processReadyEvents(rOps, ski, action);
10504 + if (interrupted) {
10505 + clearInterrupt();
10508 + return numKeysUpdated;
10511 + @Override
10512 + protected void implClose() throws IOException {
10513 + assert !isOpen();
10514 + assert Thread.holdsLock(this);
10516 + // prevent further wakeup
10517 + synchronized (interruptLock) {
10518 + interruptTriggered = true;
10521 + pollWrapper.close();
10522 + FileDispatcherImpl.closeIntFD(fd0);
10523 + FileDispatcherImpl.closeIntFD(fd1);
10527 + @Override
10528 + protected void implDereg(SelectionKeyImpl ski) throws IOException {
10529 + assert !ski.isValid();
10530 + assert Thread.holdsLock(this);
10532 + int fd = ski.getFDVal();
10533 + if (fdToKey.remove(fd) != null) {
10534 + if (ski.registeredEvents() != 0) {
10535 + pollWrapper.register(fd, POLLREMOVE);
10536 + ski.registeredEvents(0);
10538 + } else {
10539 + assert ski.registeredEvents() == 0;
10543 + @Override
10544 + public void setEventOps(SelectionKeyImpl ski) {
10545 + ensureOpen();
10546 + synchronized (updateLock) {
10547 + updateKeys.addLast(ski);
10551 + @Override
10552 + public Selector wakeup() {
10553 + synchronized (interruptLock) {
10554 + if (!interruptTriggered) {
10555 + try {
10556 + IOUtil.write1(fd1, (byte)0);
10557 + } catch (IOException ioe) {
10558 + throw new InternalError(ioe);
10560 + interruptTriggered = true;
10563 + return this;
10566 + private void clearInterrupt() throws IOException {
10567 + synchronized (interruptLock) {
10568 + IOUtil.drain(fd0);
10569 + interruptTriggered = false;
10573 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/classes/sun/nio/ch/DevPollSelectorProvider.java jdk21u-jdk-21.0.4-ga/src/java.base/solaris/classes/sun/nio/ch/DevPollSelectorProvider.java
10574 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/classes/sun/nio/ch/DevPollSelectorProvider.java 1970-01-01 01:00:00.000000000 +0100
10575 +++ jdk21u-jdk-21.0.4-ga/src/java.base/solaris/classes/sun/nio/ch/DevPollSelectorProvider.java 2024-08-17 19:13:01.457872975 +0200
10576 @@ -0,0 +1,42 @@
10578 + * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
10579 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
10581 + * This code is free software; you can redistribute it and/or modify it
10582 + * under the terms of the GNU General Public License version 2 only, as
10583 + * published by the Free Software Foundation. Oracle designates this
10584 + * particular file as subject to the "Classpath" exception as provided
10585 + * by Oracle in the LICENSE file that accompanied this code.
10587 + * This code is distributed in the hope that it will be useful, but WITHOUT
10588 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10589 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
10590 + * version 2 for more details (a copy is included in the LICENSE file that
10591 + * accompanied this code).
10593 + * You should have received a copy of the GNU General Public License version
10594 + * 2 along with this work; if not, write to the Free Software Foundation,
10595 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
10597 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
10598 + * or visit www.oracle.com if you need additional information or have any
10599 + * questions.
10600 + */
10602 +package sun.nio.ch;
10604 +import java.io.IOException;
10605 +import java.nio.channels.*;
10606 +import java.nio.channels.spi.*;
10608 +public class DevPollSelectorProvider
10609 + extends SelectorProviderImpl
10611 + public AbstractSelector openSelector() throws IOException {
10612 + return new DevPollSelectorImpl(this);
10615 + public Channel inheritedChannel() throws IOException {
10616 + return InheritedChannel.getChannel();
10619 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/classes/sun/nio/ch/EventPortSelectorImpl.java jdk21u-jdk-21.0.4-ga/src/java.base/solaris/classes/sun/nio/ch/EventPortSelectorImpl.java
10620 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/classes/sun/nio/ch/EventPortSelectorImpl.java 1970-01-01 01:00:00.000000000 +0100
10621 +++ jdk21u-jdk-21.0.4-ga/src/java.base/solaris/classes/sun/nio/ch/EventPortSelectorImpl.java 2024-08-17 19:13:01.458495953 +0200
10622 @@ -0,0 +1,308 @@
10624 + * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
10625 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
10627 + * This code is free software; you can redistribute it and/or modify it
10628 + * under the terms of the GNU General Public License version 2 only, as
10629 + * published by the Free Software Foundation. Oracle designates this
10630 + * particular file as subject to the "Classpath" exception as provided
10631 + * by Oracle in the LICENSE file that accompanied this code.
10633 + * This code is distributed in the hope that it will be useful, but WITHOUT
10634 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10635 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
10636 + * version 2 for more details (a copy is included in the LICENSE file that
10637 + * accompanied this code).
10639 + * You should have received a copy of the GNU General Public License version
10640 + * 2 along with this work; if not, write to the Free Software Foundation,
10641 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
10643 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
10644 + * or visit www.oracle.com if you need additional information or have any
10645 + * questions.
10646 + */
10648 +package sun.nio.ch;
10650 +import java.io.IOException;
10651 +import java.nio.channels.ClosedSelectorException;
10652 +import java.nio.channels.SelectionKey;
10653 +import java.nio.channels.Selector;
10654 +import java.nio.channels.spi.SelectorProvider;
10655 +import java.util.ArrayDeque;
10656 +import java.util.Deque;
10657 +import java.util.HashMap;
10658 +import java.util.Map;
10659 +import java.util.concurrent.TimeUnit;
10660 +import java.util.function.Consumer;
10662 +import static sun.nio.ch.SolarisEventPort.PORT_SOURCE_FD;
10663 +import static sun.nio.ch.SolarisEventPort.PORT_SOURCE_USER;
10664 +import static sun.nio.ch.SolarisEventPort.SIZEOF_PORT_EVENT;
10665 +import static sun.nio.ch.SolarisEventPort.OFFSETOF_EVENTS;
10666 +import static sun.nio.ch.SolarisEventPort.OFFSETOF_SOURCE;
10667 +import static sun.nio.ch.SolarisEventPort.OFFSETOF_OBJECT;
10668 +import static sun.nio.ch.SolarisEventPort.port_create;
10669 +import static sun.nio.ch.SolarisEventPort.port_close;
10670 +import static sun.nio.ch.SolarisEventPort.port_associate;
10671 +import static sun.nio.ch.SolarisEventPort.port_dissociate;
10672 +import static sun.nio.ch.SolarisEventPort.port_getn;
10673 +import static sun.nio.ch.SolarisEventPort.port_send;
10675 +/**
10676 + * Selector implementation based on the Solaris event port mechanism.
10677 + */
10679 +class EventPortSelectorImpl
10680 + extends SelectorImpl
10682 + // maximum number of events to retrive in one call to port_getn
10683 + static final int MAX_EVENTS = Math.min(IOUtil.fdLimit()-1, 1024);
10685 + // port file descriptor
10686 + private final int pfd;
10688 + // the poll array (populated by port_getn)
10689 + private final long pollArrayAddress;
10690 + private final AllocatedNativeObject pollArray;
10692 + // maps file descriptor to selection key, synchronize on selector
10693 + private final Map<Integer, SelectionKeyImpl> fdToKey = new HashMap<>();
10695 + // the last update operation, incremented by processUpdateQueue
10696 + private int lastUpdate;
10698 + // pending new registrations/updates, queued by setEventOps and
10699 + // updateSelectedKeys
10700 + private final Object updateLock = new Object();
10701 + private final Deque<SelectionKeyImpl> updateKeys = new ArrayDeque<>();
10703 + // interrupt triggering and clearing
10704 + private final Object interruptLock = new Object();
10705 + private boolean interruptTriggered;
10707 + EventPortSelectorImpl(SelectorProvider sp) throws IOException {
10708 + super(sp);
10710 + this.pfd = port_create();
10712 + int allocationSize = MAX_EVENTS * SIZEOF_PORT_EVENT;
10713 + this.pollArray = new AllocatedNativeObject(allocationSize, false);
10714 + this.pollArrayAddress = pollArray.address();
10717 + private void ensureOpen() {
10718 + if (!isOpen())
10719 + throw new ClosedSelectorException();
10722 + @Override
10723 + protected int doSelect(Consumer<SelectionKey> action, long timeout)
10724 + throws IOException
10726 + assert Thread.holdsLock(this);
10728 + long to = timeout;
10729 + boolean blocking = (to != 0);
10730 + boolean timedPoll = (to > 0);
10732 + int numEvents;
10733 + processUpdateQueue();
10734 + processDeregisterQueue();
10735 + try {
10736 + begin(blocking);
10738 + do {
10739 + long startTime = timedPoll ? System.nanoTime() : 0;
10740 + numEvents = port_getn(pfd, pollArrayAddress, MAX_EVENTS, to);
10741 + if (numEvents == IOStatus.INTERRUPTED && timedPoll) {
10742 + // timed poll interrupted so need to adjust timeout
10743 + long adjust = System.nanoTime() - startTime;
10744 + to -= TimeUnit.MILLISECONDS.convert(adjust, TimeUnit.NANOSECONDS);
10745 + if (to <= 0) {
10746 + // timeout also expired so no retry
10747 + numEvents = 0;
10750 + } while (numEvents == IOStatus.INTERRUPTED);
10751 + assert IOStatus.check(numEvents);
10753 + } finally {
10754 + end(blocking);
10756 + processDeregisterQueue();
10757 + return processPortEvents(numEvents, action);
10760 + /**
10761 + * Process new registrations and changes to the interest ops.
10762 + */
10763 + private void processUpdateQueue() throws IOException {
10764 + assert Thread.holdsLock(this);
10766 + // bump lastUpdate to ensure that the interest ops are changed at most
10767 + // once per bulk update
10768 + lastUpdate++;
10770 + synchronized (updateLock) {
10771 + SelectionKeyImpl ski;
10772 + while ((ski = updateKeys.pollFirst()) != null) {
10773 + if (ski.isValid()) {
10774 + int fd = ski.getFDVal();
10775 + // add to fdToKey if needed
10776 + SelectionKeyImpl previous = fdToKey.putIfAbsent(fd, ski);
10777 + assert (previous == null) || (previous == ski);
10779 + int newEvents = ski.translateInterestOps();
10780 + if (newEvents != ski.registeredEvents()) {
10781 + if (newEvents == 0) {
10782 + port_dissociate(pfd, PORT_SOURCE_FD, fd);
10783 + } else {
10784 + port_associate(pfd, PORT_SOURCE_FD, fd, newEvents);
10786 + ski.registeredEvents(newEvents);
10793 + /**
10794 + * Process the polled events and re-queue the selected keys so the file
10795 + * descriptors are re-associated at the next select operation.
10796 + */
10797 + private int processPortEvents(int numEvents, Consumer<SelectionKey> action)
10798 + throws IOException
10800 + assert Thread.holdsLock(this);
10802 + int numKeysUpdated = 0;
10803 + boolean interrupted = false;
10805 + // Process the polled events while holding the update lock. This allows
10806 + // keys to be queued for ready file descriptors so they can be
10807 + // re-associated at the next select. The selected-key can be updated
10808 + // in this pass.
10809 + synchronized (updateLock) {
10810 + for (int i = 0; i < numEvents; i++) {
10811 + short source = getSource(i);
10812 + if (source == PORT_SOURCE_FD) {
10813 + int fd = getDescriptor(i);
10814 + SelectionKeyImpl ski = fdToKey.get(fd);
10815 + if (ski != null) {
10816 + ski.registeredEvents(0);
10817 + updateKeys.addLast(ski);
10819 + // update selected-key set if no action specified
10820 + if (action == null) {
10821 + int rOps = getEventOps(i);
10822 + numKeysUpdated += processReadyEvents(rOps, ski, null);
10826 + } else if (source == PORT_SOURCE_USER) {
10827 + interrupted = true;
10828 + } else {
10829 + assert false;
10834 + // if an action specified then iterate over the polled events again so
10835 + // that the action is performed without holding the update lock.
10836 + if (action != null) {
10837 + for (int i = 0; i < numEvents; i++) {
10838 + short source = getSource(i);
10839 + if (source == PORT_SOURCE_FD) {
10840 + int fd = getDescriptor(i);
10841 + SelectionKeyImpl ski = fdToKey.get(fd);
10842 + if (ski != null) {
10843 + int rOps = getEventOps(i);
10844 + numKeysUpdated += processReadyEvents(rOps, ski, action);
10850 + if (interrupted) {
10851 + clearInterrupt();
10853 + return numKeysUpdated;
10856 + @Override
10857 + protected void implClose() throws IOException {
10858 + assert !isOpen();
10859 + assert Thread.holdsLock(this);
10861 + // prevent further wakeup
10862 + synchronized (interruptLock) {
10863 + interruptTriggered = true;
10866 + port_close(pfd);
10867 + pollArray.free();
10870 + @Override
10871 + protected void implDereg(SelectionKeyImpl ski) throws IOException {
10872 + assert !ski.isValid();
10873 + assert Thread.holdsLock(this);
10875 + int fd = ski.getFDVal();
10876 + if (fdToKey.remove(fd) != null) {
10877 + if (ski.registeredEvents() != 0) {
10878 + port_dissociate(pfd, PORT_SOURCE_FD, fd);
10879 + ski.registeredEvents(0);
10881 + } else {
10882 + assert ski.registeredEvents() == 0;
10886 + @Override
10887 + public void setEventOps(SelectionKeyImpl ski) {
10888 + ensureOpen();
10889 + synchronized (updateLock) {
10890 + updateKeys.addLast(ski);
10894 + @Override
10895 + public Selector wakeup() {
10896 + synchronized (interruptLock) {
10897 + if (!interruptTriggered) {
10898 + try {
10899 + port_send(pfd, 0);
10900 + } catch (IOException ioe) {
10901 + throw new InternalError(ioe);
10903 + interruptTriggered = true;
10906 + return this;
10909 + private void clearInterrupt() throws IOException {
10910 + synchronized (interruptLock) {
10911 + interruptTriggered = false;
10915 + private short getSource(int i) {
10916 + int offset = SIZEOF_PORT_EVENT * i + OFFSETOF_SOURCE;
10917 + return pollArray.getShort(offset);
10920 + private int getEventOps(int i) {
10921 + int offset = SIZEOF_PORT_EVENT * i + OFFSETOF_EVENTS;
10922 + return pollArray.getInt(offset);
10925 + private int getDescriptor(int i) {
10926 + //assert Unsafe.getUnsafe().addressSize() == 8;
10927 + int offset = SIZEOF_PORT_EVENT * i + OFFSETOF_OBJECT;
10928 + return (int) pollArray.getLong(offset);
10931 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/classes/sun/nio/ch/EventPortSelectorProvider.java jdk21u-jdk-21.0.4-ga/src/java.base/solaris/classes/sun/nio/ch/EventPortSelectorProvider.java
10932 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/classes/sun/nio/ch/EventPortSelectorProvider.java 1970-01-01 01:00:00.000000000 +0100
10933 +++ jdk21u-jdk-21.0.4-ga/src/java.base/solaris/classes/sun/nio/ch/EventPortSelectorProvider.java 2024-08-17 19:13:01.458814817 +0200
10934 @@ -0,0 +1,42 @@
10936 + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
10937 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
10939 + * This code is free software; you can redistribute it and/or modify it
10940 + * under the terms of the GNU General Public License version 2 only, as
10941 + * published by the Free Software Foundation. Oracle designates this
10942 + * particular file as subject to the "Classpath" exception as provided
10943 + * by Oracle in the LICENSE file that accompanied this code.
10945 + * This code is distributed in the hope that it will be useful, but WITHOUT
10946 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10947 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
10948 + * version 2 for more details (a copy is included in the LICENSE file that
10949 + * accompanied this code).
10951 + * You should have received a copy of the GNU General Public License version
10952 + * 2 along with this work; if not, write to the Free Software Foundation,
10953 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
10955 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
10956 + * or visit www.oracle.com if you need additional information or have any
10957 + * questions.
10958 + */
10960 +package sun.nio.ch;
10962 +import java.io.IOException;
10963 +import java.nio.channels.*;
10964 +import java.nio.channels.spi.*;
10966 +public class EventPortSelectorProvider
10967 + extends SelectorProviderImpl
10969 + public AbstractSelector openSelector() throws IOException {
10970 + return new EventPortSelectorImpl(this);
10973 + public Channel inheritedChannel() throws IOException {
10974 + return InheritedChannel.getChannel();
10977 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/classes/sun/nio/ch/SolarisAsynchronousChannelProvider.java jdk21u-jdk-21.0.4-ga/src/java.base/solaris/classes/sun/nio/ch/SolarisAsynchronousChannelProvider.java
10978 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/classes/sun/nio/ch/SolarisAsynchronousChannelProvider.java 1970-01-01 01:00:00.000000000 +0100
10979 +++ jdk21u-jdk-21.0.4-ga/src/java.base/solaris/classes/sun/nio/ch/SolarisAsynchronousChannelProvider.java 2024-08-17 19:13:01.459164484 +0200
10980 @@ -0,0 +1,93 @@
10982 + * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
10983 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
10985 + * This code is free software; you can redistribute it and/or modify it
10986 + * under the terms of the GNU General Public License version 2 only, as
10987 + * published by the Free Software Foundation. Oracle designates this
10988 + * particular file as subject to the "Classpath" exception as provided
10989 + * by Oracle in the LICENSE file that accompanied this code.
10991 + * This code is distributed in the hope that it will be useful, but WITHOUT
10992 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10993 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
10994 + * version 2 for more details (a copy is included in the LICENSE file that
10995 + * accompanied this code).
10997 + * You should have received a copy of the GNU General Public License version
10998 + * 2 along with this work; if not, write to the Free Software Foundation,
10999 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
11001 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
11002 + * or visit www.oracle.com if you need additional information or have any
11003 + * questions.
11004 + */
11006 +package sun.nio.ch;
11008 +import java.nio.channels.*;
11009 +import java.nio.channels.spi.AsynchronousChannelProvider;
11010 +import java.util.concurrent.ExecutorService;
11011 +import java.util.concurrent.ThreadFactory;
11012 +import java.io.IOException;
11014 +public class SolarisAsynchronousChannelProvider
11015 + extends AsynchronousChannelProvider
11017 + private static volatile SolarisEventPort defaultEventPort;
11019 + private SolarisEventPort defaultEventPort() throws IOException {
11020 + if (defaultEventPort == null) {
11021 + synchronized (SolarisAsynchronousChannelProvider.class) {
11022 + if (defaultEventPort == null) {
11023 + defaultEventPort =
11024 + new SolarisEventPort(this, ThreadPool.getDefault()).start();
11028 + return defaultEventPort;
11031 + public SolarisAsynchronousChannelProvider() {
11034 + @Override
11035 + public AsynchronousChannelGroup openAsynchronousChannelGroup(int nThreads, ThreadFactory factory)
11036 + throws IOException
11038 + return new SolarisEventPort(this, ThreadPool.create(nThreads, factory)).start();
11041 + @Override
11042 + public AsynchronousChannelGroup openAsynchronousChannelGroup(ExecutorService executor, int initialSize)
11043 + throws IOException
11045 + return new SolarisEventPort(this, ThreadPool.wrap(executor, initialSize)).start();
11048 + private SolarisEventPort toEventPort(AsynchronousChannelGroup group)
11049 + throws IOException
11051 + if (group == null) {
11052 + return defaultEventPort();
11053 + } else {
11054 + if (!(group instanceof SolarisEventPort))
11055 + throw new IllegalChannelGroupException();
11056 + return (SolarisEventPort)group;
11060 + @Override
11061 + public AsynchronousServerSocketChannel openAsynchronousServerSocketChannel(AsynchronousChannelGroup group)
11062 + throws IOException
11064 + return new UnixAsynchronousServerSocketChannelImpl(toEventPort(group));
11067 + @Override
11068 + public AsynchronousSocketChannel openAsynchronousSocketChannel(AsynchronousChannelGroup group)
11069 + throws IOException
11071 + return new UnixAsynchronousSocketChannelImpl(toEventPort(group));
11074 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/classes/sun/nio/ch/SolarisEventPort.java jdk21u-jdk-21.0.4-ga/src/java.base/solaris/classes/sun/nio/ch/SolarisEventPort.java
11075 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/classes/sun/nio/ch/SolarisEventPort.java 1970-01-01 01:00:00.000000000 +0100
11076 +++ jdk21u-jdk-21.0.4-ga/src/java.base/solaris/classes/sun/nio/ch/SolarisEventPort.java 2024-08-17 19:13:01.459595683 +0200
11077 @@ -0,0 +1,273 @@
11079 + * Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved.
11080 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
11082 + * This code is free software; you can redistribute it and/or modify it
11083 + * under the terms of the GNU General Public License version 2 only, as
11084 + * published by the Free Software Foundation. Oracle designates this
11085 + * particular file as subject to the "Classpath" exception as provided
11086 + * by Oracle in the LICENSE file that accompanied this code.
11088 + * This code is distributed in the hope that it will be useful, but WITHOUT
11089 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11090 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11091 + * version 2 for more details (a copy is included in the LICENSE file that
11092 + * accompanied this code).
11094 + * You should have received a copy of the GNU General Public License version
11095 + * 2 along with this work; if not, write to the Free Software Foundation,
11096 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
11098 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
11099 + * or visit www.oracle.com if you need additional information or have any
11100 + * questions.
11101 + */
11103 +package sun.nio.ch;
11105 +import java.nio.channels.spi.AsynchronousChannelProvider;
11106 +import java.util.concurrent.RejectedExecutionException;
11107 +import java.io.IOException;
11108 +import jdk.internal.misc.Unsafe;
11110 +/**
11111 + * Provides an AsynchronousChannelGroup implementation based on the Solaris 10
11112 + * event port framework and also provides direct access to that framework.
11113 + */
11115 +class SolarisEventPort
11116 + extends Port
11118 + private static final Unsafe unsafe = Unsafe.getUnsafe();
11119 + private static final int addressSize = unsafe.addressSize();
11121 + private static int dependsArch(int value32, int value64) {
11122 + return (addressSize == 4) ? value32 : value64;
11125 + /*
11126 + * typedef struct port_event {
11127 + * int portev_events;
11128 + * ushort_t portev_source;
11129 + * ushort_t portev_pad;
11130 + * uintptr_t portev_object;
11131 + * void *portev_user;
11132 + * } port_event_t;
11133 + */
11134 + static final int SIZEOF_PORT_EVENT = dependsArch(16, 24);
11135 + static final int OFFSETOF_EVENTS = 0;
11136 + static final int OFFSETOF_SOURCE = 4;
11137 + static final int OFFSETOF_OBJECT = 8;
11139 + // port sources
11140 + static final short PORT_SOURCE_USER = 3;
11141 + static final short PORT_SOURCE_FD = 4;
11143 + // events (sys/poll.h)
11144 + static final int POLLIN = 0x0001;
11145 + static final int POLLOUT = 0x0004;
11147 + // file descriptor to event port.
11148 + private final int port;
11150 + // true when port is closed
11151 + private boolean closed;
11153 + SolarisEventPort(AsynchronousChannelProvider provider, ThreadPool pool)
11154 + throws IOException
11156 + super(provider, pool);
11158 + // create event port
11159 + this.port = port_create();
11162 + SolarisEventPort start() {
11163 + startThreads(new EventHandlerTask());
11164 + return this;
11167 + // releass resources
11168 + private void implClose() {
11169 + synchronized (this) {
11170 + if (closed)
11171 + return;
11172 + closed = true;
11174 + port_close(port);
11177 + private void wakeup() {
11178 + try {
11179 + port_send(port, 0);
11180 + } catch (IOException x) {
11181 + throw new AssertionError(x);
11185 + @Override
11186 + void executeOnHandlerTask(Runnable task) {
11187 + synchronized (this) {
11188 + if (closed)
11189 + throw new RejectedExecutionException();
11190 + offerTask(task);
11191 + wakeup();
11195 + @Override
11196 + void shutdownHandlerTasks() {
11197 + /*
11198 + * If no tasks are running then just release resources; otherwise
11199 + * write to the one end of the socketpair to wakeup any polling threads..
11200 + */
11201 + int nThreads = threadCount();
11202 + if (nThreads == 0) {
11203 + implClose();
11204 + } else {
11205 + // send user event to wakeup each thread
11206 + while (nThreads-- > 0) {
11207 + try {
11208 + port_send(port, 0);
11209 + } catch (IOException x) {
11210 + throw new AssertionError(x);
11216 + @Override
11217 + void startPoll(int fd, int events) {
11218 + // (re-)associate file descriptor
11219 + // no need to translate events
11220 + try {
11221 + port_associate(port, PORT_SOURCE_FD, fd, events);
11222 + } catch (IOException x) {
11223 + throw new AssertionError(); // should not happen
11227 + /*
11228 + * Task to read a single event from the port and dispatch it to the
11229 + * channel's onEvent handler.
11230 + */
11231 + private class EventHandlerTask implements Runnable {
11232 + public void run() {
11233 + Invoker.GroupAndInvokeCount myGroupAndInvokeCount =
11234 + Invoker.getGroupAndInvokeCount();
11235 + final boolean isPooledThread = (myGroupAndInvokeCount != null);
11236 + boolean replaceMe = false;
11237 + long address = unsafe.allocateMemory(SIZEOF_PORT_EVENT);
11238 + try {
11239 + for (;;) {
11240 + // reset invoke count
11241 + if (isPooledThread)
11242 + myGroupAndInvokeCount.resetInvokeCount();
11244 + // wait for I/O completion event
11245 + // A error here is fatal (thread will not be replaced)
11246 + replaceMe = false;
11247 + try {
11248 + int n;
11249 + do {
11250 + n = port_get(port, address);
11251 + } while (n == IOStatus.INTERRUPTED);
11252 + } catch (IOException x) {
11253 + x.printStackTrace();
11254 + return;
11257 + // event source
11258 + short source = unsafe.getShort(address + OFFSETOF_SOURCE);
11259 + if (source != PORT_SOURCE_FD) {
11260 + // user event is trigger to invoke task or shutdown
11261 + if (source == PORT_SOURCE_USER) {
11262 + Runnable task = pollTask();
11263 + if (task == null) {
11264 + // shutdown request
11265 + return;
11267 + // run task (may throw error/exception)
11268 + replaceMe = true;
11269 + task.run();
11271 + // ignore
11272 + continue;
11275 + // pe->portev_object is file descriptor
11276 + int fd = (int)unsafe.getAddress(address + OFFSETOF_OBJECT);
11277 + // pe->portev_events
11278 + int events = unsafe.getInt(address + OFFSETOF_EVENTS);
11280 + // lookup channel
11281 + PollableChannel ch;
11282 + fdToChannelLock.readLock().lock();
11283 + try {
11284 + ch = fdToChannel.get(fd);
11285 + } finally {
11286 + fdToChannelLock.readLock().unlock();
11289 + // notify channel
11290 + if (ch != null) {
11291 + replaceMe = true;
11292 + // no need to translate events
11293 + ch.onEvent(events, isPooledThread);
11296 + } finally {
11297 + // free per-thread resources
11298 + unsafe.freeMemory(address);
11299 + // last task to exit when shutdown release resources
11300 + int remaining = threadExit(this, replaceMe);
11301 + if (remaining == 0 && isShutdown())
11302 + implClose();
11307 + /**
11308 + * Creates an event port
11309 + */
11310 + static native int port_create() throws IOException;
11312 + /**
11313 + * Associates specific events of a given object with a port
11314 + */
11315 + static native boolean port_associate(int port, int source, long object, int events)
11316 + throws IOException;
11318 + /**
11319 + * Removes the association of an object with a port.
11320 + */
11321 + static native boolean port_dissociate(int port, int source, long object)
11322 + throws IOException;
11324 + /**
11325 + * Retrieves a single event from a port
11326 + */
11327 + static native int port_get(int port, long address) throws IOException;
11329 + /**
11330 + * Retrieves at most {@code max} events from a port. A time-out of {@code < 0} means
11331 + * never time-out.
11332 + */
11333 + static native int port_getn(int port, long address, int max, long timeout)
11334 + throws IOException;
11336 + /**
11337 + * Sends a user-defined eventto a specified port.
11338 + */
11339 + static native void port_send(int port, int events) throws IOException;
11341 + /**
11342 + * Closes a port.
11343 + */
11344 + static native void port_close(int port);
11347 + static {
11348 + IOUtil.load();
11351 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/classes/sun/nio/fs/DefaultFileSystemProvider.java jdk21u-jdk-21.0.4-ga/src/java.base/solaris/classes/sun/nio/fs/DefaultFileSystemProvider.java
11352 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/classes/sun/nio/fs/DefaultFileSystemProvider.java 1970-01-01 01:00:00.000000000 +0100
11353 +++ jdk21u-jdk-21.0.4-ga/src/java.base/solaris/classes/sun/nio/fs/DefaultFileSystemProvider.java 2024-08-17 19:13:01.459993911 +0200
11354 @@ -0,0 +1,53 @@
11356 + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
11357 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
11359 + * This code is free software; you can redistribute it and/or modify it
11360 + * under the terms of the GNU General Public License version 2 only, as
11361 + * published by the Free Software Foundation. Oracle designates this
11362 + * particular file as subject to the "Classpath" exception as provided
11363 + * by Oracle in the LICENSE file that accompanied this code.
11365 + * This code is distributed in the hope that it will be useful, but WITHOUT
11366 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11367 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11368 + * version 2 for more details (a copy is included in the LICENSE file that
11369 + * accompanied this code).
11371 + * You should have received a copy of the GNU General Public License version
11372 + * 2 along with this work; if not, write to the Free Software Foundation,
11373 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
11375 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
11376 + * or visit www.oracle.com if you need additional information or have any
11377 + * questions.
11378 + */
11380 +package sun.nio.fs;
11382 +import java.nio.file.FileSystem;
11384 +/**
11385 + * Creates this platform's default FileSystemProvider.
11386 + */
11388 +public class DefaultFileSystemProvider {
11389 + private static final SolarisFileSystemProvider INSTANCE
11390 + = new SolarisFileSystemProvider();
11392 + private DefaultFileSystemProvider() { }
11394 + /**
11395 + * Returns the platform's default file system provider.
11396 + */
11397 + public static SolarisFileSystemProvider instance() {
11398 + return INSTANCE;
11401 + /**
11402 + * Returns the platform's default file system.
11403 + */
11404 + public static FileSystem theFileSystem() {
11405 + return INSTANCE.theFileSystem();
11408 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java jdk21u-jdk-21.0.4-ga/src/java.base/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java
11409 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java 1970-01-01 01:00:00.000000000 +0100
11410 +++ jdk21u-jdk-21.0.4-ga/src/java.base/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java 2024-08-17 19:13:01.460521626 +0200
11411 @@ -0,0 +1,414 @@
11413 + * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
11414 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
11416 + * This code is free software; you can redistribute it and/or modify it
11417 + * under the terms of the GNU General Public License version 2 only, as
11418 + * published by the Free Software Foundation. Oracle designates this
11419 + * particular file as subject to the "Classpath" exception as provided
11420 + * by Oracle in the LICENSE file that accompanied this code.
11422 + * This code is distributed in the hope that it will be useful, but WITHOUT
11423 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11424 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11425 + * version 2 for more details (a copy is included in the LICENSE file that
11426 + * accompanied this code).
11428 + * You should have received a copy of the GNU General Public License version
11429 + * 2 along with this work; if not, write to the Free Software Foundation,
11430 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
11432 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
11433 + * or visit www.oracle.com if you need additional information or have any
11434 + * questions.
11435 + */
11437 +package sun.nio.fs;
11439 +import java.nio.file.*;
11440 +import java.nio.file.attribute.*;
11441 +import java.util.*;
11442 +import java.io.IOException;
11443 +import jdk.internal.misc.Unsafe;
11445 +import static sun.nio.fs.UnixConstants.*;
11446 +import static sun.nio.fs.SolarisConstants.*;
11447 +import static sun.nio.fs.SolarisNativeDispatcher.*;
11450 +/**
11451 + * Solaris implementation of AclFileAttributeView with native support for
11452 + * NFSv4 ACLs on ZFS.
11453 + */
11455 +class SolarisAclFileAttributeView
11456 + extends AbstractAclFileAttributeView
11458 + private static final Unsafe unsafe = Unsafe.getUnsafe();
11460 + // Maximum number of entries allowed in an ACL
11461 + private static final int MAX_ACL_ENTRIES = 1024;
11463 + /**
11464 + * typedef struct ace {
11465 + * uid_t a_who;
11466 + * uint32_t a_access_mask;
11467 + * uint16_t a_flags;
11468 + * uint16_t a_type;
11469 + * } ace_t;
11470 + */
11471 + private static final short SIZEOF_ACE_T = 12;
11472 + private static final short OFFSETOF_UID = 0;
11473 + private static final short OFFSETOF_MASK = 4;
11474 + private static final short OFFSETOF_FLAGS = 8;
11475 + private static final short OFFSETOF_TYPE = 10;
11477 + private final UnixPath file;
11478 + private final boolean followLinks;
11480 + SolarisAclFileAttributeView(UnixPath file, boolean followLinks) {
11481 + this.file = file;
11482 + this.followLinks = followLinks;
11485 + /**
11486 + * Permission checks to access file
11487 + */
11488 + private void checkAccess(UnixPath file,
11489 + boolean checkRead,
11490 + boolean checkWrite)
11492 + @SuppressWarnings("removal")
11493 + SecurityManager sm = System.getSecurityManager();
11494 + if (sm != null) {
11495 + if (checkRead)
11496 + file.checkRead();
11497 + if (checkWrite)
11498 + file.checkWrite();
11499 + sm.checkPermission(new RuntimePermission("accessUserInformation"));
11503 + /**
11504 + * Encode the ACL to the given buffer
11505 + */
11506 + private static void encode(List<AclEntry> acl, long address) {
11507 + long offset = address;
11508 + for (AclEntry ace: acl) {
11509 + int flags = 0;
11511 + // map UserPrincipal to uid and flags
11512 + UserPrincipal who = ace.principal();
11513 + if (!(who instanceof UnixUserPrincipals.User))
11514 + throw new ProviderMismatchException();
11515 + UnixUserPrincipals.User user = (UnixUserPrincipals.User)who;
11516 + int uid;
11517 + if (user.isSpecial()) {
11518 + uid = -1;
11519 + if (who == UnixUserPrincipals.SPECIAL_OWNER)
11520 + flags |= ACE_OWNER;
11521 + else if (who == UnixUserPrincipals.SPECIAL_GROUP)
11522 + flags |= (ACE_GROUP | ACE_IDENTIFIER_GROUP);
11523 + else if (who == UnixUserPrincipals.SPECIAL_EVERYONE)
11524 + flags |= ACE_EVERYONE;
11525 + else
11526 + throw new AssertionError("Unable to map special identifier");
11527 + } else {
11528 + if (user instanceof UnixUserPrincipals.Group) {
11529 + uid = user.gid();
11530 + flags |= ACE_IDENTIFIER_GROUP;
11531 + } else {
11532 + uid = user.uid();
11536 + // map ACE type
11537 + int type;
11538 + switch (ace.type()) {
11539 + case ALLOW:
11540 + type = ACE_ACCESS_ALLOWED_ACE_TYPE;
11541 + break;
11542 + case DENY:
11543 + type = ACE_ACCESS_DENIED_ACE_TYPE;
11544 + break;
11545 + case AUDIT:
11546 + type = ACE_SYSTEM_AUDIT_ACE_TYPE;
11547 + break;
11548 + case ALARM:
11549 + type = ACE_SYSTEM_ALARM_ACE_TYPE;
11550 + break;
11551 + default:
11552 + throw new AssertionError("Unable to map ACE type");
11555 + // map permissions
11556 + Set<AclEntryPermission> aceMask = ace.permissions();
11557 + int mask = 0;
11558 + if (aceMask.contains(AclEntryPermission.READ_DATA))
11559 + mask |= ACE_READ_DATA;
11560 + if (aceMask.contains(AclEntryPermission.WRITE_DATA))
11561 + mask |= ACE_WRITE_DATA;
11562 + if (aceMask.contains(AclEntryPermission.APPEND_DATA))
11563 + mask |= ACE_APPEND_DATA;
11564 + if (aceMask.contains(AclEntryPermission.READ_NAMED_ATTRS))
11565 + mask |= ACE_READ_NAMED_ATTRS;
11566 + if (aceMask.contains(AclEntryPermission.WRITE_NAMED_ATTRS))
11567 + mask |= ACE_WRITE_NAMED_ATTRS;
11568 + if (aceMask.contains(AclEntryPermission.EXECUTE))
11569 + mask |= ACE_EXECUTE;
11570 + if (aceMask.contains(AclEntryPermission.DELETE_CHILD))
11571 + mask |= ACE_DELETE_CHILD;
11572 + if (aceMask.contains(AclEntryPermission.READ_ATTRIBUTES))
11573 + mask |= ACE_READ_ATTRIBUTES;
11574 + if (aceMask.contains(AclEntryPermission.WRITE_ATTRIBUTES))
11575 + mask |= ACE_WRITE_ATTRIBUTES;
11576 + if (aceMask.contains(AclEntryPermission.DELETE))
11577 + mask |= ACE_DELETE;
11578 + if (aceMask.contains(AclEntryPermission.READ_ACL))
11579 + mask |= ACE_READ_ACL;
11580 + if (aceMask.contains(AclEntryPermission.WRITE_ACL))
11581 + mask |= ACE_WRITE_ACL;
11582 + if (aceMask.contains(AclEntryPermission.WRITE_OWNER))
11583 + mask |= ACE_WRITE_OWNER;
11584 + if (aceMask.contains(AclEntryPermission.SYNCHRONIZE))
11585 + mask |= ACE_SYNCHRONIZE;
11587 + // FIXME - it would be desirable to know here if the file is a
11588 + // directory or not. Solaris returns EINVAL if an ACE has a directory
11589 + // -only flag and the file is not a directory.
11590 + Set<AclEntryFlag> aceFlags = ace.flags();
11591 + if (aceFlags.contains(AclEntryFlag.FILE_INHERIT))
11592 + flags |= ACE_FILE_INHERIT_ACE;
11593 + if (aceFlags.contains(AclEntryFlag.DIRECTORY_INHERIT))
11594 + flags |= ACE_DIRECTORY_INHERIT_ACE;
11595 + if (aceFlags.contains(AclEntryFlag.NO_PROPAGATE_INHERIT))
11596 + flags |= ACE_NO_PROPAGATE_INHERIT_ACE;
11597 + if (aceFlags.contains(AclEntryFlag.INHERIT_ONLY))
11598 + flags |= ACE_INHERIT_ONLY_ACE;
11600 + unsafe.putInt(offset + OFFSETOF_UID, uid);
11601 + unsafe.putInt(offset + OFFSETOF_MASK, mask);
11602 + unsafe.putShort(offset + OFFSETOF_FLAGS, (short)flags);
11603 + unsafe.putShort(offset + OFFSETOF_TYPE, (short)type);
11605 + offset += SIZEOF_ACE_T;
11609 + /**
11610 + * Decode the buffer, returning an ACL
11611 + */
11612 + private static List<AclEntry> decode(long address, int n) {
11613 + ArrayList<AclEntry> acl = new ArrayList<>(n);
11614 + for (int i=0; i<n; i++) {
11615 + long offset = address + i*SIZEOF_ACE_T;
11617 + int uid = unsafe.getInt(offset + OFFSETOF_UID);
11618 + int mask = unsafe.getInt(offset + OFFSETOF_MASK);
11619 + int flags = (int)unsafe.getShort(offset + OFFSETOF_FLAGS);
11620 + int type = (int)unsafe.getShort(offset + OFFSETOF_TYPE);
11622 + // map uid and flags to UserPrincipal
11623 + UnixUserPrincipals.User who = null;
11624 + if ((flags & ACE_OWNER) > 0) {
11625 + who = UnixUserPrincipals.SPECIAL_OWNER;
11626 + } else if ((flags & ACE_GROUP) > 0) {
11627 + who = UnixUserPrincipals.SPECIAL_GROUP;
11628 + } else if ((flags & ACE_EVERYONE) > 0) {
11629 + who = UnixUserPrincipals.SPECIAL_EVERYONE;
11630 + } else if ((flags & ACE_IDENTIFIER_GROUP) > 0) {
11631 + who = UnixUserPrincipals.fromGid(uid);
11632 + } else {
11633 + who = UnixUserPrincipals.fromUid(uid);
11636 + AclEntryType aceType = null;
11637 + switch (type) {
11638 + case ACE_ACCESS_ALLOWED_ACE_TYPE:
11639 + aceType = AclEntryType.ALLOW;
11640 + break;
11641 + case ACE_ACCESS_DENIED_ACE_TYPE:
11642 + aceType = AclEntryType.DENY;
11643 + break;
11644 + case ACE_SYSTEM_AUDIT_ACE_TYPE:
11645 + aceType = AclEntryType.AUDIT;
11646 + break;
11647 + case ACE_SYSTEM_ALARM_ACE_TYPE:
11648 + aceType = AclEntryType.ALARM;
11649 + break;
11650 + default:
11651 + assert false;
11654 + Set<AclEntryPermission> aceMask = EnumSet.noneOf(AclEntryPermission.class);
11655 + if ((mask & ACE_READ_DATA) > 0)
11656 + aceMask.add(AclEntryPermission.READ_DATA);
11657 + if ((mask & ACE_WRITE_DATA) > 0)
11658 + aceMask.add(AclEntryPermission.WRITE_DATA);
11659 + if ((mask & ACE_APPEND_DATA ) > 0)
11660 + aceMask.add(AclEntryPermission.APPEND_DATA);
11661 + if ((mask & ACE_READ_NAMED_ATTRS) > 0)
11662 + aceMask.add(AclEntryPermission.READ_NAMED_ATTRS);
11663 + if ((mask & ACE_WRITE_NAMED_ATTRS) > 0)
11664 + aceMask.add(AclEntryPermission.WRITE_NAMED_ATTRS);
11665 + if ((mask & ACE_EXECUTE) > 0)
11666 + aceMask.add(AclEntryPermission.EXECUTE);
11667 + if ((mask & ACE_DELETE_CHILD ) > 0)
11668 + aceMask.add(AclEntryPermission.DELETE_CHILD);
11669 + if ((mask & ACE_READ_ATTRIBUTES) > 0)
11670 + aceMask.add(AclEntryPermission.READ_ATTRIBUTES);
11671 + if ((mask & ACE_WRITE_ATTRIBUTES) > 0)
11672 + aceMask.add(AclEntryPermission.WRITE_ATTRIBUTES);
11673 + if ((mask & ACE_DELETE) > 0)
11674 + aceMask.add(AclEntryPermission.DELETE);
11675 + if ((mask & ACE_READ_ACL) > 0)
11676 + aceMask.add(AclEntryPermission.READ_ACL);
11677 + if ((mask & ACE_WRITE_ACL) > 0)
11678 + aceMask.add(AclEntryPermission.WRITE_ACL);
11679 + if ((mask & ACE_WRITE_OWNER) > 0)
11680 + aceMask.add(AclEntryPermission.WRITE_OWNER);
11681 + if ((mask & ACE_SYNCHRONIZE) > 0)
11682 + aceMask.add(AclEntryPermission.SYNCHRONIZE);
11684 + Set<AclEntryFlag> aceFlags = EnumSet.noneOf(AclEntryFlag.class);
11685 + if ((flags & ACE_FILE_INHERIT_ACE) > 0)
11686 + aceFlags.add(AclEntryFlag.FILE_INHERIT);
11687 + if ((flags & ACE_DIRECTORY_INHERIT_ACE) > 0)
11688 + aceFlags.add(AclEntryFlag.DIRECTORY_INHERIT);
11689 + if ((flags & ACE_NO_PROPAGATE_INHERIT_ACE) > 0)
11690 + aceFlags.add(AclEntryFlag.NO_PROPAGATE_INHERIT);
11691 + if ((flags & ACE_INHERIT_ONLY_ACE) > 0)
11692 + aceFlags.add(AclEntryFlag.INHERIT_ONLY);
11694 + // build the ACL entry and add it to the list
11695 + AclEntry ace = AclEntry.newBuilder()
11696 + .setType(aceType)
11697 + .setPrincipal(who)
11698 + .setPermissions(aceMask).setFlags(aceFlags).build();
11699 + acl.add(ace);
11702 + return acl;
11705 + // Returns true if NFSv4 ACLs not enabled on file system
11706 + private static boolean isAclsEnabled(int fd) {
11707 + try {
11708 + long enabled = fpathconf(fd, _PC_ACL_ENABLED);
11709 + if (enabled == _ACL_ACE_ENABLED)
11710 + return true;
11711 + } catch (UnixException x) {
11713 + return false;
11716 + @Override
11717 + public List<AclEntry> getAcl()
11718 + throws IOException
11720 + // permission check
11721 + checkAccess(file, true, false);
11723 + // open file (will fail if file is a link and not following links)
11724 + int fd = -1;
11725 + try {
11726 + fd = file.openForAttributeAccess(followLinks);
11727 + } catch (UnixException x) {
11728 + x.rethrowAsIOException(file);
11730 + try {
11731 + long address = unsafe.allocateMemory(SIZEOF_ACE_T * MAX_ACL_ENTRIES);
11732 + try {
11733 + // read ACL and decode it
11734 + int n = facl(fd, ACE_GETACL, MAX_ACL_ENTRIES, address);
11735 + assert n >= 0;
11736 + return decode(address, n);
11737 + } catch (UnixException x) {
11738 + if ((x.errno() == ENOSYS) || !isAclsEnabled(fd)) {
11739 + throw new FileSystemException(file.getPathForExceptionMessage(),
11740 + null, x.getMessage() + " (file system does not support NFSv4 ACLs)");
11742 + x.rethrowAsIOException(file);
11743 + return null; // keep compiler happy
11744 + } finally {
11745 + unsafe.freeMemory(address);
11747 + } finally {
11748 + close(fd, e -> null);
11752 + @Override
11753 + public void setAcl(List<AclEntry> acl) throws IOException {
11754 + // permission check
11755 + checkAccess(file, false, true);
11757 + // open file (will fail if file is a link and not following links)
11758 + int fd = -1;
11759 + try {
11760 + fd = file.openForAttributeAccess(followLinks);
11761 + } catch (UnixException x) {
11762 + x.rethrowAsIOException(file);
11764 + try {
11765 + // SECURITY: need to copy list as can change during processing
11766 + acl = new ArrayList<AclEntry>(acl);
11767 + int n = acl.size();
11769 + long address = unsafe.allocateMemory(SIZEOF_ACE_T * n);
11770 + try {
11771 + encode(acl, address);
11772 + facl(fd, ACE_SETACL, n, address);
11773 + } catch (UnixException x) {
11774 + if ((x.errno() == ENOSYS) || !isAclsEnabled(fd)) {
11775 + throw new FileSystemException(file.getPathForExceptionMessage(),
11776 + null, x.getMessage() + " (file system does not support NFSv4 ACLs)");
11778 + if (x.errno() == EINVAL && (n < 3))
11779 + throw new IOException("ACL must contain at least 3 entries");
11780 + x.rethrowAsIOException(file);
11781 + } finally {
11782 + unsafe.freeMemory(address);
11784 + } finally {
11785 + close(fd, e -> null);
11789 + @Override
11790 + public UserPrincipal getOwner()
11791 + throws IOException
11793 + checkAccess(file, true, false);
11795 + try {
11796 + UnixFileAttributes attrs =
11797 + UnixFileAttributes.get(file, followLinks);
11798 + return UnixUserPrincipals.fromUid(attrs.uid());
11799 + } catch (UnixException x) {
11800 + x.rethrowAsIOException(file);
11801 + return null; // keep compile happy
11805 + @Override
11806 + public void setOwner(UserPrincipal owner) throws IOException {
11807 + checkAccess(file, true, false);
11809 + if (!(owner instanceof UnixUserPrincipals.User))
11810 + throw new ProviderMismatchException();
11811 + if (owner instanceof UnixUserPrincipals.Group)
11812 + throw new IOException("'owner' parameter is a group");
11813 + int uid = ((UnixUserPrincipals.User)owner).uid();
11815 + try {
11816 + if (followLinks) {
11817 + lchown(file, uid, -1);
11818 + } else {
11819 + chown(file, uid, -1);
11821 + } catch (UnixException x) {
11822 + x.rethrowAsIOException(file);
11826 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisConstants.java.template jdk21u-jdk-21.0.4-ga/src/java.base/solaris/classes/sun/nio/fs/SolarisConstants.java.template
11827 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisConstants.java.template 1970-01-01 01:00:00.000000000 +0100
11828 +++ jdk21u-jdk-21.0.4-ga/src/java.base/solaris/classes/sun/nio/fs/SolarisConstants.java.template 2024-08-17 19:13:01.460920138 +0200
11829 @@ -0,0 +1,89 @@
11831 + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
11833 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
11835 + * This code is free software; you can redistribute it and/or modify it
11836 + * under the terms of the GNU General Public License version 2 only, as
11837 + * published by the Free Software Foundation. Oracle designates this
11838 + * particular file as subject to the "Classpath" exception as provided
11839 + * by Oracle in the LICENSE file that accompanied this code.
11841 + * This code is distributed in the hope that it will be useful, but WITHOUT
11842 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11843 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11844 + * version 2 for more details (a copy is included in the LICENSE file that
11845 + * accompanied this code).
11847 + * You should have received a copy of the GNU General Public License version
11848 + * 2 along with this work; if not, write to the Free Software Foundation,
11849 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
11851 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
11852 + * or visit www.oracle.com if you need additional information or have any
11853 + * questions.
11854 + */
11856 +@@END_COPYRIGHT@@
11858 +#include <stdio.h>
11859 +#include <errno.h>
11860 +#include <unistd.h>
11861 +#include <sys/acl.h>
11862 +#include <fcntl.h>
11863 +#include <sys/stat.h>
11865 +/* On Solaris, "sun" is defined as a macro. Undefine to make package
11866 + declaration valid */
11867 +#undef sun
11869 +/* To be able to name the Java constants the same as the C constants without
11870 + having the preprocessor rewrite those identifiers, add PREFIX_ to all
11871 + identifiers matching a C constant. The PREFIX_ is filtered out in the
11872 + makefile. */
11874 +@@START_HERE@@
11876 +package sun.nio.fs;
11877 +class SolarisConstants {
11879 + private SolarisConstants() { }
11881 + static final int PREFIX_O_XATTR = O_XATTR;
11882 + static final int PREFIX__PC_XATTR_ENABLED = _PC_XATTR_ENABLED;
11883 + static final int PREFIX__PC_ACL_ENABLED = _PC_ACL_ENABLED;
11884 + static final int PREFIX__ACL_ACE_ENABLED = _ACL_ACE_ENABLED;
11885 + static final int PREFIX_ACE_GETACL = ACE_GETACL;
11886 + static final int PREFIX_ACE_SETACL = ACE_SETACL;
11887 + static final int PREFIX_ACE_ACCESS_ALLOWED_ACE_TYPE = ACE_ACCESS_ALLOWED_ACE_TYPE;
11888 + static final int PREFIX_ACE_ACCESS_DENIED_ACE_TYPE = ACE_ACCESS_DENIED_ACE_TYPE;
11889 + static final int PREFIX_ACE_SYSTEM_AUDIT_ACE_TYPE = ACE_SYSTEM_AUDIT_ACE_TYPE;
11890 + static final int PREFIX_ACE_SYSTEM_ALARM_ACE_TYPE = ACE_SYSTEM_ALARM_ACE_TYPE;
11891 + static final int PREFIX_ACE_READ_DATA = ACE_READ_DATA;
11892 + static final int PREFIX_ACE_LIST_DIRECTORY = ACE_LIST_DIRECTORY;
11893 + static final int PREFIX_ACE_WRITE_DATA = ACE_WRITE_DATA;
11894 + static final int PREFIX_ACE_ADD_FILE = ACE_ADD_FILE;
11895 + static final int PREFIX_ACE_APPEND_DATA = ACE_APPEND_DATA;
11896 + static final int PREFIX_ACE_ADD_SUBDIRECTORY = ACE_ADD_SUBDIRECTORY;
11897 + static final int PREFIX_ACE_READ_NAMED_ATTRS = ACE_READ_NAMED_ATTRS;
11898 + static final int PREFIX_ACE_WRITE_NAMED_ATTRS = ACE_WRITE_NAMED_ATTRS;
11899 + static final int PREFIX_ACE_EXECUTE = ACE_EXECUTE;
11900 + static final int PREFIX_ACE_DELETE_CHILD = ACE_DELETE_CHILD;
11901 + static final int PREFIX_ACE_READ_ATTRIBUTES = ACE_READ_ATTRIBUTES;
11902 + static final int PREFIX_ACE_WRITE_ATTRIBUTES = ACE_WRITE_ATTRIBUTES;
11903 + static final int PREFIX_ACE_DELETE = ACE_DELETE;
11904 + static final int PREFIX_ACE_READ_ACL = ACE_READ_ACL;
11905 + static final int PREFIX_ACE_WRITE_ACL = ACE_WRITE_ACL;
11906 + static final int PREFIX_ACE_WRITE_OWNER = ACE_WRITE_OWNER;
11907 + static final int PREFIX_ACE_SYNCHRONIZE = ACE_SYNCHRONIZE;
11908 + static final int PREFIX_ACE_FILE_INHERIT_ACE = ACE_FILE_INHERIT_ACE;
11909 + static final int PREFIX_ACE_DIRECTORY_INHERIT_ACE = ACE_DIRECTORY_INHERIT_ACE;
11910 + static final int PREFIX_ACE_NO_PROPAGATE_INHERIT_ACE = ACE_NO_PROPAGATE_INHERIT_ACE;
11911 + static final int PREFIX_ACE_INHERIT_ONLY_ACE = ACE_INHERIT_ONLY_ACE;
11912 + static final int PREFIX_ACE_SUCCESSFUL_ACCESS_ACE_FLAG = ACE_SUCCESSFUL_ACCESS_ACE_FLAG;
11913 + static final int PREFIX_ACE_FAILED_ACCESS_ACE_FLAG = ACE_FAILED_ACCESS_ACE_FLAG;
11914 + static final int PREFIX_ACE_IDENTIFIER_GROUP = ACE_IDENTIFIER_GROUP;
11915 + static final int PREFIX_ACE_OWNER = ACE_OWNER;
11916 + static final int PREFIX_ACE_GROUP = ACE_GROUP;
11917 + static final int PREFIX_ACE_EVERYONE = ACE_EVERYONE;
11919 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisFileStore.java jdk21u-jdk-21.0.4-ga/src/java.base/solaris/classes/sun/nio/fs/SolarisFileStore.java
11920 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisFileStore.java 1970-01-01 01:00:00.000000000 +0100
11921 +++ jdk21u-jdk-21.0.4-ga/src/java.base/solaris/classes/sun/nio/fs/SolarisFileStore.java 2024-08-17 19:13:01.461348053 +0200
11922 @@ -0,0 +1,111 @@
11924 + * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
11925 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
11927 + * This code is free software; you can redistribute it and/or modify it
11928 + * under the terms of the GNU General Public License version 2 only, as
11929 + * published by the Free Software Foundation. Oracle designates this
11930 + * particular file as subject to the "Classpath" exception as provided
11931 + * by Oracle in the LICENSE file that accompanied this code.
11933 + * This code is distributed in the hope that it will be useful, but WITHOUT
11934 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11935 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11936 + * version 2 for more details (a copy is included in the LICENSE file that
11937 + * accompanied this code).
11939 + * You should have received a copy of the GNU General Public License version
11940 + * 2 along with this work; if not, write to the Free Software Foundation,
11941 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
11943 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
11944 + * or visit www.oracle.com if you need additional information or have any
11945 + * questions.
11946 + */
11948 +package sun.nio.fs;
11950 +import java.nio.file.attribute.*;
11951 +import java.io.IOException;
11953 +import static sun.nio.fs.UnixNativeDispatcher.*;
11954 +import static sun.nio.fs.SolarisConstants.*;
11956 +/**
11957 + * Solaris implementation of FileStore
11958 + */
11960 +class SolarisFileStore
11961 + extends UnixFileStore
11963 + private final boolean xattrEnabled;
11965 + SolarisFileStore(UnixPath file) throws IOException {
11966 + super(file);
11967 + this.xattrEnabled = xattrEnabled();
11970 + SolarisFileStore(UnixFileSystem fs, UnixMountEntry entry) throws IOException {
11971 + super(fs, entry);
11972 + this.xattrEnabled = xattrEnabled();
11975 + // returns true if extended attributes enabled
11976 + private boolean xattrEnabled() {
11977 + long res = 0L;
11978 + try {
11979 + res = pathconf(file(), _PC_XATTR_ENABLED);
11980 + } catch (UnixException x) {
11981 + // ignore
11983 + return (res != 0L);
11986 + @Override
11987 + UnixMountEntry findMountEntry() throws IOException {
11988 + // On Solaris iterate over the entries in the mount table to find device
11989 + for (UnixMountEntry entry: file().getFileSystem().getMountEntries()) {
11990 + if (entry.dev() == dev()) {
11991 + return entry;
11994 + throw new IOException("Device not found in mnttab");
11997 + @Override
11998 + public boolean supportsFileAttributeView(Class<? extends FileAttributeView> type) {
11999 + if (type == AclFileAttributeView.class) {
12000 + // lookup fstypes.properties
12001 + FeatureStatus status = checkIfFeaturePresent("nfsv4acl");
12002 + switch (status) {
12003 + case PRESENT : return true;
12004 + case NOT_PRESENT : return false;
12005 + default :
12006 + // AclFileAttributeView available on ZFS
12007 + return (type().equals("zfs"));
12010 + if (type == UserDefinedFileAttributeView.class) {
12011 + // lookup fstypes.properties
12012 + FeatureStatus status = checkIfFeaturePresent("xattr");
12013 + switch (status) {
12014 + case PRESENT : return true;
12015 + case NOT_PRESENT : return false;
12016 + default :
12017 + // UserDefinedFileAttributeView available if extended
12018 + // attributes supported
12019 + return xattrEnabled;
12022 + return super.supportsFileAttributeView(type);
12025 + @Override
12026 + public boolean supportsFileAttributeView(String name) {
12027 + if (name.equals("acl"))
12028 + return supportsFileAttributeView(AclFileAttributeView.class);
12029 + if (name.equals("user"))
12030 + return supportsFileAttributeView(UserDefinedFileAttributeView.class);
12031 + return super.supportsFileAttributeView(name);
12034 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystem.java jdk21u-jdk-21.0.4-ga/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystem.java
12035 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystem.java 1970-01-01 01:00:00.000000000 +0100
12036 +++ jdk21u-jdk-21.0.4-ga/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystem.java 2024-08-17 19:13:01.461711376 +0200
12037 @@ -0,0 +1,127 @@
12039 + * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
12040 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
12042 + * This code is free software; you can redistribute it and/or modify it
12043 + * under the terms of the GNU General Public License version 2 only, as
12044 + * published by the Free Software Foundation. Oracle designates this
12045 + * particular file as subject to the "Classpath" exception as provided
12046 + * by Oracle in the LICENSE file that accompanied this code.
12048 + * This code is distributed in the hope that it will be useful, but WITHOUT
12049 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12050 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12051 + * version 2 for more details (a copy is included in the LICENSE file that
12052 + * accompanied this code).
12054 + * You should have received a copy of the GNU General Public License version
12055 + * 2 along with this work; if not, write to the Free Software Foundation,
12056 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
12058 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
12059 + * or visit www.oracle.com if you need additional information or have any
12060 + * questions.
12061 + */
12063 +package sun.nio.fs;
12065 +import java.nio.file.*;
12066 +import java.io.IOException;
12067 +import java.util.*;
12068 +import sun.security.action.GetPropertyAction;
12069 +import static sun.nio.fs.SolarisNativeDispatcher.*;
12071 +/**
12072 + * Solaris implementation of FileSystem
12073 + */
12075 +class SolarisFileSystem extends UnixFileSystem {
12076 + private final boolean hasSolaris11Features;
12078 + SolarisFileSystem(UnixFileSystemProvider provider, String dir) {
12079 + super(provider, dir);
12081 + // check os.version
12082 + String osversion = GetPropertyAction.privilegedGetProperty("os.version");
12083 + String[] vers = Util.split(osversion, '.');
12084 + assert vers.length >= 2;
12085 + int majorVersion = Integer.parseInt(vers[0]);
12086 + int minorVersion = Integer.parseInt(vers[1]);
12087 + this.hasSolaris11Features =
12088 + (majorVersion > 5 || (majorVersion == 5 && minorVersion >= 11));
12091 + @Override
12092 + boolean isSolaris() {
12093 + return true;
12096 + @Override
12097 + public WatchService newWatchService()
12098 + throws IOException
12100 + // FEN available since Solaris 11
12101 + if (hasSolaris11Features) {
12102 + return new SolarisWatchService(this);
12103 + } else {
12104 + return new PollingWatchService();
12109 + // lazy initialization of the list of supported attribute views
12110 + private static class SupportedFileFileAttributeViewsHolder {
12111 + static final Set<String> supportedFileAttributeViews =
12112 + supportedFileAttributeViews();
12113 + private static Set<String> supportedFileAttributeViews() {
12114 + Set<String> result = new HashSet<>();
12115 + result.addAll(standardFileAttributeViews());
12116 + // additional Solaris-specific views
12117 + result.add("acl");
12118 + result.add("user");
12119 + return Collections.unmodifiableSet(result);
12123 + @Override
12124 + public Set<String> supportedFileAttributeViews() {
12125 + return SupportedFileFileAttributeViewsHolder.supportedFileAttributeViews;
12128 + @Override
12129 + void copyNonPosixAttributes(int ofd, int nfd) {
12130 + SolarisUserDefinedFileAttributeView.copyExtendedAttributes(ofd, nfd);
12131 + // TDB: copy ACL from source to target
12134 + /**
12135 + * Returns object to iterate over entries in /etc/mnttab
12136 + */
12137 + @Override
12138 + Iterable<UnixMountEntry> getMountEntries() {
12139 + ArrayList<UnixMountEntry> entries = new ArrayList<>();
12140 + try {
12141 + UnixPath mnttab = new UnixPath(this, "/etc/mnttab");
12142 + long fp = fopen(mnttab, "r");
12143 + try {
12144 + for (;;) {
12145 + UnixMountEntry entry = new UnixMountEntry();
12146 + int res = getextmntent(fp, entry);
12147 + if (res < 0)
12148 + break;
12149 + entries.add(entry);
12151 + } finally {
12152 + fclose(fp);
12154 + } catch (UnixException x) {
12155 + // nothing we can do
12157 + return entries;
12160 + @Override
12161 + FileStore getFileStore(UnixMountEntry entry) throws IOException {
12162 + return new SolarisFileStore(this, entry);
12165 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java jdk21u-jdk-21.0.4-ga/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java
12166 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java 1970-01-01 01:00:00.000000000 +0100
12167 +++ jdk21u-jdk-21.0.4-ga/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java 2024-08-17 19:13:01.462080539 +0200
12168 @@ -0,0 +1,94 @@
12170 + * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
12171 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
12173 + * This code is free software; you can redistribute it and/or modify it
12174 + * under the terms of the GNU General Public License version 2 only, as
12175 + * published by the Free Software Foundation. Oracle designates this
12176 + * particular file as subject to the "Classpath" exception as provided
12177 + * by Oracle in the LICENSE file that accompanied this code.
12179 + * This code is distributed in the hope that it will be useful, but WITHOUT
12180 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12181 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12182 + * version 2 for more details (a copy is included in the LICENSE file that
12183 + * accompanied this code).
12185 + * You should have received a copy of the GNU General Public License version
12186 + * 2 along with this work; if not, write to the Free Software Foundation,
12187 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
12189 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
12190 + * or visit www.oracle.com if you need additional information or have any
12191 + * questions.
12192 + */
12194 +package sun.nio.fs;
12196 +import java.nio.file.*;
12197 +import java.nio.file.attribute.*;
12198 +import java.nio.file.spi.FileTypeDetector;
12199 +import java.io.IOException;
12200 +import jdk.internal.util.StaticProperty;
12201 +import sun.security.action.GetPropertyAction;
12203 +/**
12204 + * Solaris implementation of FileSystemProvider
12205 + */
12207 +class SolarisFileSystemProvider extends UnixFileSystemProvider {
12208 + public SolarisFileSystemProvider() {
12209 + super();
12212 + @Override
12213 + SolarisFileSystem newFileSystem(String dir) {
12214 + return new SolarisFileSystem(this, dir);
12217 + @Override
12218 + SolarisFileStore getFileStore(UnixPath path) throws IOException {
12219 + return new SolarisFileStore(path);
12223 + @Override
12224 + @SuppressWarnings("unchecked")
12225 + public <V extends FileAttributeView> V getFileAttributeView(Path obj,
12226 + Class<V> type,
12227 + LinkOption... options)
12229 + if (type == AclFileAttributeView.class) {
12230 + return (V) new SolarisAclFileAttributeView(UnixPath.toUnixPath(obj),
12231 + Util.followLinks(options));
12233 + if (type == UserDefinedFileAttributeView.class) {
12234 + return(V) new SolarisUserDefinedFileAttributeView(UnixPath.toUnixPath(obj),
12235 + Util.followLinks(options));
12237 + return super.getFileAttributeView(obj, type, options);
12240 + @Override
12241 + public DynamicFileAttributeView getFileAttributeView(Path obj,
12242 + String name,
12243 + LinkOption... options)
12245 + if (name.equals("acl"))
12246 + return new SolarisAclFileAttributeView(UnixPath.toUnixPath(obj),
12247 + Util.followLinks(options));
12248 + if (name.equals("user"))
12249 + return new SolarisUserDefinedFileAttributeView(UnixPath.toUnixPath(obj),
12250 + Util.followLinks(options));
12251 + return super.getFileAttributeView(obj, name, options);
12254 + @Override
12255 + FileTypeDetector getFileTypeDetector() {
12256 + Path userMimeTypes = Path.of(StaticProperty.userHome(), ".mime.types");
12257 + Path etcMimeTypes = Path.of("/etc/mime.types");
12259 + return chain(new MimeTypesFileTypeDetector(userMimeTypes),
12260 + new MimeTypesFileTypeDetector(etcMimeTypes));
12263 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisNativeDispatcher.java jdk21u-jdk-21.0.4-ga/src/java.base/solaris/classes/sun/nio/fs/SolarisNativeDispatcher.java
12264 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisNativeDispatcher.java 1970-01-01 01:00:00.000000000 +0100
12265 +++ jdk21u-jdk-21.0.4-ga/src/java.base/solaris/classes/sun/nio/fs/SolarisNativeDispatcher.java 2024-08-17 19:13:01.462404651 +0200
12266 @@ -0,0 +1,55 @@
12268 + * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
12269 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
12271 + * This code is free software; you can redistribute it and/or modify it
12272 + * under the terms of the GNU General Public License version 2 only, as
12273 + * published by the Free Software Foundation. Oracle designates this
12274 + * particular file as subject to the "Classpath" exception as provided
12275 + * by Oracle in the LICENSE file that accompanied this code.
12277 + * This code is distributed in the hope that it will be useful, but WITHOUT
12278 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12279 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12280 + * version 2 for more details (a copy is included in the LICENSE file that
12281 + * accompanied this code).
12283 + * You should have received a copy of the GNU General Public License version
12284 + * 2 along with this work; if not, write to the Free Software Foundation,
12285 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
12287 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
12288 + * or visit www.oracle.com if you need additional information or have any
12289 + * questions.
12290 + */
12292 +package sun.nio.fs;
12294 +/**
12295 + * Solaris specific system calls.
12296 + */
12298 +class SolarisNativeDispatcher extends UnixNativeDispatcher {
12299 + private SolarisNativeDispatcher() { }
12301 + /**
12302 + * int getextmntent(FILE *fp, struct extmnttab *mp, int len);
12303 + */
12304 + static native int getextmntent(long fp, UnixMountEntry entry)
12305 + throws UnixException;
12307 + /**
12308 + * int facl(int filedes, int cmd, int nentries, void aclbufp)
12309 + */
12310 + static native int facl(int fd, int cmd, int nentries, long aclbufp)
12311 + throws UnixException;
12314 + // initialize
12315 + private static native void init();
12317 + static {
12318 + jdk.internal.loader.BootLoader.loadLibrary("nio");
12319 + init();
12322 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisUserDefinedFileAttributeView.java jdk21u-jdk-21.0.4-ga/src/java.base/solaris/classes/sun/nio/fs/SolarisUserDefinedFileAttributeView.java
12323 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisUserDefinedFileAttributeView.java 1970-01-01 01:00:00.000000000 +0100
12324 +++ jdk21u-jdk-21.0.4-ga/src/java.base/solaris/classes/sun/nio/fs/SolarisUserDefinedFileAttributeView.java 2024-08-17 19:13:01.462724153 +0200
12325 @@ -0,0 +1,41 @@
12327 + * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
12328 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
12330 + * This code is free software; you can redistribute it and/or modify it
12331 + * under the terms of the GNU General Public License version 2 only, as
12332 + * published by the Free Software Foundation. Oracle designates this
12333 + * particular file as subject to the "Classpath" exception as provided
12334 + * by Oracle in the LICENSE file that accompanied this code.
12336 + * This code is distributed in the hope that it will be useful, but WITHOUT
12337 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12338 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12339 + * version 2 for more details (a copy is included in the LICENSE file that
12340 + * accompanied this code).
12342 + * You should have received a copy of the GNU General Public License version
12343 + * 2 along with this work; if not, write to the Free Software Foundation,
12344 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
12346 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
12347 + * or visit www.oracle.com if you need additional information or have any
12348 + * questions.
12349 + */
12351 +package sun.nio.fs;
12353 +class SolarisUserDefinedFileAttributeView
12354 + extends UnixUserDefinedFileAttributeView
12357 + SolarisUserDefinedFileAttributeView(UnixPath file, boolean followLinks) {
12358 + super(file, followLinks);
12361 + @Override
12362 + protected int maxNameLength() {
12363 + return 255;
12367 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisWatchService.java jdk21u-jdk-21.0.4-ga/src/java.base/solaris/classes/sun/nio/fs/SolarisWatchService.java
12368 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisWatchService.java 1970-01-01 01:00:00.000000000 +0100
12369 +++ jdk21u-jdk-21.0.4-ga/src/java.base/solaris/classes/sun/nio/fs/SolarisWatchService.java 2024-08-17 19:13:01.463450810 +0200
12370 @@ -0,0 +1,821 @@
12372 + * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
12373 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
12375 + * This code is free software; you can redistribute it and/or modify it
12376 + * under the terms of the GNU General Public License version 2 only, as
12377 + * published by the Free Software Foundation. Oracle designates this
12378 + * particular file as subject to the "Classpath" exception as provided
12379 + * by Oracle in the LICENSE file that accompanied this code.
12381 + * This code is distributed in the hope that it will be useful, but WITHOUT
12382 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12383 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12384 + * version 2 for more details (a copy is included in the LICENSE file that
12385 + * accompanied this code).
12387 + * You should have received a copy of the GNU General Public License version
12388 + * 2 along with this work; if not, write to the Free Software Foundation,
12389 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
12391 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
12392 + * or visit www.oracle.com if you need additional information or have any
12393 + * questions.
12394 + */
12396 +package sun.nio.fs;
12398 +import java.nio.file.*;
12399 +import java.util.*;
12400 +import java.io.IOException;
12401 +import jdk.internal.misc.Unsafe;
12403 +import static sun.nio.fs.UnixConstants.*;
12405 +/**
12406 + * Solaris implementation of WatchService based on file events notification
12407 + * facility.
12408 + */
12410 +class SolarisWatchService
12411 + extends AbstractWatchService
12413 + private static final Unsafe unsafe = Unsafe.getUnsafe();
12414 + private static int addressSize = unsafe.addressSize();
12416 + private static int dependsArch(int value32, int value64) {
12417 + return (addressSize == 4) ? value32 : value64;
12420 + /*
12421 + * typedef struct port_event {
12422 + * int portev_events;
12423 + * ushort_t portev_source;
12424 + * ushort_t portev_pad;
12425 + * uintptr_t portev_object;
12426 + * void *portev_user;
12427 + * } port_event_t;
12428 + */
12429 + private static final int SIZEOF_PORT_EVENT = dependsArch(16, 24);
12430 + private static final int OFFSETOF_EVENTS = 0;
12431 + private static final int OFFSETOF_SOURCE = 4;
12432 + private static final int OFFSETOF_OBJECT = 8;
12434 + /*
12435 + * typedef struct file_obj {
12436 + * timestruc_t fo_atime;
12437 + * timestruc_t fo_mtime;
12438 + * timestruc_t fo_ctime;
12439 + * uintptr_t fo_pad[3];
12440 + * char *fo_name;
12441 + * } file_obj_t;
12442 + */
12443 + private static final int SIZEOF_FILEOBJ = dependsArch(40, 80);
12444 + private static final int OFFSET_FO_NAME = dependsArch(36, 72);
12446 + // port sources
12447 + private static final short PORT_SOURCE_USER = 3;
12448 + private static final short PORT_SOURCE_FILE = 7;
12450 + // user-watchable events
12451 + private static final int FILE_MODIFIED = 0x00000002;
12452 + private static final int FILE_ATTRIB = 0x00000004;
12453 + private static final int FILE_NOFOLLOW = 0x10000000;
12455 + // exception events
12456 + private static final int FILE_DELETE = 0x00000010;
12457 + private static final int FILE_RENAME_TO = 0x00000020;
12458 + private static final int FILE_RENAME_FROM = 0x00000040;
12459 + private static final int UNMOUNTED = 0x20000000;
12460 + private static final int MOUNTEDOVER = 0x40000000;
12462 + // background thread to read change events
12463 + private final Poller poller;
12465 + SolarisWatchService(UnixFileSystem fs) throws IOException {
12466 + int port = -1;
12467 + try {
12468 + port = portCreate();
12469 + } catch (UnixException x) {
12470 + throw new IOException(x.errorString());
12473 + this.poller = new Poller(fs, this, port);
12474 + this.poller.start();
12477 + @Override
12478 + WatchKey register(Path dir,
12479 + WatchEvent.Kind<?>[] events,
12480 + WatchEvent.Modifier... modifiers)
12481 + throws IOException
12483 + // delegate to poller
12484 + return poller.register(dir, events, modifiers);
12487 + @Override
12488 + void implClose() throws IOException {
12489 + // delegate to poller
12490 + poller.close();
12493 + /**
12494 + * WatchKey implementation
12495 + */
12496 + private class SolarisWatchKey extends AbstractWatchKey
12497 + implements DirectoryNode
12499 + private final UnixFileKey fileKey;
12501 + // pointer to native file_obj object
12502 + private final long object;
12504 + // events (may be changed). set to null when watch key is invalid
12505 + private volatile Set<? extends WatchEvent.Kind<?>> events;
12507 + // map of entries in directory; created lazily; accessed only by
12508 + // poller thread.
12509 + private Map<Path,EntryNode> children = new HashMap<>();
12511 + SolarisWatchKey(SolarisWatchService watcher,
12512 + UnixPath dir,
12513 + UnixFileKey fileKey,
12514 + long object,
12515 + Set<? extends WatchEvent.Kind<?>> events)
12517 + super(dir, watcher);
12518 + this.fileKey = fileKey;
12519 + this.object = object;
12520 + this.events = events;
12523 + UnixPath getDirectory() {
12524 + return (UnixPath)watchable();
12527 + UnixFileKey getFileKey() {
12528 + return fileKey;
12531 + @Override
12532 + public long object() {
12533 + return object;
12536 + void invalidate() {
12537 + events = null;
12540 + Set<? extends WatchEvent.Kind<?>> events() {
12541 + return events;
12544 + void setEvents(Set<? extends WatchEvent.Kind<?>> events) {
12545 + this.events = events;
12548 + Map<Path,EntryNode> children() {
12549 + return children;
12552 + @Override
12553 + public boolean isValid() {
12554 + return events != null;
12557 + @Override
12558 + public void cancel() {
12559 + if (isValid()) {
12560 + // delegate to poller
12561 + poller.cancel(this);
12565 + @Override
12566 + public void addChild(Path name, EntryNode node) {
12567 + children.put(name, node);
12570 + @Override
12571 + public void removeChild(Path name) {
12572 + children.remove(name);
12575 + @Override
12576 + public EntryNode getChild(Path name) {
12577 + return children.get(name);
12581 + /**
12582 + * Background thread to read from port
12583 + */
12584 + private class Poller extends AbstractPoller {
12586 + // maximum number of events to read per call to port_getn
12587 + private static final int MAX_EVENT_COUNT = 128;
12589 + // events that map to ENTRY_DELETE
12590 + private static final int FILE_REMOVED =
12591 + (FILE_DELETE|FILE_RENAME_TO|FILE_RENAME_FROM);
12593 + // events that tell us not to re-associate the object
12594 + private static final int FILE_EXCEPTION =
12595 + (FILE_REMOVED|UNMOUNTED|MOUNTEDOVER);
12597 + // address of event buffers (used to receive events with port_getn)
12598 + private final long bufferAddress;
12600 + private final SolarisWatchService watcher;
12602 + // the I/O port
12603 + private final int port;
12605 + // maps file key (dev/inode) to WatchKey
12606 + private final Map<UnixFileKey,SolarisWatchKey> fileKey2WatchKey;
12608 + // maps file_obj object to Node
12609 + private final Map<Long,Node> object2Node;
12611 + /**
12612 + * Create a new instance
12613 + */
12614 + Poller(UnixFileSystem fs, SolarisWatchService watcher, int port) {
12615 + this.watcher = watcher;
12616 + this.port = port;
12617 + this.bufferAddress =
12618 + unsafe.allocateMemory(SIZEOF_PORT_EVENT * MAX_EVENT_COUNT);
12619 + this.fileKey2WatchKey = new HashMap<UnixFileKey,SolarisWatchKey>();
12620 + this.object2Node = new HashMap<Long,Node>();
12623 + @Override
12624 + void wakeup() throws IOException {
12625 + // write to port to wakeup polling thread
12626 + try {
12627 + portSend(port, 0);
12628 + } catch (UnixException x) {
12629 + throw new IOException(x.errorString());
12633 + @Override
12634 + Object implRegister(Path obj,
12635 + Set<? extends WatchEvent.Kind<?>> events,
12636 + WatchEvent.Modifier... modifiers)
12638 + // no modifiers supported at this time
12639 + if (modifiers.length > 0) {
12640 + for (WatchEvent.Modifier modifier: modifiers) {
12641 + if (modifier == null)
12642 + return new NullPointerException();
12643 + if (!ExtendedOptions.SENSITIVITY_HIGH.matches(modifier) &&
12644 + !ExtendedOptions.SENSITIVITY_MEDIUM.matches(modifier) &&
12645 + !ExtendedOptions.SENSITIVITY_LOW.matches(modifier)) {
12646 + return new UnsupportedOperationException("Modifier not supported");
12651 + UnixPath dir = (UnixPath)obj;
12653 + // check file is directory
12654 + UnixFileAttributes attrs = null;
12655 + try {
12656 + attrs = UnixFileAttributes.get(dir, true);
12657 + } catch (UnixException x) {
12658 + return x.asIOException(dir);
12660 + if (!attrs.isDirectory()) {
12661 + return new NotDirectoryException(dir.getPathForExceptionMessage());
12664 + // if already registered then update the events and return existing key
12665 + UnixFileKey fileKey = attrs.fileKey();
12666 + SolarisWatchKey watchKey = fileKey2WatchKey.get(fileKey);
12667 + if (watchKey != null) {
12668 + try {
12669 + updateEvents(watchKey, events);
12670 + } catch (UnixException x) {
12671 + return x.asIOException(dir);
12673 + return watchKey;
12676 + // register directory
12677 + long object = 0L;
12678 + try {
12679 + object = registerImpl(dir, (FILE_MODIFIED | FILE_ATTRIB));
12680 + } catch (UnixException x) {
12681 + return x.asIOException(dir);
12684 + // create watch key and insert it into maps
12685 + watchKey = new SolarisWatchKey(watcher, dir, fileKey, object, events);
12686 + object2Node.put(object, watchKey);
12687 + fileKey2WatchKey.put(fileKey, watchKey);
12689 + // register all entries in directory
12690 + registerChildren(dir, watchKey, false, false);
12692 + return watchKey;
12695 + // release resources for single entry
12696 + void releaseChild(EntryNode node) {
12697 + long object = node.object();
12698 + if (object != 0L) {
12699 + object2Node.remove(object);
12700 + releaseObject(object, true);
12701 + node.setObject(0L);
12705 + // release resources for entries in directory
12706 + void releaseChildren(SolarisWatchKey key) {
12707 + for (EntryNode node: key.children().values()) {
12708 + releaseChild(node);
12712 + // cancel single key
12713 + @Override
12714 + void implCancelKey(WatchKey obj) {
12715 + SolarisWatchKey key = (SolarisWatchKey)obj;
12716 + if (key.isValid()) {
12717 + fileKey2WatchKey.remove(key.getFileKey());
12719 + // release resources for entries
12720 + releaseChildren(key);
12722 + // release resources for directory
12723 + long object = key.object();
12724 + object2Node.remove(object);
12725 + releaseObject(object, true);
12727 + // and finally invalidate the key
12728 + key.invalidate();
12732 + // close watch service
12733 + @Override
12734 + void implCloseAll() {
12735 + // release all native resources
12736 + for (Long object: object2Node.keySet()) {
12737 + releaseObject(object, true);
12740 + // invalidate all keys
12741 + for (Map.Entry<UnixFileKey,SolarisWatchKey> entry: fileKey2WatchKey.entrySet()) {
12742 + entry.getValue().invalidate();
12745 + // clean-up
12746 + object2Node.clear();
12747 + fileKey2WatchKey.clear();
12749 + // free global resources
12750 + unsafe.freeMemory(bufferAddress);
12751 + UnixNativeDispatcher.close(port, e -> null);
12754 + /**
12755 + * Poller main loop. Blocks on port_getn waiting for events and then
12756 + * processes them.
12757 + */
12758 + @Override
12759 + public void run() {
12760 + try {
12761 + for (;;) {
12762 + int n = portGetn(port, bufferAddress, MAX_EVENT_COUNT);
12763 + assert n > 0;
12765 + long address = bufferAddress;
12766 + for (int i=0; i<n; i++) {
12767 + boolean shutdown = processEvent(address);
12768 + if (shutdown)
12769 + return;
12770 + address += SIZEOF_PORT_EVENT;
12773 + } catch (UnixException x) {
12774 + x.printStackTrace();
12778 + /**
12779 + * Process a single port_event
12781 + * Returns true if poller thread is requested to shutdown.
12782 + */
12783 + boolean processEvent(long address) {
12784 + // pe->portev_source
12785 + short source = unsafe.getShort(address + OFFSETOF_SOURCE);
12786 + // pe->portev_object
12787 + long object = unsafe.getAddress(address + OFFSETOF_OBJECT);
12788 + // pe->portev_events
12789 + int events = unsafe.getInt(address + OFFSETOF_EVENTS);
12791 + // user event is trigger to process pending requests
12792 + if (source != PORT_SOURCE_FILE) {
12793 + if (source == PORT_SOURCE_USER) {
12794 + // process any pending requests
12795 + boolean shutdown = processRequests();
12796 + if (shutdown)
12797 + return true;
12799 + return false;
12802 + // lookup object to get Node
12803 + Node node = object2Node.get(object);
12804 + if (node == null) {
12805 + // should not happen
12806 + return false;
12809 + // As a workaround for 6642290 and 6636438/6636412 we don't use
12810 + // FILE_EXCEPTION events to tell use not to register the file.
12811 + // boolean reregister = (events & FILE_EXCEPTION) == 0;
12812 + boolean reregister = true;
12814 + // If node is EntryNode then event relates to entry in directory
12815 + // If node is a SolarisWatchKey (DirectoryNode) then event relates
12816 + // to a watched directory.
12817 + boolean isDirectory = (node instanceof SolarisWatchKey);
12818 + if (isDirectory) {
12819 + processDirectoryEvents((SolarisWatchKey)node, events);
12820 + } else {
12821 + boolean ignore = processEntryEvents((EntryNode)node, events);
12822 + if (ignore)
12823 + reregister = false;
12826 + // need to re-associate to get further events
12827 + if (reregister) {
12828 + try {
12829 + events = FILE_MODIFIED | FILE_ATTRIB;
12830 + if (!isDirectory) events |= FILE_NOFOLLOW;
12831 + portAssociate(port,
12832 + PORT_SOURCE_FILE,
12833 + object,
12834 + events);
12835 + } catch (UnixException x) {
12836 + // unable to re-register
12837 + reregister = false;
12841 + // object is not re-registered so release resources. If
12842 + // object is a watched directory then signal key
12843 + if (!reregister) {
12844 + // release resources
12845 + object2Node.remove(object);
12846 + releaseObject(object, false);
12848 + // if watch key then signal it
12849 + if (isDirectory) {
12850 + SolarisWatchKey key = (SolarisWatchKey)node;
12851 + fileKey2WatchKey.remove( key.getFileKey() );
12852 + key.invalidate();
12853 + key.signal();
12854 + } else {
12855 + // if entry then remove it from parent
12856 + EntryNode entry = (EntryNode)node;
12857 + SolarisWatchKey key = (SolarisWatchKey)entry.parent();
12858 + key.removeChild(entry.name());
12862 + return false;
12865 + /**
12866 + * Process directory events. If directory is modified then re-scan
12867 + * directory to register any new entries
12868 + */
12869 + void processDirectoryEvents(SolarisWatchKey key, int mask) {
12870 + if ((mask & (FILE_MODIFIED | FILE_ATTRIB)) != 0) {
12871 + registerChildren(key.getDirectory(), key,
12872 + key.events().contains(StandardWatchEventKinds.ENTRY_CREATE),
12873 + key.events().contains(StandardWatchEventKinds.ENTRY_DELETE));
12877 + /**
12878 + * Process events for entries in registered directories. Returns {@code
12879 + * true} if events are ignored because the watch key has been cancelled.
12880 + */
12881 + boolean processEntryEvents(EntryNode node, int mask) {
12882 + SolarisWatchKey key = (SolarisWatchKey)node.parent();
12883 + Set<? extends WatchEvent.Kind<?>> events = key.events();
12884 + if (events == null) {
12885 + // key has been cancelled so ignore event
12886 + return true;
12889 + // entry modified
12890 + if (((mask & (FILE_MODIFIED | FILE_ATTRIB)) != 0) &&
12891 + events.contains(StandardWatchEventKinds.ENTRY_MODIFY))
12893 + key.signalEvent(StandardWatchEventKinds.ENTRY_MODIFY, node.name());
12897 + return false;
12900 + /**
12901 + * Registers all entries in the given directory
12903 + * The {@code sendCreateEvents} and {@code sendDeleteEvents} parameters
12904 + * indicates if ENTRY_CREATE and ENTRY_DELETE events should be queued
12905 + * when new entries are found. When initially registering a directory
12906 + * they will always be false. When re-scanning a directory then it
12907 + * depends on if the events are enabled or not.
12908 + */
12909 + void registerChildren(UnixPath dir,
12910 + SolarisWatchKey parent,
12911 + boolean sendCreateEvents,
12912 + boolean sendDeleteEvents)
12914 + boolean isModifyEnabled =
12915 + parent.events().contains(StandardWatchEventKinds.ENTRY_MODIFY) ;
12917 + // reset visited flag on entries so that we can detect file deletes
12918 + for (EntryNode node: parent.children().values()) {
12919 + node.setVisited(false);
12922 + try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
12923 + for (Path entry: stream) {
12924 + Path name = entry.getFileName();
12926 + // skip entry if already registered
12927 + EntryNode node = parent.getChild(name);
12928 + if (node != null) {
12929 + node.setVisited(true);
12930 + continue;
12933 + // new entry found
12935 + long object = 0L;
12936 + int errno = 0;
12937 + boolean addNode = false;
12939 + // if ENTRY_MODIFY enabled then we register the entry for events
12940 + if (isModifyEnabled) {
12941 + try {
12942 + UnixPath path = (UnixPath)entry;
12943 + int events = (FILE_NOFOLLOW | FILE_MODIFIED | FILE_ATTRIB);
12944 + object = registerImpl(path, events);
12945 + addNode = true;
12946 + } catch (UnixException x) {
12947 + errno = x.errno();
12949 + } else {
12950 + addNode = true;
12953 + if (addNode) {
12954 + // create node
12955 + node = new EntryNode(object, (UnixPath)entry.getFileName(), parent);
12956 + node.setVisited(true);
12957 + // tell the parent about it
12958 + parent.addChild(entry.getFileName(), node);
12959 + if (object != 0L)
12960 + object2Node.put(object, node);
12963 + // send ENTRY_CREATE event for the new file
12964 + // send ENTRY_DELETE event for files that were deleted immediately
12965 + boolean deleted = (errno == ENOENT);
12966 + if (sendCreateEvents && (addNode || deleted))
12967 + parent.signalEvent(StandardWatchEventKinds.ENTRY_CREATE, name);
12968 + if (sendDeleteEvents && deleted)
12969 + parent.signalEvent(StandardWatchEventKinds.ENTRY_DELETE, name);
12972 + } catch (DirectoryIteratorException | IOException x) {
12973 + // queue OVERFLOW event so that user knows to re-scan directory
12974 + parent.signalEvent(StandardWatchEventKinds.OVERFLOW, null);
12975 + return;
12978 + // clean-up and send ENTRY_DELETE events for any entries that were
12979 + // not found
12980 + Iterator<Map.Entry<Path,EntryNode>> iterator =
12981 + parent.children().entrySet().iterator();
12982 + while (iterator.hasNext()) {
12983 + Map.Entry<Path,EntryNode> entry = iterator.next();
12984 + EntryNode node = entry.getValue();
12985 + if (!node.isVisited()) {
12986 + long object = node.object();
12987 + if (object != 0L) {
12988 + object2Node.remove(object);
12989 + releaseObject(object, true);
12991 + if (sendDeleteEvents)
12992 + parent.signalEvent(StandardWatchEventKinds.ENTRY_DELETE, node.name());
12993 + iterator.remove();
12998 + /**
12999 + * Update watch key's events. If ENTRY_MODIFY changes to be enabled
13000 + * then register each file in the directory; If ENTRY_MODIFY changed to
13001 + * be disabled then unregister each file.
13002 + */
13003 + void updateEvents(SolarisWatchKey key, Set<? extends WatchEvent.Kind<?>> events)
13004 + throws UnixException
13007 + // update events, remembering if ENTRY_MODIFY was previously
13008 + // enabled or disabled.
13009 + boolean oldModifyEnabled = key.events()
13010 + .contains(StandardWatchEventKinds.ENTRY_MODIFY);
13011 + key.setEvents(events);
13013 + // check if ENTRY_MODIFY has changed
13014 + boolean newModifyEnabled = events
13015 + .contains(StandardWatchEventKinds.ENTRY_MODIFY);
13016 + if (newModifyEnabled != oldModifyEnabled) {
13017 + UnixException ex = null;
13018 + for (EntryNode node: key.children().values()) {
13019 + if (newModifyEnabled) {
13020 + // register
13021 + UnixPath path = key.getDirectory().resolve(node.name());
13022 + int ev = (FILE_NOFOLLOW | FILE_MODIFIED | FILE_ATTRIB);
13023 + try {
13024 + long object = registerImpl(path, ev);
13025 + object2Node.put(object, node);
13026 + node.setObject(object);
13027 + } catch (UnixException x) {
13028 + // if file has been deleted then it will be detected
13029 + // as a FILE_MODIFIED event on the directory
13030 + if (x.errno() != ENOENT) {
13031 + ex = x;
13032 + break;
13035 + } else {
13036 + // unregister
13037 + releaseChild(node);
13041 + // an error occurred
13042 + if (ex != null) {
13043 + releaseChildren(key);
13044 + throw ex;
13049 + /**
13050 + * Calls port_associate to register the given path.
13051 + * Returns pointer to fileobj structure that is allocated for
13052 + * the registration.
13053 + */
13054 + long registerImpl(UnixPath dir, int events)
13055 + throws UnixException
13057 + // allocate memory for the path (file_obj->fo_name field)
13058 + byte[] path = dir.getByteArrayForSysCalls();
13059 + int len = path.length;
13060 + long name = unsafe.allocateMemory(len+1);
13061 + unsafe.copyMemory(path, Unsafe.ARRAY_BYTE_BASE_OFFSET, null,
13062 + name, (long)len);
13063 + unsafe.putByte(name + len, (byte)0);
13065 + // allocate memory for filedatanode structure - this is the object
13066 + // to port_associate
13067 + long object = unsafe.allocateMemory(SIZEOF_FILEOBJ);
13068 + unsafe.setMemory(null, object, SIZEOF_FILEOBJ, (byte)0);
13069 + unsafe.putAddress(object + OFFSET_FO_NAME, name);
13071 + // associate the object with the port
13072 + try {
13073 + portAssociate(port,
13074 + PORT_SOURCE_FILE,
13075 + object,
13076 + events);
13077 + } catch (UnixException x) {
13078 + // debugging
13079 + if (x.errno() == EAGAIN) {
13080 + System.err.println("The maximum number of objects associated "+
13081 + "with the port has been reached");
13084 + unsafe.freeMemory(name);
13085 + unsafe.freeMemory(object);
13086 + throw x;
13088 + return object;
13091 + /**
13092 + * Frees all resources for an file_obj object; optionally remove
13093 + * association from port
13094 + */
13095 + void releaseObject(long object, boolean dissociate) {
13096 + // remove association
13097 + if (dissociate) {
13098 + try {
13099 + portDissociate(port, PORT_SOURCE_FILE, object);
13100 + } catch (UnixException x) {
13101 + // ignore
13105 + // free native memory
13106 + long name = unsafe.getAddress(object + OFFSET_FO_NAME);
13107 + unsafe.freeMemory(name);
13108 + unsafe.freeMemory(object);
13112 + /**
13113 + * A node with native (file_obj) resources
13114 + */
13115 + private static interface Node {
13116 + long object();
13119 + /**
13120 + * A directory node with a map of the entries in the directory
13121 + */
13122 + private static interface DirectoryNode extends Node {
13123 + void addChild(Path name, EntryNode node);
13124 + void removeChild(Path name);
13125 + EntryNode getChild(Path name);
13128 + /**
13129 + * An implementation of a node that is an entry in a directory.
13130 + */
13131 + private static class EntryNode implements Node {
13132 + private long object;
13133 + private final UnixPath name;
13134 + private final DirectoryNode parent;
13135 + private boolean visited;
13137 + EntryNode(long object, UnixPath name, DirectoryNode parent) {
13138 + this.object = object;
13139 + this.name = name;
13140 + this.parent = parent;
13143 + @Override
13144 + public long object() {
13145 + return object;
13148 + void setObject(long ptr) {
13149 + this.object = ptr;
13152 + UnixPath name() {
13153 + return name;
13156 + DirectoryNode parent() {
13157 + return parent;
13160 + boolean isVisited() {
13161 + return visited;
13164 + void setVisited(boolean v) {
13165 + this.visited = v;
13169 + // -- native methods --
13171 + private static native void init();
13173 + private static native int portCreate() throws UnixException;
13175 + private static native void portAssociate(int port, int source, long object, int events)
13176 + throws UnixException;
13178 + private static native void portDissociate(int port, int source, long object)
13179 + throws UnixException;
13181 + private static native void portSend(int port, int events)
13182 + throws UnixException;
13184 + private static native int portGetn(int port, long address, int max)
13185 + throws UnixException;
13187 + static {
13188 + jdk.internal.loader.BootLoader.loadLibrary("nio");
13189 + init();
13192 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/native/libjava/ProcessHandleImpl_solaris.c jdk21u-jdk-21.0.4-ga/src/java.base/solaris/native/libjava/ProcessHandleImpl_solaris.c
13193 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/native/libjava/ProcessHandleImpl_solaris.c 1970-01-01 01:00:00.000000000 +0100
13194 +++ jdk21u-jdk-21.0.4-ga/src/java.base/solaris/native/libjava/ProcessHandleImpl_solaris.c 2024-08-17 19:13:01.463877782 +0200
13195 @@ -0,0 +1,51 @@
13197 + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
13198 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
13200 + * This code is free software; you can redistribute it and/or modify it
13201 + * under the terms of the GNU General Public License version 2 only, as
13202 + * published by the Free Software Foundation. Oracle designates this
13203 + * particular file as subject to the "Classpath" exception as provided
13204 + * by Oracle in the LICENSE file that accompanied this code.
13206 + * This code is distributed in the hope that it will be useful, but WITHOUT
13207 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13208 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13209 + * version 2 for more details (a copy is included in the LICENSE file that
13210 + * accompanied this code).
13212 + * You should have received a copy of the GNU General Public License version
13213 + * 2 along with this work; if not, write to the Free Software Foundation,
13214 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
13216 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
13217 + * or visit www.oracle.com if you need additional information or have any
13218 + * questions.
13219 + */
13221 +#include "jni.h"
13223 +#include "ProcessHandleImpl_unix.h"
13225 +#include <procfs.h>
13228 + * Implementation of native ProcessHandleImpl functions for Solaris.
13229 + * See ProcessHandleImpl_unix.c for more details.
13230 + */
13232 +void os_initNative(JNIEnv *env, jclass clazz) {}
13234 +jint os_getChildren(JNIEnv *env, jlong jpid, jlongArray jarray,
13235 + jlongArray jparentArray, jlongArray jstimesArray) {
13236 + return unix_getChildren(env, jpid, jarray, jparentArray, jstimesArray);
13239 +pid_t os_getParentPidAndTimings(JNIEnv *env, pid_t pid, jlong *total, jlong *start) {
13240 + return unix_getParentPidAndTimings(env, pid, total, start);
13243 +void os_getCmdlineAndUserInfo(JNIEnv *env, jobject jinfo, pid_t pid) {
13244 + unix_getCmdlineAndUserInfo(env, jinfo, pid);
13247 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/native/libjvm_db/libjvm_db.c jdk21u-jdk-21.0.4-ga/src/java.base/solaris/native/libjvm_db/libjvm_db.c
13248 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/native/libjvm_db/libjvm_db.c 1970-01-01 01:00:00.000000000 +0100
13249 +++ jdk21u-jdk-21.0.4-ga/src/java.base/solaris/native/libjvm_db/libjvm_db.c 2024-08-17 19:13:01.465111627 +0200
13250 @@ -0,0 +1,1552 @@
13252 + * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
13253 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
13255 + * This code is free software; you can redistribute it and/or modify it
13256 + * under the terms of the GNU General Public License version 2 only, as
13257 + * published by the Free Software Foundation.
13259 + * This code is distributed in the hope that it will be useful, but WITHOUT
13260 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13261 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13262 + * version 2 for more details (a copy is included in the LICENSE file that
13263 + * accompanied this code).
13265 + * You should have received a copy of the GNU General Public License version
13266 + * 2 along with this work; if not, write to the Free Software Foundation,
13267 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
13269 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
13270 + * or visit www.oracle.com if you need additional information or have any
13271 + * questions.
13273 + */
13275 +#include <stdio.h>
13276 +#include <stdlib.h>
13277 +#include <string.h>
13278 +#include <errno.h>
13279 +#include <gelf.h>
13281 +#include "libjvm_db.h"
13282 +#include "JvmOffsets.h"
13284 +#define LIBJVM_SO "libjvm.so"
13286 +#if defined(i386) || defined(__i386) || defined(__amd64)
13287 +#ifdef COMPILER2
13288 +#define X86_COMPILER2
13289 +#endif /* COMPILER2 */
13290 +#endif /* i386 */
13292 +typedef struct {
13293 + short vf_cnt; /* number of recognized java vframes */
13294 + short bci; /* current frame method byte code index */
13295 + int line; /* current frame method source line */
13296 + uint64_t new_fp; /* fp for the next frame */
13297 + uint64_t new_pc; /* pc for the next frame */
13298 + uint64_t new_sp; /* "raw" sp for the next frame (includes extension by interpreter/adapter */
13299 + char locinf; /* indicates there is valid location info */
13300 +} Jframe_t;
13302 +int Jlookup_by_regs(jvm_agent_t* J, const prgregset_t regs, char *name,
13303 + size_t size, Jframe_t *jframe);
13305 +int main(int arg) { return arg; }
13307 +static int debug = 0;
13309 +static void failed(int err, const char * file, int line) {
13310 + if (debug) {
13311 + fprintf(stderr, "failed %d at %s:%d\n", err, file, line);
13315 +static void warn(const char * file, int line, const char * msg) {
13316 + if (debug) {
13317 + fprintf(stderr, "warning: %s at %s:%d\n", msg, file, line);
13321 +static void warn1(const char * file, int line, const char * msg, intptr_t arg1) {
13322 + if (debug) {
13323 + fprintf(stderr, "warning: ");
13324 + fprintf(stderr, msg, arg1);
13325 + fprintf(stderr, " at %s:%d\n", file, line);
13329 +#define CHECK_FAIL(err) \
13330 + if (err != PS_OK) { failed(err, __FILE__, __LINE__); goto fail; }
13331 +#define WARN(msg) warn(__FILE__, __LINE__, msg)
13332 +#define WARN1(msg, arg1) warn1(__FILE__, __LINE__, msg, arg1)
13334 +typedef struct VMStructEntry {
13335 + const char * typeName; /* The type name containing the given field (example: "Klass") */
13336 + const char * fieldName; /* The field name within the type (example: "_name") */
13337 + uint64_t address; /* Address of field; only used for static fields */
13338 + /* ("offset" can not be reused because of apparent solstudio compiler bug */
13339 + /* in generation of initializer data) */
13340 +} VMStructEntry;
13342 +/* Prototyping inlined methods */
13344 +int sprintf(char *s, const char *format, ...);
13346 +#define SZ16 sizeof(int16_t)
13347 +#define SZ32 sizeof(int32_t)
13349 +#define COMP_METHOD_SIGN '*'
13351 +#define MAX_VFRAMES_CNT 256
13353 +typedef struct vframe {
13354 + uint64_t method;
13355 + int32_t sender_decode_offset;
13356 + int32_t methodIdx;
13357 + int32_t bci;
13358 + int32_t line;
13359 +} Vframe_t;
13361 +typedef struct frame {
13362 + uintptr_t fp;
13363 + uintptr_t pc;
13364 + uintptr_t sp;
13365 + uintptr_t sender_sp; // The unextended sp of the caller
13366 +} Frame_t;
13368 +typedef struct Nmethod_t {
13369 + struct jvm_agent* J;
13370 + Jframe_t *jframe;
13372 + uint64_t nm; /* _nmethod */
13373 + uint64_t pc;
13374 + uint64_t pc_desc;
13376 + int32_t orig_pc_offset; /* _orig_pc_offset */
13377 + uint64_t instrs_beg; /* _code_offset */
13378 + uint64_t instrs_end;
13379 + uint64_t deopt_beg; /* _deoptimize_offset */
13380 + uint64_t scopes_data_beg; /* _scopes_data_begin */
13381 + int32_t scopes_data_end;
13382 + int32_t metadata_beg; /* _metadata_offset */
13383 + int32_t metadata_end;
13384 + int32_t scopes_pcs_beg; /* _scopes_pcs_offset */
13385 + int32_t scopes_pcs_end;
13387 + int vf_cnt;
13388 + Vframe_t vframes[MAX_VFRAMES_CNT];
13389 +} Nmethod_t;
13391 +struct jvm_agent {
13392 + struct ps_prochandle* P;
13394 + uint64_t nmethod_vtbl;
13395 + uint64_t CodeBlob_vtbl;
13396 + uint64_t BufferBlob_vtbl;
13397 + uint64_t RuntimeStub_vtbl;
13398 + uint64_t Method_vtbl;
13400 + uint64_t Use_Compressed_Oops_address;
13401 + uint64_t Universe_narrow_oop_base_address;
13402 + uint64_t Universe_narrow_oop_shift_address;
13403 + uint64_t CodeCache_heaps_address;
13405 + /* Volatiles */
13406 + uint8_t Use_Compressed_Oops;
13407 + uint64_t Universe_narrow_oop_base;
13408 + uint32_t Universe_narrow_oop_shift;
13409 + // Code cache heaps
13410 + int32_t Number_of_heaps;
13411 + uint64_t* Heap_low;
13412 + uint64_t* Heap_high;
13413 + uint64_t* Heap_segmap_low;
13414 + uint64_t* Heap_segmap_high;
13416 + int32_t SIZE_CodeCache_log2_segment;
13418 + uint64_t methodPtr;
13419 + uint64_t bcp;
13421 + Nmethod_t *N; /*Inlined methods support */
13422 + Frame_t prev_fr;
13423 + Frame_t curr_fr;
13426 +static int
13427 +read_string(struct ps_prochandle *P,
13428 + char *buf, /* caller's buffer */
13429 + size_t size, /* upper limit on bytes to read */
13430 + uintptr_t addr) /* address in process */
13432 + int err = PS_OK;
13433 + while (size-- > 1 && err == PS_OK) {
13434 + err = ps_pread(P, addr, buf, 1);
13435 + if (*buf == '\0') {
13436 + return PS_OK;
13438 + addr += 1;
13439 + buf += 1;
13441 + return -1;
13444 +static int read_compressed_pointer(jvm_agent_t* J, uint64_t base, uint32_t *ptr) {
13445 + int err = -1;
13446 + uint32_t ptr32;
13447 + err = ps_pread(J->P, base, &ptr32, sizeof(uint32_t));
13448 + *ptr = ptr32;
13449 + return err;
13452 +static int read_pointer(jvm_agent_t* J, uint64_t base, uint64_t* ptr) {
13453 + int err = -1;
13454 + uint32_t ptr32;
13456 + switch (DATA_MODEL) {
13457 + case PR_MODEL_LP64:
13458 + err = ps_pread(J->P, base, ptr, sizeof(uint64_t));
13459 + break;
13460 + case PR_MODEL_ILP32:
13461 + err = ps_pread(J->P, base, &ptr32, sizeof(uint32_t));
13462 + *ptr = ptr32;
13463 + break;
13466 + return err;
13469 +static int read_string_pointer(jvm_agent_t* J, uint64_t base, const char ** stringp) {
13470 + uint64_t ptr;
13471 + int err;
13472 + char buffer[1024];
13474 + *stringp = NULL;
13475 + err = read_pointer(J, base, &ptr);
13476 + CHECK_FAIL(err);
13477 + if (ptr != 0) {
13478 + err = read_string(J->P, buffer, sizeof(buffer), ptr);
13479 + CHECK_FAIL(err);
13480 + *stringp = strdup(buffer);
13482 + return PS_OK;
13484 + fail:
13485 + return err;
13488 +static int parse_vmstruct_entry(jvm_agent_t* J, uint64_t base, VMStructEntry* vmp) {
13489 + uint64_t ptr;
13490 + int err;
13492 + err = read_string_pointer(J, base + OFFSET_VMStructEntrytypeName, &vmp->typeName);
13493 + CHECK_FAIL(err);
13494 + err = read_string_pointer(J, base + OFFSET_VMStructEntryfieldName, &vmp->fieldName);
13495 + CHECK_FAIL(err);
13496 + err = read_pointer(J, base + OFFSET_VMStructEntryaddress, &vmp->address);
13497 + CHECK_FAIL(err);
13499 + return PS_OK;
13501 + fail:
13502 + if (vmp->typeName != NULL) free((void*)vmp->typeName);
13503 + if (vmp->fieldName != NULL) free((void*)vmp->fieldName);
13504 + return err;
13507 +static int parse_vmstructs(jvm_agent_t* J) {
13508 + VMStructEntry vmVar;
13509 + VMStructEntry* vmp = &vmVar;
13510 + uint64_t gHotSpotVMStructs;
13511 + psaddr_t sym_addr;
13512 + uint64_t base;
13513 + int err;
13515 + /* Clear *vmp now in case we jump to fail: */
13516 + memset(vmp, 0, sizeof(VMStructEntry));
13518 + err = ps_pglobal_lookup(J->P, LIBJVM_SO, "gHotSpotVMStructs", &sym_addr);
13519 + CHECK_FAIL(err);
13520 + err = read_pointer(J, sym_addr, &gHotSpotVMStructs);
13521 + CHECK_FAIL(err);
13522 + base = gHotSpotVMStructs;
13524 + err = PS_OK;
13525 + while (err == PS_OK) {
13526 + memset(vmp, 0, sizeof(VMStructEntry));
13527 + err = parse_vmstruct_entry(J, base, vmp);
13528 + if (err != PS_OK || vmp->typeName == NULL) {
13529 + break;
13532 + if (vmp->typeName[0] == 'C' && strcmp("CodeCache", vmp->typeName) == 0) {
13533 + /* Read _heaps field of type GrowableArray<CodeHeaps*>* */
13534 + if (strcmp("_heaps", vmp->fieldName) == 0) {
13535 + err = read_pointer(J, vmp->address, &J->CodeCache_heaps_address);
13537 + } else if (vmp->typeName[0] == 'U' && strcmp("Universe", vmp->typeName) == 0) {
13538 + if (strcmp("_narrow_oop._base", vmp->fieldName) == 0) {
13539 + J->Universe_narrow_oop_base_address = vmp->address;
13541 + if (strcmp("_narrow_oop._shift", vmp->fieldName) == 0) {
13542 + J->Universe_narrow_oop_shift_address = vmp->address;
13545 + CHECK_FAIL(err);
13547 + base += SIZE_VMStructEntry;
13548 + if (vmp->typeName != NULL) free((void*)vmp->typeName);
13549 + if (vmp->fieldName != NULL) free((void*)vmp->fieldName);
13552 + return PS_OK;
13554 + fail:
13555 + if (vmp->typeName != NULL) free((void*)vmp->typeName);
13556 + if (vmp->fieldName != NULL) free((void*)vmp->fieldName);
13557 + return -1;
13560 +static int find_symbol(jvm_agent_t* J, const char *name, uint64_t* valuep) {
13561 + psaddr_t sym_addr;
13562 + int err;
13564 + err = ps_pglobal_lookup(J->P, LIBJVM_SO, name, &sym_addr);
13565 + if (err != PS_OK) goto fail;
13566 + *valuep = sym_addr;
13567 + return PS_OK;
13569 + fail:
13570 + return err;
13573 +static int read_volatiles(jvm_agent_t* J) {
13574 + int i;
13575 + uint64_t array_data;
13576 + uint64_t code_heap_address;
13577 + int err;
13579 + err = find_symbol(J, "UseCompressedOops", &J->Use_Compressed_Oops_address);
13580 + if (err == PS_OK) {
13581 + err = ps_pread(J->P, J->Use_Compressed_Oops_address, &J->Use_Compressed_Oops, sizeof(uint8_t));
13582 + CHECK_FAIL(err);
13583 + } else {
13584 + J->Use_Compressed_Oops = 0;
13587 + err = read_pointer(J, J->Universe_narrow_oop_base_address, &J->Universe_narrow_oop_base);
13588 + CHECK_FAIL(err);
13589 + err = ps_pread(J->P, J->Universe_narrow_oop_shift_address, &J->Universe_narrow_oop_shift, sizeof(uint32_t));
13590 + CHECK_FAIL(err);
13592 + /* CodeCache_heaps_address points to GrowableArray<CodeHeaps*>, read _data field
13593 + pointing to the first entry of type CodeCache* in the array */
13594 + err = read_pointer(J, J->CodeCache_heaps_address + OFFSET_GrowableArray_CodeHeap_data, &array_data);
13595 + /* Read _len field containing the number of code heaps */
13596 + err = ps_pread(J->P, J->CodeCache_heaps_address + OFFSET_GrowableArray_CodeHeap_len,
13597 + &J->Number_of_heaps, sizeof(J->Number_of_heaps));
13599 + /* Allocate memory for heap configurations */
13600 + J->Heap_low = (uint64_t*)calloc(J->Number_of_heaps, sizeof(uint64_t));
13601 + J->Heap_high = (uint64_t*)calloc(J->Number_of_heaps, sizeof(uint64_t));
13602 + J->Heap_segmap_low = (uint64_t*)calloc(J->Number_of_heaps, sizeof(uint64_t));
13603 + J->Heap_segmap_high = (uint64_t*)calloc(J->Number_of_heaps, sizeof(uint64_t));
13605 + /* Read code heap configurations */
13606 + for (i = 0; i < J->Number_of_heaps; ++i) {
13607 + /* Read address of heap */
13608 + err = read_pointer(J, array_data, &code_heap_address);
13609 + CHECK_FAIL(err);
13611 + err = read_pointer(J, code_heap_address + OFFSET_CodeHeap_memory +
13612 + OFFSET_VirtualSpace_low, &J->Heap_low[i]);
13613 + CHECK_FAIL(err);
13614 + err = read_pointer(J, code_heap_address + OFFSET_CodeHeap_memory +
13615 + OFFSET_VirtualSpace_high, &J->Heap_high[i]);
13616 + CHECK_FAIL(err);
13617 + err = read_pointer(J, code_heap_address + OFFSET_CodeHeap_segmap +
13618 + OFFSET_VirtualSpace_low, &J->Heap_segmap_low[i]);
13619 + CHECK_FAIL(err);
13620 + err = read_pointer(J, code_heap_address + OFFSET_CodeHeap_segmap +
13621 + OFFSET_VirtualSpace_high, &J->Heap_segmap_high[i]);
13622 + CHECK_FAIL(err);
13624 + /* Increment pointer to next entry */
13625 + array_data = array_data + POINTER_SIZE;
13628 + err = ps_pread(J->P, code_heap_address + OFFSET_CodeHeap_log2_segment_size,
13629 + &J->SIZE_CodeCache_log2_segment, sizeof(J->SIZE_CodeCache_log2_segment));
13630 + CHECK_FAIL(err);
13632 + return PS_OK;
13634 + fail:
13635 + return err;
13638 +static int codeheap_contains(int heap_num, jvm_agent_t* J, uint64_t ptr) {
13639 + return (J->Heap_low[heap_num] <= ptr && ptr < J->Heap_high[heap_num]);
13642 +static int codecache_contains(jvm_agent_t* J, uint64_t ptr) {
13643 + int i;
13644 + for (i = 0; i < J->Number_of_heaps; ++i) {
13645 + if (codeheap_contains(i, J, ptr)) {
13646 + return 1;
13649 + return 0;
13652 +static uint64_t segment_for(int heap_num, jvm_agent_t* J, uint64_t p) {
13653 + return (p - J->Heap_low[heap_num]) >> J->SIZE_CodeCache_log2_segment;
13656 +static uint64_t block_at(int heap_num, jvm_agent_t* J, int i) {
13657 + return J->Heap_low[heap_num] + (i << J->SIZE_CodeCache_log2_segment);
13660 +static int find_start(jvm_agent_t* J, uint64_t ptr, uint64_t *startp) {
13661 + int err;
13662 + int i;
13664 + for (i = 0; i < J->Number_of_heaps; ++i) {
13665 + *startp = 0;
13666 + if (codeheap_contains(i, J, ptr)) {
13667 + int32_t used;
13668 + uint64_t segment = segment_for(i, J, ptr);
13669 + uint64_t block = J->Heap_segmap_low[i];
13670 + uint8_t tag;
13671 + err = ps_pread(J->P, block + segment, &tag, sizeof(tag));
13672 + CHECK_FAIL(err);
13673 + if (tag == 0xff)
13674 + return PS_OK;
13675 + while (tag > 0) {
13676 + err = ps_pread(J->P, block + segment, &tag, sizeof(tag));
13677 + CHECK_FAIL(err);
13678 + segment -= tag;
13680 + block = block_at(i, J, segment);
13681 + err = ps_pread(J->P, block + OFFSET_HeapBlockHeader_used, &used, sizeof(used));
13682 + CHECK_FAIL(err);
13683 + if (used) {
13684 + *startp = block + SIZE_HeapBlockHeader;
13687 + return PS_OK;
13690 + fail:
13691 + return -1;
13694 +static int find_jlong_constant(jvm_agent_t* J, const char *name, uint64_t* valuep) {
13695 + psaddr_t sym_addr;
13696 + int err = ps_pglobal_lookup(J->P, LIBJVM_SO, name, &sym_addr);
13697 + if (err == PS_OK) {
13698 + err = ps_pread(J->P, sym_addr, valuep, sizeof(uint64_t));
13699 + return err;
13701 + *valuep = -1;
13702 + return -1;
13705 +jvm_agent_t *Jagent_create(struct ps_prochandle *P, int vers) {
13706 + jvm_agent_t* J;
13707 + int err;
13709 + if (vers != JVM_DB_VERSION) {
13710 + errno = ENOTSUP;
13711 + return NULL;
13714 + J = (jvm_agent_t*)calloc(sizeof(struct jvm_agent), 1);
13716 + debug = getenv("LIBJVMDB_DEBUG") != NULL;
13717 + if (debug) debug = 3;
13719 + if (debug) {
13720 + fprintf(stderr, "Jagent_create: debug=%d\n", debug);
13721 +#ifdef X86_COMPILER2
13722 + fprintf(stderr, "Jagent_create: R_SP=%d, R_FP=%d, POINTER_SIZE=%d\n", R_SP, R_FP, POINTER_SIZE);
13723 +#endif /* X86_COMPILER2 */
13726 + J->P = P;
13728 + // Initialize the initial previous frame
13730 + J->prev_fr.fp = 0;
13731 + J->prev_fr.pc = 0;
13732 + J->prev_fr.sp = 0;
13733 + J->prev_fr.sender_sp = 0;
13735 + err = find_symbol(J, "__1cHnmethodG__vtbl_", &J->nmethod_vtbl);
13736 + CHECK_FAIL(err);
13737 + err = find_symbol(J, "__1cKBufferBlobG__vtbl_", &J->BufferBlob_vtbl);
13738 + if (err != PS_OK) J->BufferBlob_vtbl = 0;
13739 + err = find_symbol(J, "__1cICodeBlobG__vtbl_", &J->CodeBlob_vtbl);
13740 + CHECK_FAIL(err);
13741 + err = find_symbol(J, "__1cLRuntimeStubG__vtbl_", &J->RuntimeStub_vtbl);
13742 + CHECK_FAIL(err);
13743 + err = find_symbol(J, "__1cGMethodG__vtbl_", &J->Method_vtbl);
13744 + CHECK_FAIL(err);
13746 + err = parse_vmstructs(J);
13747 + CHECK_FAIL(err);
13748 + err = read_volatiles(J);
13749 + CHECK_FAIL(err);
13751 + return J;
13753 + fail:
13754 + Jagent_destroy(J);
13755 + return NULL;
13758 +void Jagent_destroy(jvm_agent_t *J) {
13759 + if (J != NULL) {
13760 + free(J);
13764 +static int is_method(jvm_agent_t* J, uint64_t methodPtr) {
13765 + uint64_t klass;
13766 + int err = read_pointer(J, methodPtr, &klass);
13767 + if (err != PS_OK) goto fail;
13768 + return klass == J->Method_vtbl;
13770 + fail:
13771 + return 0;
13774 +static int
13775 +name_for_methodPtr(jvm_agent_t* J, uint64_t methodPtr, char * result, size_t size)
13777 + short nameIndex;
13778 + short signatureIndex;
13779 + uint64_t constantPool;
13780 + uint64_t constMethod;
13781 + uint64_t nameSymbol;
13782 + uint64_t signatureSymbol;
13783 + uint64_t klassPtr;
13784 + uint64_t klassSymbol;
13785 + short klassSymbolLength;
13786 + short nameSymbolLength;
13787 + short signatureSymbolLength;
13788 + char * nameString = NULL;
13789 + char * klassString = NULL;
13790 + char * signatureString = NULL;
13791 + int err;
13793 + err = read_pointer(J, methodPtr + OFFSET_Method_constMethod, &constMethod);
13794 + CHECK_FAIL(err);
13795 + err = read_pointer(J, constMethod + OFFSET_ConstMethod_constants, &constantPool);
13796 + CHECK_FAIL(err);
13798 + /* To get name string */
13799 + err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_name_index, &nameIndex, 2);
13800 + CHECK_FAIL(err);
13801 + err = read_pointer(J, constantPool + nameIndex * POINTER_SIZE + SIZE_ConstantPool, &nameSymbol);
13802 + CHECK_FAIL(err);
13803 + // The symbol is a CPSlot and has lower bit set to indicate metadata
13804 + nameSymbol &= (~1); // remove metadata lsb
13805 + err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_length, &nameSymbolLength, 2);
13806 + CHECK_FAIL(err);
13807 + nameString = (char*)calloc(nameSymbolLength + 1, 1);
13808 + err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_body, nameString, nameSymbolLength);
13809 + CHECK_FAIL(err);
13811 + /* To get signature string */
13812 + err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_signature_index, &signatureIndex, 2);
13813 + CHECK_FAIL(err);
13814 + err = read_pointer(J, constantPool + signatureIndex * POINTER_SIZE + SIZE_ConstantPool, &signatureSymbol);
13815 + CHECK_FAIL(err);
13816 + signatureSymbol &= (~1); // remove metadata lsb
13817 + err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_length, &signatureSymbolLength, 2);
13818 + CHECK_FAIL(err);
13819 + signatureString = (char*)calloc(signatureSymbolLength + 1, 1);
13820 + err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_body, signatureString, signatureSymbolLength);
13821 + CHECK_FAIL(err);
13823 + /* To get klass string */
13824 + err = read_pointer(J, constantPool + OFFSET_ConstantPool_pool_holder, &klassPtr);
13825 + CHECK_FAIL(err);
13826 + err = read_pointer(J, klassPtr + OFFSET_Klass_name, &klassSymbol);
13827 + CHECK_FAIL(err);
13828 + err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_length, &klassSymbolLength, 2);
13829 + CHECK_FAIL(err);
13830 + klassString = (char*)calloc(klassSymbolLength + 1, 1);
13831 + err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_body, klassString, klassSymbolLength);
13832 + CHECK_FAIL(err);
13834 + result[0] = '\0';
13835 + if (snprintf(result, size,
13836 + "%s.%s%s",
13837 + klassString,
13838 + nameString,
13839 + signatureString) >= size) {
13840 + // truncation
13841 + goto fail;
13844 + if (nameString != NULL) free(nameString);
13845 + if (klassString != NULL) free(klassString);
13846 + if (signatureString != NULL) free(signatureString);
13848 + return PS_OK;
13850 + fail:
13851 + if (debug) {
13852 + fprintf(stderr, "name_for_methodPtr: FAIL \n\n");
13854 + if (nameString != NULL) free(nameString);
13855 + if (klassString != NULL) free(klassString);
13856 + if (signatureString != NULL) free(signatureString);
13857 + return -1;
13860 +static int nmethod_info(Nmethod_t *N)
13862 + jvm_agent_t *J = N->J;
13863 + uint64_t nm = N->nm;
13864 + int32_t err;
13866 + if (debug > 2 )
13867 + fprintf(stderr, "\t nmethod_info: BEGIN \n");
13869 + /* Instructions */
13870 + err = read_pointer(J, nm + OFFSET_CodeBlob_code_begin, &N->instrs_beg);
13871 + CHECK_FAIL(err);
13872 + err = read_pointer(J, nm + OFFSET_CodeBlob_code_end, &N->instrs_end);
13873 + CHECK_FAIL(err);
13874 + err = read_pointer(J, nm + OFFSET_nmethod_deopt_handler_begin, &N->deopt_beg);
13875 + CHECK_FAIL(err);
13876 + err = ps_pread(J->P, nm + OFFSET_nmethod_orig_pc_offset, &N->orig_pc_offset, SZ32);
13877 + CHECK_FAIL(err);
13879 + /* Metadata */
13880 + err = ps_pread(J->P, nm + OFFSET_nmethod_metadata_offset, &N->metadata_beg, SZ32);
13881 + CHECK_FAIL(err);
13882 + err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_data_begin, &N->metadata_end, SZ32);
13883 + CHECK_FAIL(err);
13885 + /* scopes_pcs */
13886 + err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_pcs_offset, &N->scopes_pcs_beg, SZ32);
13887 + CHECK_FAIL(err);
13888 + err = ps_pread(J->P, nm + OFFSET_nmethod_dependencies_offset, &N->scopes_pcs_end, SZ32);
13889 + CHECK_FAIL(err);
13891 + /* scopes_data */
13892 + err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_data_begin, &N->scopes_data_beg, POINTER_SIZE);
13893 + CHECK_FAIL(err);
13895 + if (debug > 2 ) {
13896 + N->scopes_data_end = N->scopes_pcs_beg;
13898 + fprintf(stderr, "\t nmethod_info: instrs_beg: %#x, instrs_end: %#x\n",
13899 + N->instrs_beg, N->instrs_end);
13901 + fprintf(stderr, "\t nmethod_info: deopt_beg: %#x \n",
13902 + N->deopt_beg);
13904 + fprintf(stderr, "\t nmethod_info: orig_pc_offset: %#x \n",
13905 + N->orig_pc_offset);
13907 + fprintf(stderr, "\t nmethod_info: metadata_beg: %#x, metadata_end: %#x\n",
13908 + N->metadata_beg, N->metadata_end);
13910 + fprintf(stderr, "\t nmethod_info: scopes_data_beg: %#x, scopes_data_end: %#x\n",
13911 + N->scopes_data_beg, N->scopes_data_end);
13913 + fprintf(stderr, "\t nmethod_info: scopes_pcs_beg: %#x, scopes_pcs_end: %#x\n",
13914 + N->scopes_pcs_beg, N->scopes_pcs_end);
13916 + fprintf(stderr, "\t nmethod_info: END \n\n");
13918 + return PS_OK;
13920 + fail:
13921 + return err;
13924 +static int
13925 +raw_read_int(jvm_agent_t* J, uint64_t *buffer, int32_t *val)
13927 + int shift = 0;
13928 + int value = 0;
13929 + uint8_t ch = 0;
13930 + int32_t err;
13931 + int32_t sum;
13932 + // Constants for UNSIGNED5 coding of Pack200
13933 + // see compressedStream.hpp
13934 + enum {
13935 + lg_H = 6,
13936 + H = 1<<lg_H,
13937 + BitsPerByte = 8,
13938 + L = (1<<BitsPerByte)-H,
13939 + };
13940 + int i;
13942 + err = ps_pread(J->P, (*buffer)++, &ch, sizeof(uint8_t));
13943 + CHECK_FAIL(err);
13944 + if (debug > 2)
13945 + fprintf(stderr, "\t\t\t raw_read_int: *buffer: %#llx, ch: %#x\n", *buffer, ch);
13947 + sum = ch;
13948 + if ( sum >= L ) {
13949 + int32_t lg_H_i = lg_H;
13950 + // Read maximum of 5 total bytes (we've already read 1).
13951 + // See CompressedReadStream::read_int_mb
13952 + for ( i = 0; i < 4; i++) {
13953 + err = ps_pread(J->P, (*buffer)++, &ch, sizeof(uint8_t));
13954 + CHECK_FAIL(err);
13955 + sum += ch << lg_H_i;
13956 + if (ch < L ) {
13957 + *val = sum;
13958 + return PS_OK;
13960 + lg_H_i += lg_H;
13963 + *val = sum;
13964 + return PS_OK;
13966 + fail:
13967 + return err;
13970 +static int
13971 +read_pair(jvm_agent_t* J, uint64_t *buffer, int32_t *bci, int32_t *line)
13973 + uint8_t next = 0;
13974 + int32_t bci_delta;
13975 + int32_t line_delta;
13976 + int32_t err;
13978 + if (debug > 2)
13979 + fprintf(stderr, "\t\t read_pair: BEGIN\n");
13981 + err = ps_pread(J->P, (*buffer)++, &next, sizeof(uint8_t));
13982 + CHECK_FAIL(err);
13984 + if (next == 0) {
13985 + if (debug > 2)
13986 + fprintf(stderr, "\t\t read_pair: END: next == 0\n");
13987 + return 1; /* stream terminated */
13989 + if (next == 0xFF) {
13990 + if (debug > 2)
13991 + fprintf(stderr, "\t\t read_pair: END: next == 0xFF\n");
13993 + /* Escape character, regular compression used */
13995 + err = raw_read_int(J, buffer, &bci_delta);
13996 + CHECK_FAIL(err);
13998 + err = raw_read_int(J, buffer, &line_delta);
13999 + CHECK_FAIL(err);
14001 + *bci += bci_delta;
14002 + *line += line_delta;
14004 + if (debug > 2) {
14005 + fprintf(stderr, "\t\t read_pair: delta = (line %d: %d)\n",
14006 + line_delta, bci_delta);
14007 + fprintf(stderr, "\t\t read_pair: unpack= (line %d: %d)\n",
14008 + *line, *bci);
14010 + } else {
14011 + /* Single byte compression used */
14012 + *bci += next >> 3;
14013 + *line += next & 0x7;
14014 + if (debug > 2) {
14015 + fprintf(stderr, "\t\t read_pair: delta = (line %d: %d)\n",
14016 + next & 0x7, next >> 3);
14017 + fprintf(stderr, "\t\t read_pair: unpack= (line %d: %d)\n",
14018 + *line, *bci);
14021 + if (debug > 2)
14022 + fprintf(stderr, "\t\t read_pair: END\n");
14023 + return PS_OK;
14025 + fail:
14026 + if (debug)
14027 + fprintf(stderr, "\t\t read_pair: FAIL\n");
14028 + return err;
14031 +static int
14032 +line_number_from_bci(jvm_agent_t* J, Vframe_t *vf)
14034 + uint64_t buffer;
14035 + uint16_t code_size;
14036 + uint64_t code_end_delta;
14037 + uint64_t constMethod;
14038 + int8_t access_flags;
14039 + int32_t best_bci = 0;
14040 + int32_t stream_bci = 0;
14041 + int32_t stream_line = 0;
14042 + int32_t err;
14044 + if (debug > 2) {
14045 + char name[256];
14046 + err = name_for_methodPtr(J, vf->method, name, 256);
14047 + CHECK_FAIL(err);
14048 + fprintf(stderr, "\t line_number_from_bci: BEGIN, method name: %s, targ bci: %d\n",
14049 + name, vf->bci);
14052 + err = read_pointer(J, vf->method + OFFSET_Method_constMethod, &constMethod);
14053 + CHECK_FAIL(err);
14055 + vf->line = 0;
14056 + err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_flags, &access_flags, sizeof(int8_t));
14057 + CHECK_FAIL(err);
14059 + if (!(access_flags & ConstMethod_has_linenumber_table)) {
14060 + if (debug > 2)
14061 + fprintf(stderr, "\t line_number_from_bci: END: !HAS_LINE_NUMBER_TABLE \n\n");
14062 + return PS_OK;
14065 + /* The line numbers are a short array of 2-tuples [start_pc, line_number].
14066 + * Not necessarily sorted and not necessarily one-to-one.
14067 + */
14069 + err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_code_size, &code_size, SZ16);
14070 + CHECK_FAIL(err);
14072 + /* inlined_table_start() */
14073 + code_end_delta = (uint64_t) (access_flags & AccessFlags_NATIVE) ? 2*POINTER_SIZE : 0;
14074 + buffer = constMethod + (uint64_t) SIZE_ConstMethod + (uint64_t) code_size + code_end_delta;
14076 + if (debug > 2) {
14077 + fprintf(stderr, "\t\t line_number_from_bci: method: %#llx, native: %d\n",
14078 + vf->method, (access_flags & AccessFlags_NATIVE));
14079 + fprintf(stderr, "\t\t line_number_from_bci: buffer: %#llx, code_size: %d\n",
14080 + buffer, (int) code_size);
14083 + while (read_pair(J, &buffer, &stream_bci, &stream_line) == 0) {
14084 + if (stream_bci == vf->bci) {
14085 + /* perfect match */
14086 + if (debug > 2)
14087 + fprintf(stderr, "\t line_number_from_bci: END: exact line: %d \n\n", vf->line);
14088 + vf->line = stream_line;
14089 + return PS_OK;
14090 + } else {
14091 + /* update best_bci/line */
14092 + if (stream_bci < vf->bci && stream_bci >= best_bci) {
14093 + best_bci = stream_bci;
14094 + vf->line = stream_line;
14095 + if (debug > 2) {
14096 + fprintf(stderr, "\t line_number_from_bci: best_bci: %d, best_line: %d\n",
14097 + best_bci, vf->line);
14102 + if (debug > 2)
14103 + fprintf(stderr, "\t line_number_from_bci: END: line: %d \n\n", vf->line);
14104 + return PS_OK;
14106 + fail:
14107 + if (debug)
14108 + fprintf(stderr, "\t line_number_from_bci: FAIL\n");
14109 + return err;
14112 +static int
14113 +get_real_pc(Nmethod_t *N, uint64_t pc_desc, uint64_t *real_pc)
14115 + int32_t pc_offset;
14116 + int32_t err;
14118 + err = ps_pread(N->J->P, pc_desc + OFFSET_PcDesc_pc_offset, &pc_offset, SZ32);
14119 + CHECK_FAIL(err);
14121 + *real_pc = N->instrs_beg + pc_offset;
14122 + if (debug > 2) {
14123 + fprintf(stderr, "\t\t get_real_pc: pc_offset: %lx, real_pc: %llx\n",
14124 + pc_offset, *real_pc);
14126 + return PS_OK;
14128 + fail:
14129 + return err;
14132 +/* Finds a PcDesc with real-pc equal to N->pc */
14133 +static int pc_desc_at(Nmethod_t *N)
14135 + uint64_t pc_diff = 999;
14136 + int32_t offs;
14137 + int32_t err;
14139 + if (debug > 2)
14140 + fprintf(stderr, "\t pc_desc_at: BEGIN\n");
14142 + N->vf_cnt = 0;
14143 + N->pc_desc = 0;
14145 + for (offs = N->scopes_pcs_beg; offs < N->scopes_pcs_end; offs += SIZE_PcDesc) {
14146 + uint64_t pd;
14147 + uint64_t best_pc_diff = 16; /* some approximation */
14148 + uint64_t real_pc = 0;
14150 + pd = N->nm + offs;
14151 + err = get_real_pc(N, pd, &real_pc);
14152 + CHECK_FAIL(err);
14154 + pc_diff = real_pc - N->pc;
14156 + /* In general, this fragment should work */
14157 + if (pc_diff == 0) {
14158 + N->pc_desc = pd;
14159 + if (debug) {
14160 + fprintf(stderr, "\t pc_desc_at: END: pc_desc: FOUND: %#lx \n\n", pd);
14162 + return PS_OK;
14164 + /* This fragment is to be able to find out an appropriate
14165 + * pc_desc entry even if pc_desc info is inaccurate.
14166 + */
14167 + if (best_pc_diff > pc_diff && pc_diff > 0) {
14168 + best_pc_diff = pc_diff;
14169 + N->pc_desc = pd;
14172 + if (debug) {
14173 + fprintf(stderr, "\t pc_desc_at: END: pc_desc NOT FOUND");
14174 + if (pc_diff < 20)
14175 + fprintf(stderr, ", best pc_diff: %d\n\n", pc_diff);
14176 + else
14177 + fprintf(stderr, "\n\n");
14179 + return PS_OK;
14181 + fail:
14182 + return err;
14185 +static int
14186 +scope_desc_at(Nmethod_t *N, int32_t decode_offset, Vframe_t *vf)
14188 + uint64_t buffer;
14189 + int32_t err;
14191 + if (debug > 2) {
14192 + fprintf(stderr, "\t\t scope_desc_at: BEGIN \n");
14195 + buffer = N->scopes_data_beg + decode_offset;
14197 + err = raw_read_int(N->J, &buffer, &vf->sender_decode_offset);
14198 + CHECK_FAIL(err);
14200 + err = raw_read_int(N->J, &buffer, &vf->methodIdx);
14201 + CHECK_FAIL(err);
14203 + err = raw_read_int(N->J, &buffer, &vf->bci);
14204 + CHECK_FAIL(err);
14206 + if (debug > 2) {
14207 + fprintf(stderr, "\t\t scope_desc_at: sender_decode_offset: %#x\n",
14208 + vf->sender_decode_offset);
14209 + fprintf(stderr, "\t\t scope_desc_at: methodIdx: %d\n", vf->methodIdx);
14210 + fprintf(stderr, "\t\t scope_desc_at: bci: %d\n", vf->bci);
14212 + fprintf(stderr, "\t\t scope_desc_at: END \n\n");
14214 + return PS_OK;
14216 + fail:
14217 + return err;
14220 +static int scopeDesc_chain(Nmethod_t *N) {
14221 + int32_t decode_offset = 0;
14222 + int32_t err;
14224 + if (debug > 2) {
14225 + fprintf(stderr, "\t scopeDesc_chain: BEGIN\n");
14228 + err = ps_pread(N->J->P, N->pc_desc + OFFSET_PcDesc_scope_decode_offset,
14229 + &decode_offset, SZ32);
14230 + CHECK_FAIL(err);
14232 + while (decode_offset > 0) {
14233 + Vframe_t *vf = &N->vframes[N->vf_cnt];
14235 + if (debug > 2) {
14236 + fprintf(stderr, "\t scopeDesc_chain: decode_offset: %#x\n", decode_offset);
14239 + err = scope_desc_at(N, decode_offset, vf);
14240 + CHECK_FAIL(err);
14242 + if (vf->methodIdx > ((N->metadata_end - N->metadata_beg) / POINTER_SIZE)) {
14243 + fprintf(stderr, "\t scopeDesc_chain: (methodIdx > metadata length) !\n");
14244 + return -1;
14246 + err = read_pointer(N->J, N->nm + N->metadata_beg + (vf->methodIdx-1)*POINTER_SIZE,
14247 + &vf->method);
14248 + CHECK_FAIL(err);
14250 + if (vf->method) {
14251 + N->vf_cnt++;
14252 + err = line_number_from_bci(N->J, vf);
14253 + CHECK_FAIL(err);
14254 + if (debug > 2) {
14255 + fprintf(stderr, "\t scopeDesc_chain: method: %#8llx, line: %d\n",
14256 + vf->method, vf->line);
14259 + decode_offset = vf->sender_decode_offset;
14261 + if (debug > 2) {
14262 + fprintf(stderr, "\t scopeDesc_chain: END \n\n");
14264 + return PS_OK;
14266 + fail:
14267 + if (debug) {
14268 + fprintf(stderr, "\t scopeDesc_chain: FAIL \n\n");
14270 + return err;
14274 +static int
14275 +name_for_nmethod(jvm_agent_t* J,
14276 + uint64_t nm,
14277 + uint64_t pc,
14278 + uint64_t method,
14279 + char *result,
14280 + size_t size,
14281 + Jframe_t *jframe
14282 +) {
14283 + Nmethod_t *N;
14284 + Vframe_t *vf;
14285 + int32_t err;
14286 + int deoptimized = 0;
14288 + if (debug) {
14289 + fprintf(stderr, "name_for_nmethod: BEGIN: nmethod: %#llx, pc: %#llx\n", nm, pc);
14291 + if (J->N == NULL) {
14292 + J->N = (Nmethod_t *) malloc(sizeof(Nmethod_t));
14294 + memset(J->N, 0, sizeof(Nmethod_t)); /* Initial stat: all values are zeros */
14295 + N = J->N;
14296 + N->J = J;
14297 + N->nm = nm;
14298 + N->pc = pc;
14299 + N->jframe = jframe;
14301 + err = nmethod_info(N);
14302 + CHECK_FAIL(err);
14303 + if (debug) {
14304 + fprintf(stderr, "name_for_nmethod: pc: %#llx, deopt_pc: %#llx\n",
14305 + pc, N->deopt_beg);
14308 + /* check for a deoptimized frame */
14309 + if ( pc == N->deopt_beg) {
14310 + uint64_t base;
14311 + if (debug) {
14312 + fprintf(stderr, "name_for_nmethod: found deoptimized frame\n");
14314 + if (J->prev_fr.sender_sp != 0) {
14315 + base = J->prev_fr.sender_sp + N->orig_pc_offset;
14316 + } else {
14317 + base = J->curr_fr.sp + N->orig_pc_offset;
14319 + err = read_pointer(J, base, &N->pc);
14320 + CHECK_FAIL(err);
14321 + if (debug) {
14322 + fprintf(stderr, "name_for_nmethod: found deoptimized frame converting pc from %#8llx to %#8llx\n",
14323 + pc, N->pc);
14325 + deoptimized = 1;
14328 + err = pc_desc_at(N);
14329 + CHECK_FAIL(err);
14331 + if (N->pc_desc > 0) {
14332 + jframe->locinf = 1;
14333 + err = scopeDesc_chain(N);
14334 + CHECK_FAIL(err);
14336 + result[0] = COMP_METHOD_SIGN;
14337 + vf = &N->vframes[0];
14338 + if (N->vf_cnt > 0) {
14339 + jframe->vf_cnt = N->vf_cnt;
14340 + jframe->bci = vf->bci;
14341 + jframe->line = vf->line;
14342 + err = name_for_methodPtr(J, N->vframes[0].method, result+1, size-1);
14343 + CHECK_FAIL(err);
14344 + } else {
14345 + err = name_for_methodPtr(J, method, result+1, size-1);
14346 + CHECK_FAIL(err);
14348 + if (deoptimized) {
14349 + strncat(result, " [deoptimized frame]; ", size - strlen(result) - 1);
14350 + } else {
14351 + strncat(result, " [compiled] ", size - strlen(result) - 1);
14353 + if (debug)
14354 + fprintf(stderr, "name_for_nmethod: END: method name: %s, vf_cnt: %d\n\n",
14355 + result, N->vf_cnt);
14356 + return PS_OK;
14358 + fail:
14359 + if (debug)
14360 + fprintf(stderr, "name_for_nmethod: FAIL \n\n");
14361 + return err;
14364 +static int
14365 +name_for_imethod(jvm_agent_t* J,
14366 + uint64_t bcp,
14367 + uint64_t method,
14368 + char *result,
14369 + size_t size,
14370 + Jframe_t *jframe
14371 +) {
14372 + uint64_t bci;
14373 + uint64_t constMethod;
14374 + Vframe_t vframe = {0};
14375 + Vframe_t *vf = &vframe;
14376 + int32_t err;
14378 + err = read_pointer(J, method + OFFSET_Method_constMethod, &constMethod);
14379 + CHECK_FAIL(err);
14381 + bci = bcp - (constMethod + (uint64_t) SIZE_ConstMethod);
14383 + if (debug)
14384 + fprintf(stderr, "\t name_for_imethod: BEGIN: method: %#llx\n", method);
14386 + err = name_for_methodPtr(J, method, result, size);
14387 + CHECK_FAIL(err);
14388 + if (debug)
14389 + fprintf(stderr, "\t name_for_imethod: method name: %s\n", result);
14391 + if (bci > 0) {
14392 + vf->method = method;
14393 + vf->bci = bci;
14394 + err = line_number_from_bci(J, vf);
14395 + CHECK_FAIL(err);
14397 + jframe->bci = vf->bci;
14398 + jframe->line = vf->line;
14399 + jframe->locinf = 1;
14401 + if (debug) {
14402 + fprintf(stderr, "\t name_for_imethod: END: bci: %d, line: %d\n\n",
14403 + vf->bci, vf->line);
14405 + return PS_OK;
14407 + fail:
14408 + if (debug)
14409 + fprintf(stderr, "\t name_for_imethod: FAIL\n");
14410 + return err;
14413 +static int
14414 +name_for_codecache(jvm_agent_t* J, uint64_t fp, uint64_t pc, char * result,
14415 + size_t size, Jframe_t *jframe, int* is_interpreted)
14417 + uint64_t start;
14418 + uint64_t vtbl;
14419 + int32_t err;
14420 + *is_interpreted = 0;
14422 + result[0] = '\0';
14424 + err = find_start(J, pc, &start);
14425 + CHECK_FAIL(err);
14427 + err = read_pointer(J, start, &vtbl);
14428 + CHECK_FAIL(err);
14430 + if (vtbl == J->nmethod_vtbl) {
14431 + uint64_t method;
14433 + err = read_pointer(J, start + OFFSET_nmethod_method, &method);
14434 + CHECK_FAIL(err);
14436 + if (debug) {
14437 + fprintf(stderr, "name_for_codecache: start: %#8llx, pc: %#8llx, method: %#8llx \n",
14438 + start, pc, method);
14440 + err = name_for_nmethod(J, start, pc, method, result, size, jframe);
14441 + CHECK_FAIL(err);
14442 + } else if (vtbl == J->BufferBlob_vtbl) {
14443 + const char * name;
14445 + err = read_string_pointer(J, start + OFFSET_CodeBlob_name, &name);
14447 + /*
14448 + * Temporary usage of string "Interpreter".
14449 + * We need some other way to distinguish "StubRoutines"
14450 + * and regular interpreted frames.
14451 + */
14452 + if (err == PS_OK && strncmp(name, "Interpreter", 11) == 0) {
14453 + *is_interpreted = 1;
14454 + if (is_method(J, J->methodPtr)) {
14455 + return name_for_imethod(J, J->bcp, J->methodPtr, result, size, jframe);
14459 + if (err == PS_OK) {
14460 + strncpy(result, name, size);
14461 + free((void*)name);
14462 + } else {
14463 + strncpy(result, "<unknown BufferBlob>", size);
14465 + /* return PS_OK; */
14466 + } else {
14467 + const char * name;
14469 + err = read_string_pointer(J, start + OFFSET_CodeBlob_name, &name);
14470 + if (err == PS_OK) {
14471 + strncpy(result, name, size);
14472 + free((void*)name);
14473 + } else {
14474 + strncpy(result, "<unknown CodeBlob>", size);
14475 + WARN1("unknown CodeBlob: vtbl = 0x%x", vtbl);
14478 + result[size-1] = '\0';
14480 +#ifdef X86_COMPILER2
14481 + if (vtbl != J->RuntimeStub_vtbl) {
14482 + uint64_t trial_pc;
14483 + int frame_size;
14484 + err = ps_pread(J->P, start + OFFSET_CodeBlob_frame_size,
14485 + &frame_size, SZ32);
14486 + CHECK_FAIL(err);
14488 + // frame_size is in words, we want bytes.
14489 + frame_size *= POINTER_SIZE; /* word => byte conversion */
14491 + /*
14492 + Because c2 doesn't use FP as a framepointer the value of sp/fp we receive
14493 + in the initial entry to a set of stack frames containing server frames
14494 + will pretty much be nonsense. We can detect that nonsense by looking to
14495 + see if the PC we received is correct if we look at the expected storage
14496 + location in relation to the FP (ie. POINTER_SIZE(FP) )
14497 + */
14499 + err = read_pointer(J, fp + POINTER_SIZE , &trial_pc);
14500 + if ( (err != PS_OK || trial_pc != pc) && frame_size > 0 ) {
14501 + // Either we couldn't even read at the "fp" or the pc didn't match
14502 + // both are sure clues that the fp is bogus. We no search the stack
14503 + // for a reasonable number of words trying to find the bogus fp
14504 + // and the current pc in adjacent words. The we will be able to
14505 + // deduce an approximation of the frame pointer and actually get
14506 + // the correct stack pointer. Which we can then unwind for the
14507 + // next frame.
14508 + int i;
14509 + uint64_t check;
14510 + uint64_t base = J->curr_fr.sp;
14511 + uint64_t prev_fp = 0;
14512 + for ( i = 0; i < frame_size * 5 ; i++, base += POINTER_SIZE ) {
14513 + err = read_pointer(J, base , &check);
14514 + CHECK_FAIL(err);
14515 + if (check == fp) {
14516 + base += POINTER_SIZE;
14517 + err = read_pointer(J, base , &check);
14518 + CHECK_FAIL(err);
14519 + if (check == pc) {
14520 + if (debug) {
14521 + fprintf(stderr, "name_for_codecache: found matching fp/pc combo at 0x%llx\n", base - POINTER_SIZE);
14523 + prev_fp = base - 2 * POINTER_SIZE;
14524 + break;
14528 + if ( prev_fp != 0 ) {
14529 + // real_sp is the sp we should have received for this frame
14530 + uint64_t real_sp = prev_fp + 2 * POINTER_SIZE;
14531 + // +POINTER_SIZE because callee owns the return address so caller's sp is +1 word
14532 + jframe->new_sp = real_sp + frame_size + POINTER_SIZE;
14533 + err = read_pointer(J, jframe->new_sp - POINTER_SIZE , &jframe->new_pc);
14534 + CHECK_FAIL(err);
14535 + err = read_pointer(J, jframe->new_sp - 2*POINTER_SIZE, &jframe->new_fp);
14536 + CHECK_FAIL(err);
14537 + return PS_OK;
14541 + /* A prototype to workaround FP absence */
14542 + /*
14543 + * frame_size can be 0 for StubRoutines (1) frame.
14544 + * In this case it should work with fp as usual.
14545 + */
14546 + if (frame_size > 0) {
14547 + jframe->new_fp = J->prev_fr.fp + frame_size;
14548 + jframe->new_sp = jframe->new_fp + 2 * POINTER_SIZE;
14549 + } else {
14550 + memset(&J->curr_fr, 0, sizeof(Frame_t));
14551 + err = read_pointer(J, fp, &jframe->new_fp);
14552 + CHECK_FAIL(err);
14554 + err = read_pointer(J, jframe->new_fp + POINTER_SIZE, &jframe->new_pc);
14555 + CHECK_FAIL(err);
14557 + if (debug) {
14558 + fprintf(stderr, "name_for_codecache: %s, frame_size=%#lx\n",
14559 + result, frame_size);
14560 + fprintf(stderr, "name_for_codecache: prev_fr.fp=%#lx, fp=%#lx\n",
14561 + J->prev_fr.fp, jframe->new_fp);
14564 +#endif /* X86_COMPILER2 */
14566 + return PS_OK;
14568 + fail:
14569 + return err;
14572 +int Jget_vframe(jvm_agent_t* J, int vframe_no,
14573 + char *name, size_t size, Jframe_t *jframe)
14575 + Nmethod_t *N = J->N;
14576 + Vframe_t *vf;
14577 + int32_t err;
14579 + if (vframe_no >= N->vf_cnt) {
14580 + (void) sprintf(name, "Wrong inlinedMethod%1d()", vframe_no);
14581 + return -1;
14583 + vf = N->vframes + vframe_no;
14584 + name[0] = COMP_METHOD_SIGN;
14585 + err = name_for_methodPtr(J, vf->method, name + 1, size);
14586 + CHECK_FAIL(err);
14588 + jframe->bci = vf->bci;
14589 + jframe->line = vf->line;
14590 + if (debug) {
14591 + fprintf(stderr, "\t Jget_vframe: method name: %s, line: %d\n",
14592 + name, vf->line);
14594 + return PS_OK;
14596 + fail:
14597 + if (debug) {
14598 + fprintf(stderr, "\t Jget_vframe: FAIL\n");
14600 + return err;
14603 +#define MAX_SYM_SIZE 256
14605 +int Jlookup_by_regs(jvm_agent_t* J, const prgregset_t regs, char *name,
14606 + size_t size, Jframe_t *jframe) {
14607 + uintptr_t fp;
14608 + uintptr_t pc;
14609 + /* arguments given to read_pointer need to be worst case sized */
14610 + uint64_t methodPtr = 0;
14611 + uint64_t sender_sp;
14612 + uint64_t bcp = 0;
14613 + int is_interpreted = 0;
14614 + int result = PS_OK;
14615 + int err = PS_OK;
14617 + if (J == NULL) {
14618 + return -1;
14621 + jframe->vf_cnt = 1;
14622 + jframe->new_fp = 0;
14623 + jframe->new_pc = 0;
14624 + jframe->line = 0;
14625 + jframe->bci = 0;
14626 + jframe->locinf = 0;
14628 + read_volatiles(J);
14629 + pc = (uintptr_t) regs[R_PC];
14630 + J->curr_fr.pc = pc;
14631 + J->curr_fr.fp = regs[R_FP];
14632 + J->curr_fr.sp = regs[R_SP];
14634 + if (debug)
14635 + fprintf(stderr, "Jlookup_by_regs: BEGINs: fp=%#lx, pc=%#lx\n", regs[R_FP], pc);
14637 +#if defined(i386) || defined(__i386) || defined(__amd64)
14639 + fp = (uintptr_t) regs[R_FP];
14640 + if (J->prev_fr.fp == 0) {
14641 +#ifdef X86_COMPILER2
14642 + /* A workaround for top java frames */
14643 + J->prev_fr.fp = (uintptr_t)(regs[R_SP] - 2 * POINTER_SIZE);
14644 +#else
14645 + J->prev_fr.fp = (uintptr_t)(regs[R_SP] - POINTER_SIZE);
14646 +#endif /* COMPILER2 */
14648 + if (debug > 2) {
14649 + printf("Jlookup_by_regs: J->prev_fr.fp = %#lx\n", J->prev_fr.fp);
14652 + if (read_pointer(J, fp + OFFSET_interpreter_frame_method, &methodPtr) != PS_OK) {
14653 + methodPtr = 0;
14655 + if (read_pointer(J, fp + OFFSET_interpreter_frame_sender_sp, &sender_sp) != PS_OK) {
14656 + sender_sp = 0;
14658 + if (read_pointer(J, fp + OFFSET_interpreter_frame_bcp_offset, &bcp) != PS_OK) {
14659 + bcp = 0;
14661 +#endif /* i386 */
14663 + J->methodPtr = methodPtr;
14664 + J->bcp = bcp;
14666 + /* On x86 with C2 JVM: native frame may have wrong regs[R_FP]
14667 + * For example: JVM_SuspendThread frame poins to the top interpreted frame.
14668 + * If we call is_method(J, methodPtr) before codecache_contains(J, pc)
14669 + * then we go over and omit both: nmethod and I2CAdapter frames.
14670 + * Note, that regs[R_PC] is always correct if frame defined correctly.
14671 + * So it is better to call codecache_contains(J, pc) from the beginning.
14672 + */
14673 +#ifndef X86_COMPILER2
14674 + if (is_method(J, J->methodPtr)) {
14675 + result = name_for_imethod(J, bcp, J->methodPtr, name, size, jframe);
14676 + /* If the methodPtr is a method then this is highly likely to be
14677 + an interpreter frame */
14678 + if (result >= 0) {
14679 + is_interpreted = 1;
14681 + } else
14682 +#endif /* ! X86_COMPILER2 */
14684 + if (codecache_contains(J, pc)) {
14685 + result = name_for_codecache(J, fp, pc, name, size, jframe, &is_interpreted);
14687 +#ifdef X86_COMPILER2
14688 + else if (is_method(J, J->methodPtr)) {
14689 + result = name_for_imethod(J, bcp, J->methodPtr, name, size, jframe);
14690 + /* If the methodPtr is a method then this is highly likely to be
14691 + an interpreter frame */
14692 + if (result >= 0) {
14693 + is_interpreted = 1;
14696 +#endif /* X86_COMPILER2 */
14697 + else {
14698 + if (debug) {
14699 + fprintf(stderr, "Jlookup_by_regs: END with -1\n\n");
14701 + result = -1;
14703 + if (!is_interpreted) {
14704 + sender_sp = 0;
14706 + J->curr_fr.sender_sp = sender_sp;
14708 +#ifdef X86_COMPILER2
14709 + if (!J->curr_fr.fp) {
14710 + J->curr_fr.fp = (jframe->new_fp) ? jframe->new_fp : (uintptr_t)regs[R_FP];
14712 + if (!jframe->new_pc && jframe->new_fp) {
14713 + // This seems dubious
14714 + read_pointer(J, jframe->new_fp + POINTER_SIZE, &jframe->new_pc);
14715 + CHECK_FAIL(err);
14716 + if (debug > 2) {
14717 + printf("Jlookup_by_regs: (update pc) jframe->new_fp: %#llx, jframe->new_pc: %#llx\n",
14718 + jframe->new_fp, jframe->new_pc);
14722 +#endif /* X86_COMPILER2 */
14723 + J->prev_fr = J->curr_fr;
14725 + if (debug)
14726 + fprintf(stderr, "Jlookup_by_regs: END\n\n");
14728 + return result;
14730 + fail:
14731 + return err;
14734 +void update_gregs(prgregset_t gregs, Jframe_t jframe) {
14735 +#ifdef X86_COMPILER2
14736 + if (debug > 0) {
14737 + fprintf(stderr, "update_gregs: before update sp = 0x%llx, fp = 0x%llx, pc = 0x%llx\n", gregs[R_SP], gregs[R_FP], gregs[R_PC]);
14739 + /*
14740 + * A workaround for java C2 frames with unconventional FP.
14741 + * may have to modify regset with new values for FP/PC/SP when needed.
14742 + */
14743 + if (jframe.new_sp) {
14744 + *((uintptr_t *) &gregs[R_SP]) = (uintptr_t) jframe.new_sp;
14745 + } else {
14746 + // *((uintptr_t *) &gregs[R_SP]) = (uintptr_t) gregs[R_FP] + 2 * POINTER_SIZE;
14749 + if (jframe.new_fp) {
14750 + *((uintptr_t *) &gregs[R_FP]) = (uintptr_t) jframe.new_fp;
14752 + if (jframe.new_pc) {
14753 + *((uintptr_t *) &gregs[R_PC]) = (uintptr_t) jframe.new_pc;
14755 + if (debug > 0) {
14756 + fprintf(stderr, "update_gregs: after update sp = 0x%llx, fp = 0x%llx, pc = 0x%llx\n", gregs[R_SP], gregs[R_FP], gregs[R_PC]);
14758 +#endif /* X86_COMPILER2 */
14762 + * Iterates over java frames at current location given by 'gregs'.
14764 + * Returns -1 if no java frames are present or if an error is encountered.
14765 + * Returns the result of calling 'func' if the return value is non-zero.
14766 + * Returns 0 otherwise.
14767 + */
14768 +int Jframe_iter(jvm_agent_t *J, prgregset_t gregs, java_stack_f *func, void* cld) {
14769 + char buf[MAX_SYM_SIZE + 1];
14770 + Jframe_t jframe;
14771 + int i = 0, res;
14772 +#ifdef X86_COMPILER2
14773 + if (debug > 0) {
14774 + fprintf(stderr, "Jframe_iter: Entry sp = 0x%llx, fp = 0x%llx, pc = 0x%llx\n", gregs[R_SP], gregs[R_FP], gregs[R_PC]);
14776 +#endif /* X86_COMPILER2 */
14778 + memset(&jframe, 0, sizeof(Jframe_t));
14779 + memset(buf, 0, sizeof(buf));
14780 + res = Jlookup_by_regs(J, gregs, buf, sizeof(buf), &jframe);
14781 + if (res != PS_OK)
14782 + return (-1);
14785 + res = func(cld, gregs, buf, (jframe.locinf)? jframe.bci : -1,
14786 + jframe.line, NULL);
14787 + if (res != 0) {
14788 + update_gregs(gregs, jframe);
14789 + return (res);
14791 + for (i = 1; i < jframe.vf_cnt; i++) {
14792 + Jget_vframe(J, i, buf, sizeof(buf), &jframe);
14793 + res = func(cld, gregs, buf, (jframe.locinf)? jframe.bci : -1,
14794 + jframe.line, NULL);
14795 + if (res != 0) {
14796 + update_gregs(gregs, jframe);
14797 + return (res);
14800 + update_gregs(gregs, jframe);
14801 + return (0);
14803 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/native/libjvm_db/libjvm_db.h jdk21u-jdk-21.0.4-ga/src/java.base/solaris/native/libjvm_db/libjvm_db.h
14804 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/native/libjvm_db/libjvm_db.h 1970-01-01 01:00:00.000000000 +0100
14805 +++ jdk21u-jdk-21.0.4-ga/src/java.base/solaris/native/libjvm_db/libjvm_db.h 2024-08-17 19:13:01.465457156 +0200
14806 @@ -0,0 +1,69 @@
14808 + * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
14809 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
14811 + * This code is free software; you can redistribute it and/or modify it
14812 + * under the terms of the GNU General Public License version 2 only, as
14813 + * published by the Free Software Foundation.
14815 + * This code is distributed in the hope that it will be useful, but WITHOUT
14816 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14817 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14818 + * version 2 for more details (a copy is included in the LICENSE file that
14819 + * accompanied this code).
14821 + * You should have received a copy of the GNU General Public License version
14822 + * 2 along with this work; if not, write to the Free Software Foundation,
14823 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
14825 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
14826 + * or visit www.oracle.com if you need additional information or have any
14827 + * questions.
14829 + */
14831 +#ifndef OS_SOLARIS_DTRACE_LIBJVM_DB_H
14832 +#define OS_SOLARIS_DTRACE_LIBJVM_DB_H
14834 +#include <proc_service.h>
14835 +#include "jni.h"
14837 +#ifdef __cplusplus
14838 +extern "C" {
14839 +#endif
14841 +typedef struct jvm_agent jvm_agent_t;
14843 +#define JVM_DB_VERSION 1
14845 +JNIEXPORT jvm_agent_t *Jagent_create(struct ps_prochandle *P, int vers);
14848 + * Called from Jframe_iter() for each java frame. If it returns 0, then
14849 + * Jframe_iter() proceeds to the next frame. Otherwise, the return value is
14850 + * immediately returned to the caller of Jframe_iter().
14852 + * Parameters:
14853 + * 'cld' is client supplied data (to maintain iterator state, if any).
14854 + * 'name' is java method name.
14855 + * 'bci' is byte code index. it will be -1 if not available.
14856 + * 'line' is java source line number. it will be 0 if not available.
14857 + * 'handle' is an abstract client handle, reserved for future expansions
14858 + */
14860 +typedef int java_stack_f(void *cld, const prgregset_t regs, const char* name, int bci, int line, void *handle);
14863 + * Iterates over the java frames at the current location. Returns -1 if no java
14864 + * frames were found, or if there was some unrecoverable error. Otherwise,
14865 + * returns the last value returned from 'func'.
14866 + */
14867 +JNIEXPORT int Jframe_iter(jvm_agent_t *agent, prgregset_t gregs, java_stack_f *func, void* cld);
14869 +JNIEXPORT void Jagent_destroy(jvm_agent_t *J);
14871 +#ifdef __cplusplus
14872 +} /* extern "C" */
14873 +#endif /* __cplusplus */
14875 +#endif // OS_SOLARIS_DTRACE_LIBJVM_DB_H
14876 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/native/libjvm_dtrace/jvm_dtrace.c jdk21u-jdk-21.0.4-ga/src/java.base/solaris/native/libjvm_dtrace/jvm_dtrace.c
14877 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/native/libjvm_dtrace/jvm_dtrace.c 1970-01-01 01:00:00.000000000 +0100
14878 +++ jdk21u-jdk-21.0.4-ga/src/java.base/solaris/native/libjvm_dtrace/jvm_dtrace.c 2024-08-17 19:13:01.466089764 +0200
14879 @@ -0,0 +1,562 @@
14881 + * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
14882 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
14884 + * This code is free software; you can redistribute it and/or modify it
14885 + * under the terms of the GNU General Public License version 2 only, as
14886 + * published by the Free Software Foundation.
14888 + * This code is distributed in the hope that it will be useful, but WITHOUT
14889 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14890 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14891 + * version 2 for more details (a copy is included in the LICENSE file that
14892 + * accompanied this code).
14894 + * You should have received a copy of the GNU General Public License version
14895 + * 2 along with this work; if not, write to the Free Software Foundation,
14896 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
14898 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
14899 + * or visit www.oracle.com if you need additional information or have any
14900 + * questions.
14902 + */
14904 +#include <door.h>
14905 +#include <errno.h>
14906 +#include <fcntl.h>
14907 +#include <limits.h>
14908 +#include <poll.h>
14909 +#include <signal.h>
14910 +#include <stdarg.h>
14911 +#include <stdio.h>
14912 +#include <stdlib.h>
14913 +#include <string.h>
14914 +#include <sys/types.h>
14915 +#include <sys/stat.h>
14916 +#include <thread.h>
14917 +#include <unistd.h>
14918 +#include "jvm_dtrace.h"
14920 +// NOTE: These constants are used in JVM code as well.
14921 +// KEEP JVM CODE IN SYNC if you are going to change these...
14923 +#define DTRACE_ALLOC_PROBES 0x1
14924 +#define DTRACE_METHOD_PROBES 0x2
14925 +#define DTRACE_MONITOR_PROBES 0x4
14926 +#define DTRACE_ALL_PROBES -1
14928 +// generic error messages
14929 +#define JVM_ERR_OUT_OF_MEMORY "out of memory (native heap)"
14930 +#define JVM_ERR_INVALID_PARAM "invalid input parameter(s)"
14931 +#define JVM_ERR_NULL_PARAM "input paramater is NULL"
14933 +// error messages for attach
14934 +#define JVM_ERR_CANT_OPEN_DOOR "cannot open door file"
14935 +#define JVM_ERR_CANT_CREATE_ATTACH_FILE "cannot create attach file"
14936 +#define JVM_ERR_DOOR_FILE_PERMISSION "door file is not secure"
14937 +#define JVM_ERR_CANT_SIGNAL "cannot send SIGQUIT to target"
14939 +// error messages for enable probe
14940 +#define JVM_ERR_DOOR_CMD_SEND "door command send failed"
14941 +#define JVM_ERR_DOOR_CANT_READ_STATUS "cannot read door command status"
14942 +#define JVM_ERR_DOOR_CMD_STATUS "door command error status"
14944 +// error message for detach
14945 +#define JVM_ERR_CANT_CLOSE_DOOR "cannot close door file"
14947 +#define RESTARTABLE(_cmd, _result) do { \
14948 + do { \
14949 + _result = _cmd; \
14950 + } while((_result == -1) && (errno == EINTR)); \
14951 +} while(0)
14953 +struct _jvm_t {
14954 + pid_t pid;
14955 + int door_fd;
14958 +static int libjvm_dtrace_debug;
14959 +static void print_debug(const char* fmt,...) {
14960 + if (libjvm_dtrace_debug) {
14961 + va_list alist;
14962 + va_start(alist, fmt);
14963 + fputs("libjvm_dtrace DEBUG: ", stderr);
14964 + vfprintf(stderr, fmt, alist);
14965 + va_end(alist);
14969 +/* Key for thread local error message */
14970 +static thread_key_t jvm_error_key;
14972 +/* init function for this library */
14973 +static void init_jvm_dtrace() {
14974 + /* check for env. var for debug mode */
14975 + libjvm_dtrace_debug = getenv("LIBJVM_DTRACE_DEBUG") != NULL;
14976 + /* create key for thread local error message */
14977 + if (thr_keycreate(&jvm_error_key, NULL) != 0) {
14978 + print_debug("can't create thread_key_t for jvm error key\n");
14979 + // exit(1); ?
14983 +#pragma init(init_jvm_dtrace)
14985 +/* set thread local error message */
14986 +static void set_jvm_error(const char* msg) {
14987 + thr_setspecific(jvm_error_key, (void*)msg);
14990 +/* clear thread local error message */
14991 +static void clear_jvm_error() {
14992 + thr_setspecific(jvm_error_key, NULL);
14995 +/* file handling functions that can handle interrupt */
14997 +static int file_open(const char* path, int flag) {
14998 + int ret;
14999 + RESTARTABLE(open(path, flag), ret);
15000 + return ret;
15003 +static int file_close(int fd) {
15004 + return close(fd);
15007 +static int file_read(int fd, char* buf, int len) {
15008 + int ret;
15009 + RESTARTABLE(read(fd, buf, len), ret);
15010 + return ret;
15013 +/* send SIGQUIT signal to given process */
15014 +static int send_sigquit(pid_t pid) {
15015 + int ret;
15016 + RESTARTABLE(kill(pid, SIGQUIT), ret);
15017 + return ret;
15020 +/* called to check permissions on attach file */
15021 +static int check_permission(const char* path) {
15022 + struct stat64 sb;
15023 + uid_t uid, gid;
15024 + int res;
15026 + /*
15027 + * Check that the path is owned by the effective uid/gid of this
15028 + * process. Also check that group/other access is not allowed.
15029 + */
15030 + uid = geteuid();
15031 + gid = getegid();
15033 + res = stat64(path, &sb);
15034 + if (res != 0) {
15035 + print_debug("stat failed for %s\n", path);
15036 + return -1;
15039 + if ((sb.st_uid != uid) || (sb.st_gid != gid) ||
15040 + ((sb.st_mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) != 0)) {
15041 + print_debug("well-known file %s is not secure\n", path);
15042 + return -1;
15044 + return 0;
15047 +#define ATTACH_FILE_PATTERN "/tmp/.attach_pid%d"
15049 +/* fill-in the name of attach file name in given buffer */
15050 +static void fill_attach_file_name(char* path, int len, pid_t pid) {
15051 + memset(path, 0, len);
15052 + sprintf(path, ATTACH_FILE_PATTERN, pid);
15055 +#define DOOR_FILE_PATTERN "/tmp/.java_pid%d"
15057 +/* open door file for the given JVM */
15058 +static int open_door(pid_t pid) {
15059 + char path[PATH_MAX + 1];
15060 + int fd;
15062 + sprintf(path, DOOR_FILE_PATTERN, pid);
15063 + fd = file_open(path, O_RDONLY);
15064 + if (fd < 0) {
15065 + set_jvm_error(JVM_ERR_CANT_OPEN_DOOR);
15066 + print_debug("cannot open door file %s\n", path);
15067 + return -1;
15069 + print_debug("opened door file %s\n", path);
15070 + if (check_permission(path) != 0) {
15071 + set_jvm_error(JVM_ERR_DOOR_FILE_PERMISSION);
15072 + print_debug("check permission failed for %s\n", path);
15073 + file_close(fd);
15074 + fd = -1;
15076 + return fd;
15079 +/* create attach file for given process */
15080 +static int create_attach_file(pid_t pid) {
15081 + char path[PATH_MAX + 1];
15082 + int fd;
15083 + fill_attach_file_name(path, sizeof(path), pid);
15084 + fd = file_open(path, O_CREAT | O_RDWR);
15085 + if (fd < 0) {
15086 + set_jvm_error(JVM_ERR_CANT_CREATE_ATTACH_FILE);
15087 + print_debug("cannot create file %s\n", path);
15088 + } else {
15089 + print_debug("created attach file %s\n", path);
15091 + return fd;
15094 +/* delete attach file for given process */
15095 +static void delete_attach_file(pid_t pid) {
15096 + char path[PATH_MAX + 1];
15097 + fill_attach_file_name(path, sizeof(path), pid);
15098 + int res = unlink(path);
15099 + if (res) {
15100 + print_debug("cannot delete attach file %s\n", path);
15101 + } else {
15102 + print_debug("deleted attach file %s\n", path);
15106 +/* attach to given JVM */
15107 +jvm_t* jvm_attach(pid_t pid) {
15108 + jvm_t* jvm;
15109 + int door_fd, attach_fd, i = 0;
15111 + jvm = (jvm_t*) calloc(1, sizeof(jvm_t));
15112 + if (jvm == NULL) {
15113 + set_jvm_error(JVM_ERR_OUT_OF_MEMORY);
15114 + print_debug("calloc failed in %s at %d\n", __FILE__, __LINE__);
15115 + return NULL;
15117 + jvm->pid = pid;
15118 + attach_fd = -1;
15120 + door_fd = open_door(pid);
15121 + if (door_fd < 0) {
15122 + print_debug("trying to create attach file\n");
15123 + if ((attach_fd = create_attach_file(pid)) < 0) {
15124 + goto quit;
15127 + /* send QUIT signal to the target so that it will
15128 + * check for the attach file.
15129 + */
15130 + if (send_sigquit(pid) != 0) {
15131 + set_jvm_error(JVM_ERR_CANT_SIGNAL);
15132 + print_debug("sending SIGQUIT failed\n");
15133 + goto quit;
15136 + /* give the target VM time to start the attach mechanism */
15137 + do {
15138 + int res;
15139 + RESTARTABLE(poll(0, 0, 200), res);
15140 + door_fd = open_door(pid);
15141 + i++;
15142 + } while (i <= 50 && door_fd == -1);
15143 + if (door_fd < 0) {
15144 + print_debug("Unable to open door to process %d\n", pid);
15145 + goto quit;
15149 +quit:
15150 + if (attach_fd >= 0) {
15151 + file_close(attach_fd);
15152 + delete_attach_file(jvm->pid);
15154 + if (door_fd >= 0) {
15155 + jvm->door_fd = door_fd;
15156 + clear_jvm_error();
15157 + } else {
15158 + free(jvm);
15159 + jvm = NULL;
15161 + return jvm;
15164 +/* return the last thread local error message */
15165 +const char* jvm_get_last_error() {
15166 + const char* res = NULL;
15167 + thr_getspecific(jvm_error_key, (void**)&res);
15168 + return res;
15171 +/* detach the givenb JVM */
15172 +int jvm_detach(jvm_t* jvm) {
15173 + if (jvm) {
15174 + int res = 0;
15175 + if (jvm->door_fd != -1) {
15176 + if (file_close(jvm->door_fd) != 0) {
15177 + set_jvm_error(JVM_ERR_CANT_CLOSE_DOOR);
15178 + res = -1;
15179 + } else {
15180 + clear_jvm_error();
15183 + free(jvm);
15184 + return res;
15185 + } else {
15186 + set_jvm_error(JVM_ERR_NULL_PARAM);
15187 + print_debug("jvm_t* is NULL\n");
15188 + return -1;
15193 + * A simple table to translate some known errors into reasonable
15194 + * error messages
15195 + */
15196 +static struct {
15197 + int err;
15198 + const char* msg;
15199 +} const error_messages[] = {
15200 + { 100, "Bad request" },
15201 + { 101, "Protocol mismatch" },
15202 + { 102, "Resource failure" },
15203 + { 103, "Internal error" },
15204 + { 104, "Permission denied" },
15208 + * Lookup the given error code and return the appropriate
15209 + * message. If not found return NULL.
15210 + */
15211 +static const char* translate_error(int err) {
15212 + int table_size = sizeof(error_messages) / sizeof(error_messages[0]);
15213 + int i;
15215 + for (i=0; i<table_size; i++) {
15216 + if (err == error_messages[i].err) {
15217 + return error_messages[i].msg;
15220 + return NULL;
15224 + * Current protocol version
15225 + */
15226 +static const char* PROTOCOL_VERSION = "1";
15228 +#define RES_BUF_SIZE 128
15231 + * Enqueue attach-on-demand command to the given JVM
15232 + */
15233 +static
15234 +int enqueue_command(jvm_t* jvm, const char* cstr, int arg_count, const char** args) {
15235 + size_t size;
15236 + door_arg_t door_args;
15237 + char res_buffer[RES_BUF_SIZE];
15238 + int rc, i;
15239 + char* buf = NULL;
15240 + int result = -1;
15242 + /*
15243 + * First we get the command string and create the start of the
15244 + * argument string to send to the target VM:
15245 + * <ver>\0<cmd>\0
15246 + */
15247 + if (cstr == NULL) {
15248 + print_debug("command name is NULL\n");
15249 + goto quit;
15251 + size = strlen(PROTOCOL_VERSION) + strlen(cstr) + 2;
15252 + buf = (char*)malloc(size);
15253 + if (buf != NULL) {
15254 + char* pos = buf;
15255 + strcpy(buf, PROTOCOL_VERSION);
15256 + pos += strlen(PROTOCOL_VERSION)+1;
15257 + strcpy(pos, cstr);
15258 + } else {
15259 + set_jvm_error(JVM_ERR_OUT_OF_MEMORY);
15260 + print_debug("malloc failed at %d in %s\n", __LINE__, __FILE__);
15261 + goto quit;
15264 + /*
15265 + * Next we iterate over the arguments and extend the buffer
15266 + * to include them.
15267 + */
15268 + for (i=0; i<arg_count; i++) {
15269 + cstr = args[i];
15270 + if (cstr != NULL) {
15271 + size_t len = strlen(cstr);
15272 + char* newbuf = (char*)realloc(buf, size+len+1);
15273 + if (newbuf == NULL) {
15274 + set_jvm_error(JVM_ERR_OUT_OF_MEMORY);
15275 + print_debug("realloc failed in %s at %d\n", __FILE__, __LINE__);
15276 + goto quit;
15278 + buf = newbuf;
15279 + strcpy(buf+size, cstr);
15280 + size += len+1;
15284 + /*
15285 + * The arguments to the door function are in 'buf' so we now
15286 + * do the door call
15287 + */
15288 + door_args.data_ptr = buf;
15289 + door_args.data_size = size;
15290 + door_args.desc_ptr = NULL;
15291 + door_args.desc_num = 0;
15292 + door_args.rbuf = (char*)&res_buffer;
15293 + door_args.rsize = sizeof(res_buffer);
15295 + RESTARTABLE(door_call(jvm->door_fd, &door_args), rc);
15297 + /*
15298 + * door_call failed
15299 + */
15300 + if (rc == -1) {
15301 + print_debug("door_call failed\n");
15302 + } else {
15303 + /*
15304 + * door_call succeeded but the call didn't return the expected jint.
15305 + */
15306 + if (door_args.data_size < sizeof(int)) {
15307 + print_debug("Enqueue error - reason unknown as result is truncated!");
15308 + } else {
15309 + int* res = (int*)(door_args.data_ptr);
15310 + if (*res != 0) {
15311 + const char* msg = translate_error(*res);
15312 + if (msg == NULL) {
15313 + print_debug("Unable to enqueue command to target VM: %d\n", *res);
15314 + } else {
15315 + print_debug("Unable to enqueue command to target VM: %s\n", msg);
15317 + } else {
15318 + /*
15319 + * The door call should return a file descriptor to one end of
15320 + * a socket pair
15321 + */
15322 + if ((door_args.desc_ptr != NULL) &&
15323 + (door_args.desc_num == 1) &&
15324 + (door_args.desc_ptr->d_attributes & DOOR_DESCRIPTOR)) {
15325 + result = door_args.desc_ptr->d_data.d_desc.d_descriptor;
15326 + } else {
15327 + print_debug("Reply from enqueue missing descriptor!\n");
15333 +quit:
15334 + if (buf) free(buf);
15335 + return result;
15338 +/* read status code for a door command */
15339 +static int read_status(int fd) {
15340 + char ch, buf[16];
15341 + int index = 0;
15343 + while (1) {
15344 + if (file_read(fd, &ch, sizeof(ch)) != sizeof(ch)) {
15345 + set_jvm_error(JVM_ERR_DOOR_CANT_READ_STATUS);
15346 + print_debug("door cmd status: read status failed\n");
15347 + return -1;
15349 + buf[index++] = ch;
15350 + if (ch == '\n') {
15351 + buf[index - 1] = '\0';
15352 + return atoi(buf);
15354 + if (index == sizeof(buf)) {
15355 + set_jvm_error(JVM_ERR_DOOR_CANT_READ_STATUS);
15356 + print_debug("door cmd status: read status overflow\n");
15357 + return -1;
15362 +static const char* ENABLE_DPROBES_CMD = "enabledprobes";
15364 +/* enable one or more DTrace probes for a given JVM */
15365 +int jvm_enable_dtprobes(jvm_t* jvm, int num_probe_types, const char** probe_types) {
15366 + int fd, status = 0;
15367 + char ch;
15368 + const char* args[1];
15369 + char buf[16];
15370 + int probe_type = 0, index;
15371 + int count = 0;
15373 + if (jvm == NULL) {
15374 + set_jvm_error(JVM_ERR_NULL_PARAM);
15375 + print_debug("jvm_t* is NULL\n");
15376 + return -1;
15379 + if (num_probe_types == 0 || probe_types == NULL ||
15380 + probe_types[0] == NULL) {
15381 + set_jvm_error(JVM_ERR_INVALID_PARAM);
15382 + print_debug("invalid probe type argument(s)\n");
15383 + return -1;
15386 + for (index = 0; index < num_probe_types; index++) {
15387 + const char* p = probe_types[index];
15388 + if (strcmp(p, JVM_DTPROBE_OBJECT_ALLOC) == 0) {
15389 + probe_type |= DTRACE_ALLOC_PROBES;
15390 + count++;
15391 + } else if (strcmp(p, JVM_DTPROBE_METHOD_ENTRY) == 0 ||
15392 + strcmp(p, JVM_DTPROBE_METHOD_RETURN) == 0) {
15393 + probe_type |= DTRACE_METHOD_PROBES;
15394 + count++;
15395 + } else if (strcmp(p, JVM_DTPROBE_MONITOR_ENTER) == 0 ||
15396 + strcmp(p, JVM_DTPROBE_MONITOR_ENTERED) == 0 ||
15397 + strcmp(p, JVM_DTPROBE_MONITOR_EXIT) == 0 ||
15398 + strcmp(p, JVM_DTPROBE_MONITOR_WAIT) == 0 ||
15399 + strcmp(p, JVM_DTPROBE_MONITOR_WAITED) == 0 ||
15400 + strcmp(p, JVM_DTPROBE_MONITOR_NOTIFY) == 0 ||
15401 + strcmp(p, JVM_DTPROBE_MONITOR_NOTIFYALL) == 0) {
15402 + probe_type |= DTRACE_MONITOR_PROBES;
15403 + count++;
15404 + } else if (strcmp(p, JVM_DTPROBE_ALL) == 0) {
15405 + probe_type |= DTRACE_ALL_PROBES;
15406 + count++;
15410 + if (count == 0) {
15411 + return count;
15413 + sprintf(buf, "%d", probe_type);
15414 + args[0] = buf;
15416 + fd = enqueue_command(jvm, ENABLE_DPROBES_CMD, 1, args);
15417 + if (fd < 0) {
15418 + set_jvm_error(JVM_ERR_DOOR_CMD_SEND);
15419 + return -1;
15422 + status = read_status(fd);
15423 + // non-zero status is error
15424 + if (status) {
15425 + set_jvm_error(JVM_ERR_DOOR_CMD_STATUS);
15426 + print_debug("%s command failed (status: %d) in target JVM\n",
15427 + ENABLE_DPROBES_CMD, status);
15428 + file_close(fd);
15429 + return -1;
15431 + // read from stream until EOF
15432 + while (file_read(fd, &ch, sizeof(ch)) == sizeof(ch)) {
15433 + if (libjvm_dtrace_debug) {
15434 + printf("%c", ch);
15438 + file_close(fd);
15439 + clear_jvm_error();
15440 + return count;
15442 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/native/libjvm_dtrace/jvm_dtrace.h jdk21u-jdk-21.0.4-ga/src/java.base/solaris/native/libjvm_dtrace/jvm_dtrace.h
15443 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/native/libjvm_dtrace/jvm_dtrace.h 1970-01-01 01:00:00.000000000 +0100
15444 +++ jdk21u-jdk-21.0.4-ga/src/java.base/solaris/native/libjvm_dtrace/jvm_dtrace.h 2024-08-17 19:13:01.466427091 +0200
15445 @@ -0,0 +1,86 @@
15447 + * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
15448 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
15450 + * This code is free software; you can redistribute it and/or modify it
15451 + * under the terms of the GNU General Public License version 2 only, as
15452 + * published by the Free Software Foundation.
15454 + * This code is distributed in the hope that it will be useful, but WITHOUT
15455 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15456 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15457 + * version 2 for more details (a copy is included in the LICENSE file that
15458 + * accompanied this code).
15460 + * You should have received a copy of the GNU General Public License version
15461 + * 2 along with this work; if not, write to the Free Software Foundation,
15462 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
15464 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
15465 + * or visit www.oracle.com if you need additional information or have any
15466 + * questions.
15468 + */
15470 +#ifndef _JVM_DTRACE_H_
15471 +#define _JVM_DTRACE_H_
15474 + * Interface to dynamically turn on probes in Hotspot JVM. Currently,
15475 + * this interface can be used to dynamically enable certain DTrace
15476 + * probe points that are costly to have "always on".
15477 + */
15479 +#ifdef __cplusplus
15480 +extern "C" {
15481 +#endif
15483 +#include <sys/types.h>
15484 +#include "jni.h"
15486 +struct _jvm_t;
15487 +typedef struct _jvm_t jvm_t;
15490 +/* Attach to the given JVM process. Returns NULL on failure.
15491 + jvm_get_last_error() returns last error message. */
15492 +JNIEXPORT jvm_t* jvm_attach(pid_t pid);
15494 +/* Returns the last error message from this library or NULL if none. */
15495 +JNIEXPORT const char* jvm_get_last_error();
15497 +/* few well-known probe type constants for 'probe_types' param below */
15499 +#define JVM_DTPROBE_METHOD_ENTRY "method-entry"
15500 +#define JVM_DTPROBE_METHOD_RETURN "method-return"
15501 +#define JVM_DTPROBE_MONITOR_ENTER "monitor-contended-enter"
15502 +#define JVM_DTPROBE_MONITOR_ENTERED "monitor-contended-entered"
15503 +#define JVM_DTPROBE_MONITOR_EXIT "monitor-contended-exit"
15504 +#define JVM_DTPROBE_MONITOR_WAIT "monitor-wait"
15505 +#define JVM_DTPROBE_MONITOR_WAITED "monitor-waited"
15506 +#define JVM_DTPROBE_MONITOR_NOTIFY "monitor-notify"
15507 +#define JVM_DTPROBE_MONITOR_NOTIFYALL "monitor-notifyall"
15508 +#define JVM_DTPROBE_OBJECT_ALLOC "object-alloc"
15509 +#define JVM_DTPROBE_ALL "*"
15511 +/* Enable the specified DTrace probes of given probe types on
15512 + * the specified JVM. Returns >= 0 on success, -1 on failure.
15513 + * On success, this returns number of probe_types enabled.
15514 + * On failure, jvm_get_last_error() returns the last error message.
15515 + */
15516 +JNIEXPORT int jvm_enable_dtprobes(jvm_t* jvm, int num_probe_types, const char** probe_types);
15518 +/* Note: There is no jvm_disable_dtprobes function. Probes are automatically
15519 + * disabled when there are no more clients requiring those probes.
15520 + */
15522 +/* Detach the given JVM. Returns 0 on success, -1 on failure.
15523 + * jvm_get_last_error() returns the last error message.
15524 + */
15525 +JNIEXPORT int jvm_detach(jvm_t* jvm);
15527 +#ifdef __cplusplus
15529 +#endif
15531 +#endif /* _JVM_DTRACE_H_ */
15532 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/native/libnet/solaris_close.c jdk21u-jdk-21.0.4-ga/src/java.base/solaris/native/libnet/solaris_close.c
15533 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/native/libnet/solaris_close.c 1970-01-01 01:00:00.000000000 +0100
15534 +++ jdk21u-jdk-21.0.4-ga/src/java.base/solaris/native/libnet/solaris_close.c 2024-08-17 19:13:01.466844681 +0200
15535 @@ -0,0 +1,107 @@
15537 + * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
15538 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
15540 + * This code is free software; you can redistribute it and/or modify it
15541 + * under the terms of the GNU General Public License version 2 only, as
15542 + * published by the Free Software Foundation. Oracle designates this
15543 + * particular file as subject to the "Classpath" exception as provided
15544 + * by Oracle in the LICENSE file that accompanied this code.
15546 + * This code is distributed in the hope that it will be useful, but WITHOUT
15547 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15548 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15549 + * version 2 for more details (a copy is included in the LICENSE file that
15550 + * accompanied this code).
15552 + * You should have received a copy of the GNU General Public License version
15553 + * 2 along with this work; if not, write to the Free Software Foundation,
15554 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
15556 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
15557 + * or visit www.oracle.com if you need additional information or have any
15558 + * questions.
15559 + */
15561 +#include <errno.h>
15562 +#include <sys/socket.h>
15563 +#include <stropts.h>
15564 +#include <unistd.h>
15565 +#include "jvm.h"
15566 +#include "net_util.h"
15568 +/* Support for restartable system calls on Solaris. */
15570 +#define RESTARTABLE_RETURN_INT(_cmd) do { \
15571 + int _result; \
15572 + if (1) { \
15573 + do { \
15574 + _result = _cmd; \
15575 + } while((_result == -1) && (errno == EINTR)); \
15576 + return _result; \
15577 + } \
15578 +} while(0)
15580 +int NET_Read(int s, void* buf, size_t len) {
15581 + RESTARTABLE_RETURN_INT(recv(s, buf, len, 0));
15584 +int NET_NonBlockingRead(int s, void* buf, size_t len) {
15585 + RESTARTABLE_RETURN_INT(recv(s, buf, len, MSG_DONTWAIT));
15588 +int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
15589 + struct sockaddr *from, socklen_t *fromlen) {
15590 + RESTARTABLE_RETURN_INT(recvfrom(s, buf, len, flags, from, fromlen));
15593 +int NET_Send(int s, void *msg, int len, unsigned int flags) {
15594 + RESTARTABLE_RETURN_INT(send(s, msg, len, flags));
15597 +int NET_SendTo(int s, const void *msg, int len, unsigned int flags,
15598 + const struct sockaddr *to, int tolen) {
15599 + RESTARTABLE_RETURN_INT(sendto(s, msg, len, flags, to, tolen));
15602 +int NET_Connect(int s, struct sockaddr *addr, int addrlen) {
15603 + RESTARTABLE_RETURN_INT(connect(s, addr, addrlen));
15606 +int NET_Accept(int s, struct sockaddr *addr, socklen_t *addrlen) {
15607 + RESTARTABLE_RETURN_INT(accept(s, addr, addrlen));
15610 +int NET_SocketClose(int fd) {
15611 + return close(fd);
15614 +int NET_Dup2(int fd, int fd2) {
15615 + return dup2(fd, fd2);
15618 +int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
15619 + RESTARTABLE_RETURN_INT(poll(ufds, nfds, timeout));
15622 +int NET_Timeout(JNIEnv *env, int s, long timeout, jlong nanoTimeStamp) {
15623 + int result;
15624 + jlong prevNanoTime = nanoTimeStamp;
15625 + jlong nanoTimeout = (jlong) timeout * NET_NSEC_PER_MSEC;
15626 + struct pollfd pfd;
15627 + pfd.fd = s;
15628 + pfd.events = POLLIN;
15630 + for(;;) {
15631 + result = poll(&pfd, 1, nanoTimeout / NET_NSEC_PER_MSEC);
15632 + if (result < 0 && errno == EINTR) {
15633 + jlong newNanoTime = JVM_NanoTime(env, 0);
15634 + nanoTimeout -= newNanoTime - prevNanoTime;
15635 + if (nanoTimeout < NET_NSEC_PER_MSEC)
15636 + return 0;
15637 + prevNanoTime = newNanoTime;
15638 + } else {
15639 + return result;
15643 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/native/libnio/ch/DevPollArrayWrapper.c jdk21u-jdk-21.0.4-ga/src/java.base/solaris/native/libnio/ch/DevPollArrayWrapper.c
15644 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/native/libnio/ch/DevPollArrayWrapper.c 1970-01-01 01:00:00.000000000 +0100
15645 +++ jdk21u-jdk-21.0.4-ga/src/java.base/solaris/native/libnio/ch/DevPollArrayWrapper.c 2024-08-17 19:13:01.467319373 +0200
15646 @@ -0,0 +1,112 @@
15648 + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
15649 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
15651 + * This code is free software; you can redistribute it and/or modify it
15652 + * under the terms of the GNU General Public License version 2 only, as
15653 + * published by the Free Software Foundation. Oracle designates this
15654 + * particular file as subject to the "Classpath" exception as provided
15655 + * by Oracle in the LICENSE file that accompanied this code.
15657 + * This code is distributed in the hope that it will be useful, but WITHOUT
15658 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15659 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15660 + * version 2 for more details (a copy is included in the LICENSE file that
15661 + * accompanied this code).
15663 + * You should have received a copy of the GNU General Public License version
15664 + * 2 along with this work; if not, write to the Free Software Foundation,
15665 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
15667 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
15668 + * or visit www.oracle.com if you need additional information or have any
15669 + * questions.
15670 + */
15672 +#include <sys/types.h>
15673 +#include <sys/stat.h>
15674 +#include <devpoll.h>
15675 +#include <fcntl.h>
15676 +#include <poll.h>
15678 +#include "jni.h"
15679 +#include "jni_util.h"
15680 +#include "jvm.h"
15681 +#include "jlong.h"
15682 +#include "nio.h"
15683 +#include "nio_util.h"
15685 +#include "sun_nio_ch_DevPollArrayWrapper.h"
15687 +JNIEXPORT jint JNICALL
15688 +Java_sun_nio_ch_DevPollArrayWrapper_init(JNIEnv *env, jobject this)
15690 + int wfd = open("/dev/poll", O_RDWR);
15691 + if (wfd < 0) {
15692 + JNU_ThrowIOExceptionWithLastError(env, "Error opening driver");
15693 + return -1;
15695 + return wfd;
15698 +JNIEXPORT void JNICALL
15699 +Java_sun_nio_ch_DevPollArrayWrapper_register(JNIEnv *env, jobject this,
15700 + jint wfd, jint fd, jint mask)
15702 + struct pollfd a[1];
15703 + int n;
15705 + a[0].fd = fd;
15706 + a[0].events = mask;
15707 + a[0].revents = 0;
15709 + n = write(wfd, &a[0], sizeof(a));
15710 + if (n != sizeof(a)) {
15711 + if (n < 0) {
15712 + JNU_ThrowIOExceptionWithLastError(env, "Error writing pollfds");
15713 + } else {
15714 + JNU_ThrowIOException(env, "Unexpected number of bytes written");
15719 +JNIEXPORT void JNICALL
15720 +Java_sun_nio_ch_DevPollArrayWrapper_registerMultiple(JNIEnv *env, jobject this,
15721 + jint wfd, jlong address,
15722 + jint len)
15724 + unsigned char *pollBytes = (unsigned char *)jlong_to_ptr(address);
15725 + unsigned char *pollEnd = pollBytes + sizeof(struct pollfd) * len;
15726 + while (pollBytes < pollEnd) {
15727 + int bytesWritten = write(wfd, pollBytes, (int)(pollEnd - pollBytes));
15728 + if (bytesWritten < 0) {
15729 + JNU_ThrowIOExceptionWithLastError(env, "Error writing pollfds");
15730 + return;
15732 + pollBytes += bytesWritten;
15736 +JNIEXPORT jint JNICALL
15737 +Java_sun_nio_ch_DevPollArrayWrapper_poll0(JNIEnv *env, jobject this,
15738 + jlong address, jint numfds,
15739 + jlong timeout, jint wfd)
15741 + struct dvpoll a;
15742 + void *pfd = (void *) jlong_to_ptr(address);
15743 + int result;
15745 + a.dp_fds = pfd;
15746 + a.dp_nfds = numfds;
15747 + a.dp_timeout = (int)timeout;
15748 + result = ioctl(wfd, DP_POLL, &a);
15749 + if (result < 0) {
15750 + if (errno == EINTR) {
15751 + return IOS_INTERRUPTED;
15752 + } else {
15753 + JNU_ThrowIOExceptionWithLastError(env, "Error reading driver");
15754 + return IOS_THROWN;
15757 + return result;
15759 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/native/libnio/ch/SolarisEventPort.c jdk21u-jdk-21.0.4-ga/src/java.base/solaris/native/libnio/ch/SolarisEventPort.c
15760 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/native/libnio/ch/SolarisEventPort.c 1970-01-01 01:00:00.000000000 +0100
15761 +++ jdk21u-jdk-21.0.4-ga/src/java.base/solaris/native/libnio/ch/SolarisEventPort.c 2024-08-17 19:13:01.467794985 +0200
15762 @@ -0,0 +1,147 @@
15764 + * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
15765 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
15767 + * This code is free software; you can redistribute it and/or modify it
15768 + * under the terms of the GNU General Public License version 2 only, as
15769 + * published by the Free Software Foundation. Oracle designates this
15770 + * particular file as subject to the "Classpath" exception as provided
15771 + * by Oracle in the LICENSE file that accompanied this code.
15773 + * This code is distributed in the hope that it will be useful, but WITHOUT
15774 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15775 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15776 + * version 2 for more details (a copy is included in the LICENSE file that
15777 + * accompanied this code).
15779 + * You should have received a copy of the GNU General Public License version
15780 + * 2 along with this work; if not, write to the Free Software Foundation,
15781 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
15783 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
15784 + * or visit www.oracle.com if you need additional information or have any
15785 + * questions.
15786 + */
15788 +#include <stdlib.h>
15789 +#include <dlfcn.h>
15790 +#include <sys/types.h>
15791 +#include <port.h>
15793 +#include "jni.h"
15794 +#include "jni_util.h"
15795 +#include "jvm.h"
15796 +#include "jlong.h"
15797 +#include "nio.h"
15798 +#include "nio_util.h"
15800 +#include "sun_nio_ch_SolarisEventPort.h"
15802 +JNIEXPORT jint JNICALL
15803 +Java_sun_nio_ch_SolarisEventPort_port_1create
15804 + (JNIEnv* env, jclass clazz)
15806 + int port = port_create();
15807 + if (port == -1) {
15808 + JNU_ThrowIOExceptionWithLastError(env, "port_create");
15810 + return (jint)port;
15813 +JNIEXPORT void JNICALL
15814 +Java_sun_nio_ch_SolarisEventPort_port_1close
15815 + (JNIEnv* env, jclass clazz, jint port)
15817 + int res = close(port);
15818 + if (res < 0 && res != EINTR) {
15819 + JNU_ThrowIOExceptionWithLastError(env, "close failed");
15823 +JNIEXPORT jboolean JNICALL
15824 +Java_sun_nio_ch_SolarisEventPort_port_1associate
15825 + (JNIEnv* env, jclass clazz, jint port, jint source, jlong objectAddress, jint events)
15827 + uintptr_t object = (uintptr_t)jlong_to_ptr(objectAddress);
15828 + if (port_associate((int)port, (int)source, object, (int)events, NULL) == 0) {
15829 + return JNI_TRUE;
15830 + } else {
15831 + if (errno != EBADFD)
15832 + JNU_ThrowIOExceptionWithLastError(env, "port_associate");
15833 + return JNI_FALSE;
15837 +JNIEXPORT jboolean JNICALL
15838 +Java_sun_nio_ch_SolarisEventPort_port_1dissociate
15839 + (JNIEnv* env, jclass clazz, jint port, jint source, jlong objectAddress)
15841 + uintptr_t object = (uintptr_t)jlong_to_ptr(objectAddress);
15843 + if (port_dissociate((int)port, (int)source, object) == 0) {
15844 + return JNI_TRUE;
15845 + } else {
15846 + if (errno != ENOENT)
15847 + JNU_ThrowIOExceptionWithLastError(env, "port_dissociate");
15848 + return JNI_FALSE;
15852 +JNIEXPORT void JNICALL
15853 +Java_sun_nio_ch_SolarisEventPort_port_1send(JNIEnv* env, jclass clazz,
15854 + jint port, jint events)
15856 + if (port_send((int)port, (int)events, NULL) == -1) {
15857 + JNU_ThrowIOExceptionWithLastError(env, "port_send");
15861 +JNIEXPORT jint JNICALL
15862 +Java_sun_nio_ch_SolarisEventPort_port_1get(JNIEnv* env, jclass clazz,
15863 + jint port, jlong eventAddress)
15865 + int res;
15866 + port_event_t* ev = (port_event_t*)jlong_to_ptr(eventAddress);
15868 + res = port_get((int)port, ev, NULL);
15869 + if (res == -1) {
15870 + if (errno == EINTR) {
15871 + return IOS_INTERRUPTED;
15872 + } else {
15873 + JNU_ThrowIOExceptionWithLastError(env, "port_get failed");
15874 + return IOS_THROWN;
15877 + return res;
15880 +JNIEXPORT jint JNICALL
15881 +Java_sun_nio_ch_SolarisEventPort_port_1getn(JNIEnv* env, jclass clazz,
15882 + jint port, jlong arrayAddress, jint max, jlong timeout)
15884 + int res;
15885 + uint_t n = 1;
15886 + port_event_t* list = (port_event_t*)jlong_to_ptr(arrayAddress);
15887 + timespec_t ts;
15888 + timespec_t* tsp;
15890 + if (timeout >= 0L) {
15891 + ts.tv_sec = timeout / 1000;
15892 + ts.tv_nsec = 1000000 * (timeout % 1000);
15893 + tsp = &ts;
15894 + } else {
15895 + tsp = NULL;
15898 + res = port_getn((int)port, list, (uint_t)max, &n, tsp);
15899 + if (res == -1 && errno != ETIME) {
15900 + if (errno == EINTR) {
15901 + return IOS_INTERRUPTED;
15902 + } else {
15903 + JNU_ThrowIOExceptionWithLastError(env, "port_getn failed");
15904 + return IOS_THROWN;
15908 + return (jint)n;
15910 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/native/libnio/fs/SolarisNativeDispatcher.c jdk21u-jdk-21.0.4-ga/src/java.base/solaris/native/libnio/fs/SolarisNativeDispatcher.c
15911 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/native/libnio/fs/SolarisNativeDispatcher.c 1970-01-01 01:00:00.000000000 +0100
15912 +++ jdk21u-jdk-21.0.4-ga/src/java.base/solaris/native/libnio/fs/SolarisNativeDispatcher.c 2024-08-17 19:13:01.468228220 +0200
15913 @@ -0,0 +1,143 @@
15915 + * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
15916 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
15918 + * This code is free software; you can redistribute it and/or modify it
15919 + * under the terms of the GNU General Public License version 2 only, as
15920 + * published by the Free Software Foundation. Oracle designates this
15921 + * particular file as subject to the "Classpath" exception as provided
15922 + * by Oracle in the LICENSE file that accompanied this code.
15924 + * This code is distributed in the hope that it will be useful, but WITHOUT
15925 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15926 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15927 + * version 2 for more details (a copy is included in the LICENSE file that
15928 + * accompanied this code).
15930 + * You should have received a copy of the GNU General Public License version
15931 + * 2 along with this work; if not, write to the Free Software Foundation,
15932 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
15934 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
15935 + * or visit www.oracle.com if you need additional information or have any
15936 + * questions.
15937 + */
15939 +#include "jni.h"
15940 +#include "jni_util.h"
15941 +#include "jvm.h"
15942 +#include "jlong.h"
15944 +#include <strings.h>
15945 +#include <errno.h>
15946 +#include <sys/acl.h>
15947 +#include <sys/mnttab.h>
15948 +#include <sys/mkdev.h>
15950 +#include "jni.h"
15952 +#include "sun_nio_fs_SolarisNativeDispatcher.h"
15954 +static jfieldID entry_name;
15955 +static jfieldID entry_dir;
15956 +static jfieldID entry_fstype;
15957 +static jfieldID entry_options;
15958 +static jfieldID entry_dev;
15960 +static void throwUnixException(JNIEnv* env, int errnum) {
15961 + jobject x = JNU_NewObjectByName(env, "sun/nio/fs/UnixException",
15962 + "(I)V", errnum);
15963 + if (x != NULL) {
15964 + (*env)->Throw(env, x);
15968 +JNIEXPORT void JNICALL
15969 +Java_sun_nio_fs_SolarisNativeDispatcher_init(JNIEnv *env, jclass clazz) {
15970 + clazz = (*env)->FindClass(env, "sun/nio/fs/UnixMountEntry");
15971 + CHECK_NULL(clazz);
15972 + entry_name = (*env)->GetFieldID(env, clazz, "name", "[B");
15973 + CHECK_NULL(entry_name);
15974 + entry_dir = (*env)->GetFieldID(env, clazz, "dir", "[B");
15975 + CHECK_NULL(entry_dir);
15976 + entry_fstype = (*env)->GetFieldID(env, clazz, "fstype", "[B");
15977 + CHECK_NULL(entry_fstype);
15978 + entry_options = (*env)->GetFieldID(env, clazz, "opts", "[B");
15979 + CHECK_NULL(entry_options);
15980 + entry_dev = (*env)->GetFieldID(env, clazz, "dev", "J");
15981 + CHECK_NULL(entry_dev);
15984 +JNIEXPORT jint JNICALL
15985 +Java_sun_nio_fs_SolarisNativeDispatcher_facl(JNIEnv* env, jclass this, jint fd,
15986 + jint cmd, jint nentries, jlong address)
15988 + void* aclbufp = jlong_to_ptr(address);
15989 + int n = -1;
15991 + n = facl((int)fd, (int)cmd, (int)nentries, aclbufp);
15992 + if (n == -1) {
15993 + throwUnixException(env, errno);
15995 + return (jint)n;
15998 +JNIEXPORT jint JNICALL
15999 +Java_sun_nio_fs_SolarisNativeDispatcher_getextmntent(JNIEnv* env, jclass this,
16000 + jlong value, jobject entry)
16002 + struct extmnttab ent;
16003 + FILE* fp = jlong_to_ptr(value);
16004 + jsize len;
16005 + jbyteArray bytes;
16006 + char* name;
16007 + char* dir;
16008 + char* fstype;
16009 + char* options;
16010 + dev_t dev;
16012 + if (getextmntent(fp, &ent, 0))
16013 + return -1;
16014 + name = ent.mnt_special;
16015 + dir = ent.mnt_mountp;
16016 + fstype = ent.mnt_fstype;
16017 + options = ent.mnt_mntopts;
16018 + dev = makedev(ent.mnt_major, ent.mnt_minor);
16019 + if (dev == NODEV) {
16020 + throwUnixException(env, errno);
16021 + return -1;
16024 + len = strlen(name);
16025 + bytes = (*env)->NewByteArray(env, len);
16026 + if (bytes == NULL)
16027 + return -1;
16028 + (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)name);
16029 + (*env)->SetObjectField(env, entry, entry_name, bytes);
16031 + len = strlen(dir);
16032 + bytes = (*env)->NewByteArray(env, len);
16033 + if (bytes == NULL)
16034 + return -1;
16035 + (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)dir);
16036 + (*env)->SetObjectField(env, entry, entry_dir, bytes);
16038 + len = strlen(fstype);
16039 + bytes = (*env)->NewByteArray(env, len);
16040 + if (bytes == NULL)
16041 + return -1;
16042 + (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)fstype);
16043 + (*env)->SetObjectField(env, entry, entry_fstype, bytes);
16045 + len = strlen(options);
16046 + bytes = (*env)->NewByteArray(env, len);
16047 + if (bytes == NULL)
16048 + return -1;
16049 + (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)options);
16050 + (*env)->SetObjectField(env, entry, entry_options, bytes);
16052 + if (dev != 0)
16053 + (*env)->SetLongField(env, entry, entry_dev, (jlong)dev);
16055 + return 0;
16057 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/native/libnio/fs/SolarisWatchService.c jdk21u-jdk-21.0.4-ga/src/java.base/solaris/native/libnio/fs/SolarisWatchService.c
16058 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/solaris/native/libnio/fs/SolarisWatchService.c 1970-01-01 01:00:00.000000000 +0100
16059 +++ jdk21u-jdk-21.0.4-ga/src/java.base/solaris/native/libnio/fs/SolarisWatchService.c 2024-08-17 19:13:01.468558354 +0200
16060 @@ -0,0 +1,104 @@
16062 + * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
16063 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
16065 + * This code is free software; you can redistribute it and/or modify it
16066 + * under the terms of the GNU General Public License version 2 only, as
16067 + * published by the Free Software Foundation. Oracle designates this
16068 + * particular file as subject to the "Classpath" exception as provided
16069 + * by Oracle in the LICENSE file that accompanied this code.
16071 + * This code is distributed in the hope that it will be useful, but WITHOUT
16072 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16073 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16074 + * version 2 for more details (a copy is included in the LICENSE file that
16075 + * accompanied this code).
16077 + * You should have received a copy of the GNU General Public License version
16078 + * 2 along with this work; if not, write to the Free Software Foundation,
16079 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
16081 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
16082 + * or visit www.oracle.com if you need additional information or have any
16083 + * questions.
16084 + */
16086 +#include "jni.h"
16087 +#include "jni_util.h"
16088 +#include "jvm.h"
16089 +#include "jlong.h"
16091 +#include <stdlib.h>
16092 +#include <dlfcn.h>
16093 +#include <sys/types.h>
16094 +#include <port.h> // Solaris 10
16096 +#include "sun_nio_fs_SolarisWatchService.h"
16098 +static void throwUnixException(JNIEnv* env, int errnum) {
16099 + jobject x = JNU_NewObjectByName(env, "sun/nio/fs/UnixException",
16100 + "(I)V", errnum);
16101 + if (x != NULL) {
16102 + (*env)->Throw(env, x);
16106 +JNIEXPORT void JNICALL
16107 +Java_sun_nio_fs_SolarisWatchService_init(JNIEnv *env, jclass clazz)
16111 +JNIEXPORT jint JNICALL
16112 +Java_sun_nio_fs_SolarisWatchService_portCreate
16113 + (JNIEnv* env, jclass clazz)
16115 + int port = port_create();
16116 + if (port == -1) {
16117 + throwUnixException(env, errno);
16119 + return (jint)port;
16122 +JNIEXPORT void JNICALL
16123 +Java_sun_nio_fs_SolarisWatchService_portAssociate
16124 + (JNIEnv* env, jclass clazz, jint port, jint source, jlong objectAddress, jint events)
16126 + uintptr_t object = (uintptr_t)jlong_to_ptr(objectAddress);
16128 + if (port_associate((int)port, (int)source, object, (int)events, NULL) == -1) {
16129 + throwUnixException(env, errno);
16133 +JNIEXPORT void JNICALL
16134 +Java_sun_nio_fs_SolarisWatchService_portDissociate
16135 + (JNIEnv* env, jclass clazz, jint port, jint source, jlong objectAddress)
16137 + uintptr_t object = (uintptr_t)jlong_to_ptr(objectAddress);
16139 + if (port_dissociate((int)port, (int)source, object) == -1) {
16140 + throwUnixException(env, errno);
16144 +JNIEXPORT void JNICALL
16145 +Java_sun_nio_fs_SolarisWatchService_portSend(JNIEnv* env, jclass clazz,
16146 + jint port, jint events)
16148 + if (port_send((int)port, (int)events, NULL) == -1) {
16149 + throwUnixException(env, errno);
16153 +JNIEXPORT jint JNICALL
16154 +Java_sun_nio_fs_SolarisWatchService_portGetn(JNIEnv* env, jclass clazz,
16155 + jint port, jlong arrayAddress, jint max)
16157 + uint_t n = 1;
16158 + port_event_t* list = (port_event_t*)jlong_to_ptr(arrayAddress);
16160 + if (port_getn((int)port, list, (uint_t)max, &n, NULL) == -1) {
16161 + throwUnixException(env, errno);
16163 + return (jint)n;
16165 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/classes/java/lang/ProcessImpl.java jdk21u-jdk-21.0.4-ga/src/java.base/unix/classes/java/lang/ProcessImpl.java
16166 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/classes/java/lang/ProcessImpl.java 2024-07-09 10:07:16.000000000 +0200
16167 +++ jdk21u-jdk-21.0.4-ga/src/java.base/unix/classes/java/lang/ProcessImpl.java 2024-08-17 19:13:01.401435641 +0200
16168 @@ -83,6 +83,9 @@
16169 private /* final */ InputStream stdout;
16170 private /* final */ InputStream stderr;
16172 + // only used on Solaris
16173 + private /* final */ DeferredCloseInputStream stdout_inner_stream;
16175 private static enum LaunchMechanism {
16176 // order IS important!
16177 FORK,
16178 @@ -108,6 +111,7 @@
16179 return lm; // All options are valid for Linux
16180 case AIX:
16181 case MACOS:
16182 + case SOLARIS:
16183 if (lm != LaunchMechanism.VFORK) {
16184 return lm; // All but VFORK are valid
16186 @@ -364,6 +368,44 @@
16188 break;
16190 + case SOLARIS:
16191 + stdin = (fds[0] == -1) ?
16192 + ProcessBuilder.NullOutputStream.INSTANCE :
16193 + new BufferedOutputStream(
16194 + new FileOutputStream(newFileDescriptor(fds[0])));
16196 + stdout = (fds[1] == -1 || forceNullOutputStream) ?
16197 + ProcessBuilder.NullInputStream.INSTANCE :
16198 + new BufferedInputStream(
16199 + stdout_inner_stream =
16200 + new DeferredCloseInputStream(
16201 + newFileDescriptor(fds[1])));
16203 + stderr = (fds[2] == -1) ?
16204 + ProcessBuilder.NullInputStream.INSTANCE :
16205 + new DeferredCloseInputStream(newFileDescriptor(fds[2]));
16207 + /*
16208 + * For each subprocess forked a corresponding reaper task
16209 + * is submitted. That task is the only thread which waits
16210 + * for the subprocess to terminate and it doesn't hold any
16211 + * locks while doing so. This design allows waitFor() and
16212 + * exitStatus() to be safely executed in parallel (and they
16213 + * need no native code).
16214 + */
16215 + ProcessHandleImpl.completion(pid, true).handle((exitcode, throwable) -> {
16216 + lock.lock();
16217 + try {
16218 + this.exitcode = (exitcode == null) ? -1 : exitcode.intValue();
16219 + this.hasExited = true;
16220 + condition.signalAll();
16221 + } finally {
16222 + lock.unlock();
16224 + return null;
16225 + });
16226 + break;
16228 case AIX:
16229 stdin = (fds[0] == -1) ?
16230 ProcessBuilder.NullOutputStream.INSTANCE :
16231 @@ -480,6 +522,32 @@
16232 try { stderr.close(); } catch (IOException ignored) {}
16233 break;
16235 + case SOLARIS:
16236 + // There is a risk that pid will be recycled, causing us to
16237 + // kill the wrong process! So we only terminate processes
16238 + // that appear to still be running. Even with this check,
16239 + // there is an unavoidable race condition here, but the window
16240 + // is very small, and OSes try hard to not recycle pids too
16241 + // soon, so this is quite safe.
16242 + lock.lock();
16243 + try {
16244 + if (!hasExited)
16245 + processHandle.destroyProcess(force);
16246 + } finally {
16247 + lock.unlock();
16249 + try {
16250 + stdin.close();
16251 + if (stdout_inner_stream != null)
16252 + stdout_inner_stream.closeDeferred(stdout);
16253 + if (stderr instanceof DeferredCloseInputStream)
16254 + ((DeferredCloseInputStream) stderr)
16255 + .closeDeferred(stderr);
16256 + } catch (IOException e) {
16257 + // ignore
16259 + break;
16261 default: throw new AssertionError("Unsupported platform: " + OperatingSystem.current());
16264 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/classes/sun/net/PortConfig.java jdk21u-jdk-21.0.4-ga/src/java.base/unix/classes/sun/net/PortConfig.java
16265 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/classes/sun/net/PortConfig.java 2024-07-09 10:07:16.000000000 +0200
16266 +++ jdk21u-jdk-21.0.4-ga/src/java.base/unix/classes/sun/net/PortConfig.java 2024-08-17 19:13:01.401922055 +0200
16267 @@ -47,6 +47,10 @@
16268 defaultLower = 32768;
16269 defaultUpper = 61000;
16270 break;
16271 + case SOLARIS:
16272 + defaultLower = 32768;
16273 + defaultUpper = 65535;
16274 + break;
16275 case MACOS:
16276 defaultLower = 49152;
16277 defaultUpper = 65535;
16278 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/classes/sun/nio/fs/UnixConstants.java.template jdk21u-jdk-21.0.4-ga/src/java.base/unix/classes/sun/nio/fs/UnixConstants.java.template
16279 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/classes/sun/nio/fs/UnixConstants.java.template 2024-07-09 10:07:16.000000000 +0200
16280 +++ jdk21u-jdk-21.0.4-ga/src/java.base/unix/classes/sun/nio/fs/UnixConstants.java.template 2024-08-17 19:13:01.402429300 +0200
16281 @@ -35,6 +35,10 @@
16282 #include <sys/clonefile.h>
16283 #endif
16285 +/* On Solaris, "sun" is defined as a macro. Undefine to make package
16286 + declaration valid */
16287 +#undef sun
16289 /* To be able to name the Java constants the same as the C constants without
16290 having the preprocessor rewrite those identifiers, add PREFIX_ to all
16291 identifiers matching a C constant. The PREFIX_ is filtered out in the
16292 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java jdk21u-jdk-21.0.4-ga/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java
16293 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java 2024-07-09 10:07:16.000000000 +0200
16294 +++ jdk21u-jdk-21.0.4-ga/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java 2024-08-17 19:13:01.403080966 +0200
16295 @@ -127,6 +127,10 @@
16296 return rootDirectory;
16299 + boolean isSolaris() {
16300 + return false;
16303 static List<String> standardFileAttributeViews() {
16304 return Arrays.asList("basic", "posix", "unix", "owner");
16306 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/classes/sun/nio/fs/UnixPath.java jdk21u-jdk-21.0.4-ga/src/java.base/unix/classes/sun/nio/fs/UnixPath.java
16307 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/classes/sun/nio/fs/UnixPath.java 2024-07-09 10:07:16.000000000 +0200
16308 +++ jdk21u-jdk-21.0.4-ga/src/java.base/unix/classes/sun/nio/fs/UnixPath.java 2024-08-17 19:13:01.403673567 +0200
16309 @@ -779,7 +779,15 @@
16310 ("NOFOLLOW_LINKS is not supported on this platform");
16311 flags |= O_NOFOLLOW;
16313 - return open(this, flags, 0);
16314 + try {
16315 + return open(this, flags, 0);
16316 + } catch (UnixException x) {
16317 + // HACK: EINVAL instead of ELOOP on Solaris 10 prior to u4 (see 6460380)
16318 + if (getFileSystem().isSolaris() && x.errno() == EINVAL)
16319 + x.setError(ELOOP);
16321 + throw x;
16325 void checkRead() {
16326 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/classes/sun/security/provider/NativePRNG.java jdk21u-jdk-21.0.4-ga/src/java.base/unix/classes/sun/security/provider/NativePRNG.java
16327 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/classes/sun/security/provider/NativePRNG.java 2024-07-09 10:07:16.000000000 +0200
16328 +++ jdk21u-jdk-21.0.4-ga/src/java.base/unix/classes/sun/security/provider/NativePRNG.java 2024-08-17 19:13:01.404288591 +0200
16329 @@ -33,7 +33,7 @@
16330 import sun.security.util.Debug;
16333 - * Native PRNG implementation for Linux/MacOS.
16334 + * Native PRNG implementation for Solaris/Linux/MacOS.
16335 * <p>
16336 * It obtains seed and random numbers by reading system files such as
16337 * the special device files /dev/random and /dev/urandom. This
16338 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libjava/io_util_md.c jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libjava/io_util_md.c
16339 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libjava/io_util_md.c 2024-07-09 10:07:16.000000000 +0200
16340 +++ jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libjava/io_util_md.c 2024-08-17 19:13:01.408010486 +0200
16341 @@ -30,6 +30,10 @@
16342 #include <string.h>
16343 #include <unistd.h>
16345 +#ifdef __solaris__
16346 +#include <sys/filio.h>
16347 +#endif
16349 #if defined(__linux__) || defined(_ALLBSD_SOURCE) || defined(_AIX)
16350 #include <sys/ioctl.h>
16351 #endif
16352 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libjava/java_props_md.c jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libjava/java_props_md.c
16353 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libjava/java_props_md.c 2024-07-09 10:07:16.000000000 +0200
16354 +++ jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libjava/java_props_md.c 2024-08-17 19:13:01.408518503 +0200
16355 @@ -323,6 +323,27 @@
16357 #endif
16359 +#ifdef __solaris__
16360 + if (strcmp(p,"eucJP") == 0) {
16361 + /* For Solaris use customized vendor defined character
16362 + * customized EUC-JP converter
16363 + */
16364 + *std_encoding = "eucJP-open";
16365 + } else if (strcmp(p, "Big5") == 0 || strcmp(p, "BIG5") == 0) {
16366 + /*
16367 + * Remap the encoding string to Big5_Solaris which augments
16368 + * the default converter for Solaris Big5 locales to include
16369 + * seven additional ideographic characters beyond those included
16370 + * in the Java "Big5" converter.
16371 + */
16372 + *std_encoding = "Big5_Solaris";
16373 + } else if (strcmp(p, "Big5-HKSCS") == 0) {
16374 + /*
16375 + * Solaris uses HKSCS2001
16376 + */
16377 + *std_encoding = "Big5-HKSCS-2001";
16379 +#endif
16380 #ifdef MACOSX
16382 * For the case on MacOS X where encoding is set to US-ASCII, but we
16383 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libjava/jlong_md.h jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libjava/jlong_md.h
16384 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libjava/jlong_md.h 2024-07-09 10:07:16.000000000 +0200
16385 +++ jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libjava/jlong_md.h 2024-08-17 19:13:01.408962344 +0200
16386 @@ -23,8 +23,8 @@
16387 * questions.
16390 -#ifndef _UNIX_JLONG_MD_H_
16391 -#define _UNIX_JLONG_MD_H_
16392 +#ifndef _SOLARIS_JLONG_MD_H_
16393 +#define _SOLARIS_JLONG_MD_H_
16395 /* Make sure ptrdiff_t is defined */
16396 #include <stddef.h>
16397 @@ -97,4 +97,4 @@
16398 #define size_to_jlong(a) ((jlong)(a))
16399 #define long_to_jlong(a) ((jlong)(a))
16401 -#endif /* !_UNIX_JLONG_MD_H_ */
16402 +#endif /* !_SOLARIS_JLONG_MD_H_ */
16403 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c
16404 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c 2024-07-09 10:07:16.000000000 +0200
16405 +++ jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c 2024-08-17 19:13:01.405190683 +0200
16406 @@ -45,10 +45,20 @@
16407 #include <sys/stat.h>
16408 #include <sys/wait.h>
16410 +/* For POSIX-compliant getpwuid_r on Solaris */
16411 +#if defined(__solaris__)
16412 +#define _POSIX_PTHREAD_SEMANTICS
16413 +#endif
16414 #include <pwd.h>
16416 +#ifdef _AIX
16417 +#include <sys/procfs.h>
16418 +#endif
16419 +#ifdef __solaris__
16420 +#include <procfs.h>
16421 +#endif
16423 #if defined(_AIX)
16424 - #include <sys/procfs.h>
16425 #define DIR DIR64
16426 #define dirent dirent64
16427 #define opendir opendir64
16428 @@ -128,13 +138,18 @@
16429 #define WTERMSIG(status) ((status)&0x7F)
16430 #endif
16432 +#ifdef __solaris__
16433 /* The child exited because of a signal.
16434 * The best value to return is 0x80 + signal number,
16435 * because that is what all Unix shells do, and because
16436 * it allows callers to distinguish between process exit and
16437 * process death by signal.
16438 - */
16439 + * Unfortunately, the historical behavior on Solaris is to return
16440 + * the signal number, and we preserve this for compatibility. */
16441 +#define WTERMSIG_RETURN(status) WTERMSIG(status)
16442 +#else
16443 #define WTERMSIG_RETURN(status) (WTERMSIG(status) + 0x80)
16444 +#endif
16446 #define RESTARTABLE(_cmd, _result) do { \
16447 do { \
16448 @@ -488,7 +503,7 @@
16449 * The following functions are for Linux
16452 -#if defined (__linux__)
16453 +#if defined(__solaris__) || defined (__linux__)
16456 * Return pids of active processes, and optionally parent pids and
16457 @@ -617,13 +632,13 @@
16458 return count;
16461 -#endif // defined (__linux__)
16462 +#endif // defined(__solaris__) || defined (__linux__)
16465 - * The following functions are for AIX.
16466 + * The following functions are common on Solaris and AIX.
16469 -#if defined(_AIX)
16470 +#if defined(__solaris__) || defined(_AIX)
16473 * Helper function to get the 'psinfo_t' data from "/proc/%d/psinfo".
16474 @@ -687,6 +702,19 @@
16475 int ret;
16478 + * On Solaris, the full path to the executable command is the link in
16479 + * /proc/<pid>/paths/a.out. But it is only readable for processes we own.
16480 + */
16481 +#if defined(__solaris__)
16482 + snprintf(fn, sizeof fn, "/proc/%d/path/a.out", pid);
16483 + if ((ret = readlink(fn, exePath, PATH_MAX - 1)) > 0) {
16484 + // null terminate and create String to store for command
16485 + exePath[ret] = '\0';
16486 + CHECK_NULL(cmdexe = JNU_NewStringPlatform(env, exePath));
16488 +#endif
16490 + /*
16491 * Now try to open /proc/%d/psinfo
16493 if (getPsinfo(pid, &psinfo) < 0) {
16494 @@ -715,4 +743,4 @@
16495 prargs[0] == '\0' ? NULL : prargs);
16498 -#endif // defined(_AIX)
16499 +#endif // defined(__solaris__) || defined(_AIX)
16500 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.h jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.h
16501 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.h 2024-07-09 10:07:16.000000000 +0200
16502 +++ jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.h 2024-08-17 19:13:01.405593469 +0200
16503 @@ -29,7 +29,7 @@
16504 * Declaration of ProcessHandleImpl functions common on all Unix platforms.
16505 * 'unix_' functions have a single implementation in ProcessHandleImpl_unix.c
16506 * 'os_' prefixed functions have different, os-specific implementations in the
16507 - * various ProcessHandleImpl_{linux,macosx,aix}.c files.
16508 + * various ProcessHandleImpl_{linux,macosx,solaris,aix}.c files.
16509 * See ProcessHandleImpl_unix.c for more details.
16512 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libjava/ProcessImpl_md.c jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libjava/ProcessImpl_md.c
16513 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libjava/ProcessImpl_md.c 2024-07-09 10:07:16.000000000 +0200
16514 +++ jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libjava/ProcessImpl_md.c 2024-08-17 19:13:01.406217471 +0200
16515 @@ -230,7 +230,14 @@
16516 static const char*
16517 defaultPath(void)
16519 - return ":/bin:/usr/bin";
16520 +#ifdef __solaris__
16521 + /* These really are the Solaris defaults! */
16522 + return (geteuid() == 0 || getuid() == 0) ?
16523 + "/usr/xpg4/bin:/usr/bin:/opt/SUNWspro/bin:/usr/sbin" :
16524 + "/usr/xpg4/bin:/usr/bin:/opt/SUNWspro/bin:";
16525 +#else
16526 + return ":/bin:/usr/bin"; /* glibc */
16527 +#endif
16530 static const char*
16531 @@ -447,7 +454,7 @@
16532 #endif
16534 /* vfork(2) is deprecated on Darwin */
16535 -#ifndef __APPLE__
16536 +#ifndef __solaris__
16537 static pid_t
16538 vforkChild(ChildStuff *c) {
16539 volatile pid_t resultPid;
16540 @@ -602,7 +609,7 @@
16541 startChild(JNIEnv *env, jobject process, ChildStuff *c, const char *helperpath) {
16542 switch (c->mode) {
16543 /* vfork(2) is deprecated on Darwin*/
16544 - #ifndef __APPLE__
16545 + #ifndef __solaris__
16546 case MODE_VFORK:
16547 return vforkChild(c);
16548 #endif
16549 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libjava/TimeZone_md.c jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libjava/TimeZone_md.c
16550 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libjava/TimeZone_md.c 2024-07-09 10:07:16.000000000 +0200
16551 +++ jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libjava/TimeZone_md.c 2024-08-17 19:13:01.407111138 +0200
16552 @@ -35,6 +35,9 @@
16553 #include <string.h>
16554 #include <dirent.h>
16555 #include <unistd.h>
16556 +#if defined(__solaris__)
16557 +#include <libscf.h>
16558 +#endif
16560 #include "jvm.h"
16561 #include "TimeZone_md.h"
16562 @@ -50,9 +53,11 @@
16563 } while((_result == -1) && (errno == EINTR)); \
16564 } while(0)
16566 +#if !defined(__solaris__) || defined(__sparcv9) || defined(amd64)
16567 #define fileopen fopen
16568 #define filegets fgets
16569 #define fileclose fclose
16570 +#endif
16572 #if defined(_ALLBSD_SOURCE)
16573 #define stat64 stat
16574 @@ -76,7 +81,7 @@
16575 static const char *ETC_ENVIRONMENT_FILE = "/etc/environment";
16576 #endif
16578 -#if defined(__linux__) || defined(MACOSX)
16579 +#if defined(__linux__) || defined(MACOSX) || defined(__solaris__)
16582 * remove repeated path separators ('/') in the given 'path'.
16583 @@ -186,6 +191,13 @@
16585 if ((strcmp(dp->d_name, "ROC") == 0)
16586 || (strcmp(dp->d_name, "posixrules") == 0)
16587 +#if defined(__solaris__)
16588 + /*
16589 + * Skip the "src" and "tab" directories on Solaris.
16590 + */
16591 + || (strcmp(dp->d_name, "src") == 0)
16592 + || (strcmp(dp->d_name, "tab") == 0)
16593 +#endif
16594 || (strcmp(dp->d_name, "localtime") == 0)) {
16595 continue;
16597 @@ -257,6 +269,8 @@
16598 return possibleMatch;
16601 +#if defined(__linux__) || defined(MACOSX)
16604 * Performs Linux specific mapping and returns a zone ID
16605 * if found. Otherwise, NULL is returned.
16606 @@ -368,6 +382,183 @@
16607 return tz;
16610 +#elif defined(__solaris__)
16613 + * Performs Solaris dependent mapping. Returns a zone ID if
16614 + * found. Otherwise, NULL is returned. Solaris libc looks up
16615 + * "/etc/default/init" to get the default TZ value if TZ is not defined
16616 + * as an environment variable.
16617 + */
16618 +static char *
16619 +getPlatformTimeZoneID()
16621 + char *tz = NULL;
16622 + FILE *fp;
16624 + /*
16625 + * Try the TZ entry in /etc/default/init.
16626 + */
16627 + if ((fp = fileopen(SYS_INIT_FILE, "r")) != NULL) {
16628 + char line[256];
16629 + char quote = '\0';
16631 + while (filegets(line, sizeof(line), fp) != NULL) {
16632 + char *p = line;
16633 + char *s;
16634 + char c;
16636 + /* quick check for comment lines */
16637 + if (*p == '#') {
16638 + continue;
16640 + if (strncmp(p, "TZ=", 3) == 0) {
16641 + p += 3;
16642 + SKIP_SPACE(p);
16643 + c = *p;
16644 + if (c == '"' || c == '\'') {
16645 + quote = c;
16646 + p++;
16649 + /*
16650 + * PSARC/2001/383: quoted string support
16651 + */
16652 + for (s = p; (c = *s) != '\0' && c != '\n'; s++) {
16653 + /* No '\\' is supported here. */
16654 + if (c == quote) {
16655 + quote = '\0';
16656 + break;
16658 + if (c == ' ' && quote == '\0') {
16659 + break;
16662 + if (quote != '\0') {
16663 + jio_fprintf(stderr, "ZoneInfo: unterminated time zone name in /etc/TIMEZONE\n");
16665 + *s = '\0';
16666 + tz = strdup(p);
16667 + break;
16670 + (void) fileclose(fp);
16672 + return tz;
16675 +#define TIMEZONE_FMRI "svc:/system/timezone:default"
16676 +#define TIMEZONE_PG "timezone"
16677 +#define LOCALTIME_PROP "localtime"
16679 +static void
16680 +cleanupScf(scf_handle_t *h,
16681 + scf_snapshot_t *snap,
16682 + scf_instance_t *inst,
16683 + scf_propertygroup_t *pg,
16684 + scf_property_t *prop,
16685 + scf_value_t *val,
16686 + char *buf) {
16687 + if (buf != NULL) {
16688 + free(buf);
16690 + if (snap != NULL) {
16691 + scf_snapshot_destroy(snap);
16693 + if (val != NULL) {
16694 + scf_value_destroy(val);
16696 + if (prop != NULL) {
16697 + scf_property_destroy(prop);
16699 + if (pg != NULL) {
16700 + scf_pg_destroy(pg);
16702 + if (inst != NULL) {
16703 + scf_instance_destroy(inst);
16705 + if (h != NULL) {
16706 + scf_handle_destroy(h);
16711 + * Returns a zone ID of Solaris when the TZ value is "localtime".
16712 + * First, it tries scf. If scf fails, it looks for the same file as
16713 + * /usr/share/lib/zoneinfo/localtime under /usr/share/lib/zoneinfo/.
16714 + */
16715 +static char *
16716 +getSolarisDefaultZoneID() {
16717 + char *tz = NULL;
16718 + struct stat64 statbuf;
16719 + size_t size;
16720 + char *buf;
16721 + int fd;
16722 + int res;
16723 + /* scf specific variables */
16724 + scf_handle_t *h = NULL;
16725 + scf_snapshot_t *snap = NULL;
16726 + scf_instance_t *inst = NULL;
16727 + scf_propertygroup_t *pg = NULL;
16728 + scf_property_t *prop = NULL;
16729 + scf_value_t *val = NULL;
16731 + if ((h = scf_handle_create(SCF_VERSION)) != NULL
16732 + && scf_handle_bind(h) == 0
16733 + && (inst = scf_instance_create(h)) != NULL
16734 + && (snap = scf_snapshot_create(h)) != NULL
16735 + && (pg = scf_pg_create(h)) != NULL
16736 + && (prop = scf_property_create(h)) != NULL
16737 + && (val = scf_value_create(h)) != NULL
16738 + && scf_handle_decode_fmri(h, TIMEZONE_FMRI, NULL, NULL, inst,
16739 + NULL, NULL, SCF_DECODE_FMRI_REQUIRE_INSTANCE) == 0
16740 + && scf_instance_get_snapshot(inst, "running", snap) == 0
16741 + && scf_instance_get_pg_composed(inst, snap, TIMEZONE_PG, pg) == 0
16742 + && scf_pg_get_property(pg, LOCALTIME_PROP, prop) == 0
16743 + && scf_property_get_value(prop, val) == 0) {
16744 + ssize_t len;
16746 + /* Gets the length of the zone ID string */
16747 + len = scf_value_get_astring(val, NULL, 0);
16748 + if (len != -1) {
16749 + tz = malloc(++len); /* +1 for a null byte */
16750 + if (tz != NULL && scf_value_get_astring(val, tz, len) != -1) {
16751 + cleanupScf(h, snap, inst, pg, prop, val, NULL);
16752 + return tz;
16756 + cleanupScf(h, snap, inst, pg, prop, val, tz);
16758 + RESTARTABLE(stat64(DEFAULT_ZONEINFO_FILE, &statbuf), res);
16759 + if (res == -1) {
16760 + return NULL;
16762 + size = (size_t) statbuf.st_size;
16763 + buf = malloc(size);
16764 + if (buf == NULL) {
16765 + return NULL;
16767 + RESTARTABLE(open(DEFAULT_ZONEINFO_FILE, O_RDONLY), fd);
16768 + if (fd == -1) {
16769 + free((void *) buf);
16770 + return NULL;
16773 + RESTARTABLE(read(fd, buf, size), res);
16774 + if (res != (ssize_t) size) {
16775 + (void) close(fd);
16776 + free((void *) buf);
16777 + return NULL;
16779 + (void) close(fd);
16780 + tz = findZoneinfoFile(buf, size, ZONEINFO_DIR);
16781 + free((void *) buf);
16782 + return tz;
16785 +#endif /* defined(__solaris__) */
16787 #elif defined(_AIX)
16789 static char *
16790 @@ -533,6 +724,15 @@
16791 free((void *) freetz);
16793 #else
16794 +#if defined(__solaris__)
16795 + /* Solaris might use localtime, so handle it here. */
16796 + if (strcmp(tz, "localtime") == 0) {
16797 + javatz = getSolarisDefaultZoneID();
16798 + if (freetz != NULL) {
16799 + free((void *) freetz);
16801 + } else
16802 +#endif
16803 if (freetz == NULL) {
16804 /* strdup if we are still working on getenv result. */
16805 javatz = strdup(tz);
16806 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libjava/UnixFileSystem_md.c jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libjava/UnixFileSystem_md.c
16807 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libjava/UnixFileSystem_md.c 2024-07-09 10:07:16.000000000 +0200
16808 +++ jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libjava/UnixFileSystem_md.c 2024-08-17 19:13:01.407581564 +0200
16809 @@ -63,6 +63,10 @@
16810 #define stat stat64
16811 #endif
16813 +#if defined(__solaris__) && !defined(NAME_MAX)
16814 + #define NAME_MAX MAXNAMLEN
16815 +#endif
16817 #if defined(_ALLBSD_SOURCE)
16818 #ifndef MACOSX
16819 #define statvfs64 statvfs
16820 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libjsig/jsig.c jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libjsig/jsig.c
16821 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libjsig/jsig.c 2024-07-09 10:07:16.000000000 +0200
16822 +++ jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libjsig/jsig.c 2024-08-17 19:13:01.409800505 +0200
16823 @@ -35,6 +35,16 @@
16825 #include "jni.h"
16827 +#ifdef SOLARIS
16828 +/* Our redeclarations of the system functions must not have a less
16829 + * restrictive linker scoping, so we have to declare them as JNIEXPORT
16830 + * before including signal.h */
16831 +#include "sys/signal.h"
16832 +JNIEXPORT void (*signal(int sig, void (*disp)(int)))(int);
16833 +JNIEXPORT void (*sigset(int sig, void (*disp)(int)))(int);
16834 +JNIEXPORT int sigaction(int sig, const struct sigaction *act, struct sigaction *oact);
16835 +#endif
16837 #include <dlfcn.h>
16838 #include <errno.h>
16839 #include <pthread.h>
16840 @@ -51,9 +61,16 @@
16841 #define false 0
16842 #endif
16844 +#ifdef SOLARIS
16845 +#define MAX_SIGNALS (SIGRTMAX+1)
16847 +/* On solaris, MAX_SIGNALS is a macro, not a constant, so we must allocate sact dynamically. */
16848 +static struct sigaction *sact = (struct sigaction *)NULL; /* saved signal handlers */
16849 +#else
16850 #define MAX_SIGNALS NSIG
16852 static struct sigaction sact[MAX_SIGNALS]; /* saved signal handlers */
16853 +#endif
16855 static sigset_t jvmsigs; /* Signals used by jvm. */
16857 @@ -78,6 +95,20 @@
16858 static bool jvm_signal_installed = false;
16861 +/* assume called within signal_lock */
16862 +static void allocate_sact() {
16863 +#ifdef SOLARIS
16864 + if (sact == NULL) {
16865 + sact = (struct sigaction *)malloc((MAX_SIGNALS) * (size_t)sizeof(struct sigaction));
16866 + if (sact == NULL) {
16867 + printf("%s\n", "libjsig.so unable to allocate memory");
16868 + exit(0);
16870 + memset(sact, 0, (MAX_SIGNALS) * (size_t)sizeof(struct sigaction));
16872 +#endif
16875 static void signal_lock() {
16876 pthread_mutex_lock(&mutex);
16877 /* When the jvm is installing its set of signal handlers, threads
16878 @@ -137,7 +168,18 @@
16879 sact[sig].sa_handler = disp;
16880 sigemptyset(&set);
16881 sact[sig].sa_mask = set;
16882 - sact[sig].sa_flags = 0;
16883 + if (!is_sigset) {
16884 +#ifdef SOLARIS
16885 + sact[sig].sa_flags = SA_NODEFER;
16886 + if (sig != SIGILL && sig != SIGTRAP && sig != SIGPWR) {
16887 + sact[sig].sa_flags |= SA_RESETHAND;
16889 +#else
16890 + sact[sig].sa_flags = 0;
16891 +#endif
16892 + } else {
16893 + sact[sig].sa_flags = 0;
16897 static sa_handler_t set_signal(int sig, sa_handler_t disp, bool is_sigset) {
16898 @@ -146,6 +188,7 @@
16899 bool sigblocked;
16901 signal_lock();
16902 + allocate_sact();
16904 sigused = sigismember(&jvmsigs, sig);
16905 if (jvm_signal_installed && sigused) {
16906 @@ -157,6 +200,13 @@
16907 oldhandler = sact[sig].sa_handler;
16908 save_signal_handler(sig, disp, is_sigset);
16910 +#ifdef SOLARIS
16911 + if (is_sigset && sigblocked) {
16912 + /* We won't honor the SIG_HOLD request to change the signal mask */
16913 + oldhandler = SIG_HOLD;
16915 +#endif
16917 signal_unlock();
16918 return oldhandler;
16919 } else if (jvm_signal_installing) {
16920 @@ -234,6 +284,7 @@
16922 signal_lock();
16924 + allocate_sact();
16925 sigused = sigismember(&jvmsigs, sig);
16926 if (jvm_signal_installed && sigused) {
16927 /* jvm has installed its signal handler for this signal. */
16928 @@ -300,6 +351,7 @@
16931 JNIEXPORT struct sigaction *JVM_get_signal_action(int sig) {
16932 + allocate_sact();
16933 /* Does race condition make sense here? */
16934 if (sigismember(&jvmsigs, sig)) {
16935 return &sact[sig];
16936 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libnet/Inet4AddressImpl.c jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libnet/Inet4AddressImpl.c
16937 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libnet/Inet4AddressImpl.c 2024-07-09 10:07:16.000000000 +0200
16938 +++ jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libnet/Inet4AddressImpl.c 2024-08-17 19:13:01.410316202 +0200
16939 @@ -66,8 +66,27 @@
16940 if (gethostname(hostname, sizeof(hostname)) != 0) {
16941 strcpy(hostname, "localhost");
16942 } else {
16943 +#if defined(__solaris__)
16944 + // try to resolve hostname via nameservice
16945 + // if it is known but getnameinfo fails, hostname will still be the
16946 + // value from gethostname
16947 + struct addrinfo hints, *res;
16949 // make sure string is null-terminated
16950 hostname[NI_MAXHOST] = '\0';
16951 + memset(&hints, 0, sizeof(hints));
16952 + hints.ai_flags = AI_CANONNAME;
16953 + hints.ai_family = AF_INET;
16955 + if (getaddrinfo(hostname, NULL, &hints, &res) == 0) {
16956 + getnameinfo(res->ai_addr, res->ai_addrlen, hostname, sizeof(hostname),
16957 + NULL, 0, NI_NAMEREQD);
16958 + freeaddrinfo(res);
16960 +#else
16961 + // make sure string is null-terminated
16962 + hostname[NI_MAXHOST] = '\0';
16963 +#endif
16965 return (*env)->NewStringUTF(env, hostname);
16967 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libnet/Inet6AddressImpl.c jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libnet/Inet6AddressImpl.c
16968 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libnet/Inet6AddressImpl.c 2024-07-09 10:07:16.000000000 +0200
16969 +++ jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libnet/Inet6AddressImpl.c 2024-08-17 19:13:01.410877624 +0200
16970 @@ -67,8 +67,27 @@
16971 if (gethostname(hostname, sizeof(hostname)) != 0) {
16972 strcpy(hostname, "localhost");
16973 } else {
16974 +#if defined(__solaris__)
16975 + // try to resolve hostname via nameservice
16976 + // if it is known but getnameinfo fails, hostname will still be the
16977 + // value from gethostname
16978 + struct addrinfo hints, *res;
16980 // make sure string is null-terminated
16981 hostname[NI_MAXHOST] = '\0';
16982 + memset(&hints, 0, sizeof(hints));
16983 + hints.ai_flags = AI_CANONNAME;
16984 + hints.ai_family = AF_UNSPEC;
16986 + if (getaddrinfo(hostname, NULL, &hints, &res) == 0) {
16987 + getnameinfo(res->ai_addr, res->ai_addrlen, hostname, sizeof(hostname),
16988 + NULL, 0, NI_NAMEREQD);
16989 + freeaddrinfo(res);
16991 +#else
16992 + // make sure string is null-terminated
16993 + hostname[NI_MAXHOST] = '\0';
16994 +#endif
16996 return (*env)->NewStringUTF(env, hostname);
16998 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libnet/net_util_md.c jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libnet/net_util_md.c
16999 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libnet/net_util_md.c 2024-07-09 10:07:16.000000000 +0200
17000 +++ jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libnet/net_util_md.c 2024-08-17 19:13:01.413404982 +0200
17001 @@ -37,6 +37,14 @@
17002 #include <sys/utsname.h>
17003 #endif
17005 +#if defined(__solaris__)
17006 +#include <inet/nd.h>
17007 +#include <limits.h>
17008 +#include <stropts.h>
17009 +#include <sys/filio.h>
17010 +#include <sys/sockio.h>
17011 +#endif
17013 #if defined(MACOSX)
17014 #include <sys/sysctl.h>
17015 #endif
17016 @@ -51,6 +59,20 @@
17017 #define IPV6_FLOWINFO_SEND 33
17018 #endif
17020 +#if defined(__solaris__) && !defined(MAXINT)
17021 +#define MAXINT INT_MAX
17022 +#endif
17025 + * EXCLBIND socket options only on Solaris
17026 + */
17027 +#if defined(__solaris__) && !defined(TCP_EXCLBIND)
17028 +#define TCP_EXCLBIND 0x21
17029 +#endif
17030 +#if defined(__solaris__) && !defined(UDP_EXCLBIND)
17031 +#define UDP_EXCLBIND 0x0101
17032 +#endif
17034 #define RESTARTABLE(_cmd, _result) do { \
17035 do { \
17036 _result = _cmd; \
17037 @@ -63,6 +85,94 @@
17038 return result;
17041 +#ifdef __solaris__
17042 +static int init_tcp_max_buf, init_udp_max_buf;
17043 +static int tcp_max_buf;
17044 +static int udp_max_buf;
17045 +static int useExclBind = 0;
17048 + * Get the specified parameter from the specified driver. The value
17049 + * of the parameter is assumed to be an 'int'. If the parameter
17050 + * cannot be obtained return -1
17051 + */
17052 +int net_getParam(char *driver, char *param)
17054 + struct strioctl stri;
17055 + char buf [64];
17056 + int s;
17057 + int value;
17059 + s = open (driver, O_RDWR);
17060 + if (s < 0) {
17061 + return -1;
17063 + strncpy (buf, param, sizeof(buf));
17064 + stri.ic_cmd = ND_GET;
17065 + stri.ic_timout = 0;
17066 + stri.ic_dp = buf;
17067 + stri.ic_len = sizeof(buf);
17068 + if (ioctl (s, I_STR, &stri) < 0) {
17069 + value = -1;
17070 + } else {
17071 + value = atoi(buf);
17073 + close (s);
17074 + return value;
17078 + * Iterative way to find the max value that SO_SNDBUF or SO_RCVBUF
17079 + * for Solaris versions that do not support the ioctl() in net_getParam().
17080 + * Ugly, but only called once (for each sotype).
17082 + * As an optimization, we make a guess using the default values for Solaris
17083 + * assuming they haven't been modified with ndd.
17084 + */
17086 +#define MAX_TCP_GUESS 1024 * 1024
17087 +#define MAX_UDP_GUESS 2 * 1024 * 1024
17089 +#define FAIL_IF_NOT_ENOBUFS if (errno != ENOBUFS) return -1
17091 +static int findMaxBuf(int fd, int opt, int sotype) {
17092 + int a = 0;
17093 + int b = MAXINT;
17094 + int initial_guess;
17095 + int limit = -1;
17097 + if (sotype == SOCK_DGRAM) {
17098 + initial_guess = MAX_UDP_GUESS;
17099 + } else {
17100 + initial_guess = MAX_TCP_GUESS;
17103 + if (setsockopt(fd, SOL_SOCKET, opt, &initial_guess, sizeof(int)) == 0) {
17104 + initial_guess++;
17105 + if (setsockopt(fd, SOL_SOCKET, opt, &initial_guess,sizeof(int)) < 0) {
17106 + FAIL_IF_NOT_ENOBUFS;
17107 + return initial_guess - 1;
17109 + a = initial_guess;
17110 + } else {
17111 + FAIL_IF_NOT_ENOBUFS;
17112 + b = initial_guess - 1;
17114 + do {
17115 + int mid = a + (b-a)/2;
17116 + if (setsockopt(fd, SOL_SOCKET, opt, &mid, sizeof(int)) == 0) {
17117 + limit = mid;
17118 + a = mid + 1;
17119 + } else {
17120 + FAIL_IF_NOT_ENOBUFS;
17121 + b = mid - 1;
17123 + } while (b >= a);
17125 + return limit;
17127 +#endif
17129 void
17130 NET_ThrowByNameWithLastError(JNIEnv *env, const char *name,
17131 const char *defaultDetail) {
17132 @@ -146,6 +256,50 @@
17134 #endif
17136 + /**
17137 + * On Solaris 8 it's possible to create INET6 sockets even
17138 + * though IPv6 is not enabled on all interfaces. Thus we
17139 + * query the number of IPv6 addresses to verify that IPv6
17140 + * has been configured on at least one interface.
17142 + * On Linux it doesn't matter - if IPv6 is built-in the
17143 + * kernel then IPv6 addresses will be bound automatically
17144 + * to all interfaces.
17145 + */
17146 +#ifdef __solaris__
17148 +#ifdef SIOCGLIFNUM
17150 + struct lifnum numifs;
17152 + numifs.lifn_family = AF_INET6;
17153 + numifs.lifn_flags = 0;
17154 + if (ioctl(fd, SIOCGLIFNUM, (char *)&numifs) < 0) {
17155 + /**
17156 + * SIOCGLIFNUM failed - assume IPv6 not configured
17157 + */
17158 + close(fd);
17159 + return JNI_FALSE;
17161 + /**
17162 + * If no IPv6 addresses then return false. If count > 0
17163 + * it's possible that all IPv6 addresses are "down" but
17164 + * that's okay as they may be brought "up" while the
17165 + * VM is running.
17166 + */
17167 + if (numifs.lifn_count == 0) {
17168 + close(fd);
17169 + return JNI_FALSE;
17172 +#else
17173 + /* SIOCGLIFNUM not defined in build environment ??? */
17174 + close(fd);
17175 + return JNI_FALSE;
17176 +#endif
17178 +#endif /* __solaris */
17181 * OK we may have the stack available in the kernel,
17182 * we should also check if the APIs are available.
17183 @@ -210,6 +364,26 @@
17187 +void parseExclusiveBindProperty(JNIEnv *env) {
17188 +#ifdef __solaris__
17189 + jstring s, flagSet;
17190 + jclass iCls;
17191 + jmethodID mid;
17193 + s = (*env)->NewStringUTF(env, "sun.net.useExclusiveBind");
17194 + CHECK_NULL(s);
17195 + iCls = (*env)->FindClass(env, "java/lang/System");
17196 + CHECK_NULL(iCls);
17197 + mid = (*env)->GetStaticMethodID(env, iCls, "getProperty",
17198 + "(Ljava/lang/String;)Ljava/lang/String;");
17199 + CHECK_NULL(mid);
17200 + flagSet = (*env)->CallStaticObjectMethod(env, iCls, mid, s);
17201 + if (flagSet != NULL) {
17202 + useExclBind = 1;
17204 +#endif
17207 JNIEXPORT jint JNICALL
17208 NET_EnableFastTcpLoopback(int fd) {
17209 return 0;
17210 @@ -368,7 +542,7 @@
17211 *level = IPPROTO_IPV6;
17212 *optname = IPV6_MULTICAST_LOOP;
17213 return 0;
17214 -#if defined(MACOSX)
17215 +#if (defined(__solaris__) || defined(MACOSX))
17216 // Map IP_TOS request to IPV6_TCLASS
17217 case java_net_SocketOptions_IP_TOS:
17218 *level = IPPROTO_IPV6;
17219 @@ -517,6 +691,65 @@
17220 *iptos &= (IPTOS_TOS_MASK | IPTOS_PREC_MASK);
17223 + /*
17224 + * SOL_SOCKET/{SO_SNDBUF,SO_RCVBUF} - On Solaris we may need to clamp
17225 + * the value when it exceeds the system limit.
17226 + */
17227 +#ifdef __solaris__
17228 + if (level == SOL_SOCKET) {
17229 + if (opt == SO_SNDBUF || opt == SO_RCVBUF) {
17230 + int sotype=0;
17231 + socklen_t arglen;
17232 + int *bufsize, maxbuf;
17233 + int ret;
17235 + /* Attempt with the original size */
17236 + ret = setsockopt(fd, level, opt, arg, len);
17237 + if ((ret == 0) || (ret == -1 && errno != ENOBUFS))
17238 + return ret;
17240 + /* Exceeded system limit so clamp and retry */
17242 + arglen = sizeof(sotype);
17243 + if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *)&sotype,
17244 + &arglen) < 0) {
17245 + return -1;
17248 + /*
17249 + * We try to get tcp_maxbuf (and udp_max_buf) using
17250 + * an ioctl() that isn't available on all versions of Solaris.
17251 + * If that fails, we use the search algorithm in findMaxBuf()
17252 + */
17253 + if (!init_tcp_max_buf && sotype == SOCK_STREAM) {
17254 + tcp_max_buf = net_getParam("/dev/tcp", "tcp_max_buf");
17255 + if (tcp_max_buf == -1) {
17256 + tcp_max_buf = findMaxBuf(fd, opt, SOCK_STREAM);
17257 + if (tcp_max_buf == -1) {
17258 + return -1;
17261 + init_tcp_max_buf = 1;
17262 + } else if (!init_udp_max_buf && sotype == SOCK_DGRAM) {
17263 + udp_max_buf = net_getParam("/dev/udp", "udp_max_buf");
17264 + if (udp_max_buf == -1) {
17265 + udp_max_buf = findMaxBuf(fd, opt, SOCK_DGRAM);
17266 + if (udp_max_buf == -1) {
17267 + return -1;
17270 + init_udp_max_buf = 1;
17273 + maxbuf = (sotype == SOCK_STREAM) ? tcp_max_buf : udp_max_buf;
17274 + bufsize = (int *)arg;
17275 + if (*bufsize > maxbuf) {
17276 + *bufsize = maxbuf;
17280 +#endif
17282 #ifdef _AIX
17283 if (level == SOL_SOCKET) {
17284 if (opt == SO_SNDBUF || opt == SO_RCVBUF) {
17285 @@ -631,10 +864,20 @@
17287 * Linux allows a socket to bind to 127.0.0.255 which must be
17288 * caught.
17290 + * On Solaris with IPv6 enabled we must use an exclusive
17291 + * bind to guarantee a unique port number across the IPv4 and
17292 + * IPv6 port spaces.
17296 NET_Bind(int fd, SOCKETADDRESS *sa, int len)
17298 +#if defined(__solaris__)
17299 + int level = -1;
17300 + int exclbind = -1;
17301 + int arg, alen;
17302 +#endif
17303 int rv;
17305 #ifdef __linux__
17306 @@ -651,8 +894,61 @@
17308 #endif
17310 +#if defined(__solaris__)
17311 + /*
17312 + * Solaris has separate IPv4 and IPv6 port spaces so we
17313 + * use an exclusive bind when SO_REUSEADDR is not used to
17314 + * give the illusion of a unified port space.
17315 + * This also avoids problems with IPv6 sockets connecting
17316 + * to IPv4 mapped addresses whereby the socket conversion
17317 + * results in a late bind that fails because the
17318 + * corresponding IPv4 port is in use.
17319 + */
17320 + alen = sizeof(arg);
17322 + if (useExclBind ||
17323 + getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&arg, &alen) == 0)
17325 + if (useExclBind || arg == 0) {
17326 + /*
17327 + * SO_REUSEADDR is disabled or sun.net.useExclusiveBind
17328 + * property is true so enable TCP_EXCLBIND or
17329 + * UDP_EXCLBIND
17330 + */
17331 + alen = sizeof(arg);
17332 + if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&arg, &alen) == 0)
17334 + if (arg == SOCK_STREAM) {
17335 + level = IPPROTO_TCP;
17336 + exclbind = TCP_EXCLBIND;
17337 + } else {
17338 + level = IPPROTO_UDP;
17339 + exclbind = UDP_EXCLBIND;
17343 + arg = 1;
17344 + setsockopt(fd, level, exclbind, (char *)&arg, sizeof(arg));
17348 +#endif
17350 rv = bind(fd, &sa->sa, len);
17352 +#if defined(__solaris__)
17353 + if (rv < 0) {
17354 + int en = errno;
17355 + /* Restore *_EXCLBIND if the bind fails */
17356 + if (exclbind != -1) {
17357 + int arg = 0;
17358 + setsockopt(fd, level, exclbind, (char *)&arg,
17359 + sizeof(arg));
17361 + errno = en;
17363 +#endif
17365 return rv;
17368 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libnet/net_util_md.h jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libnet/net_util_md.h
17369 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libnet/net_util_md.h 2024-07-09 10:07:16.000000000 +0200
17370 +++ jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libnet/net_util_md.h 2024-08-17 19:13:01.413871984 +0200
17371 @@ -47,6 +47,8 @@
17372 #ifndef SO_REUSEPORT
17373 #ifdef __linux__
17374 #define SO_REUSEPORT 15
17375 +#elif defined(__solaris__)
17376 +#define SO_REUSEPORT 0x100e
17377 #elif defined(AIX) || defined(MACOSX)
17378 #define SO_REUSEPORT 0x0200
17379 #else
17380 @@ -80,4 +82,8 @@
17381 void NET_ThrowByNameWithLastError(JNIEnv *env, const char *name,
17382 const char *defaultDetail);
17384 +#ifdef __solaris__
17385 +int net_getParam(char *driver, char *param);
17386 +#endif
17388 #endif /* NET_UTILS_MD_H */
17389 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libnet/NetworkInterface.c jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libnet/NetworkInterface.c
17390 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libnet/NetworkInterface.c 2024-07-09 10:07:16.000000000 +0200
17391 +++ jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libnet/NetworkInterface.c 2024-08-17 19:13:01.411920985 +0200
17392 @@ -37,6 +37,12 @@
17393 #include <strings.h>
17394 #endif
17396 +#if defined(__solaris__)
17397 +#include <stropts.h>
17398 +#include <sys/dlpi.h>
17399 +#include <sys/sockio.h>
17400 +#endif
17402 #if defined(_ALLBSD_SOURCE)
17403 #include <net/ethernet.h>
17404 #include <net/if_dl.h>
17405 @@ -49,6 +55,11 @@
17407 #if defined(__linux__)
17408 #define _PATH_PROCNET_IFINET6 "/proc/net/if_inet6"
17409 +#elif defined(__solaris__)
17410 + #ifndef SIOCGLIFHWADDR
17411 + #define SIOCGLIFHWADDR _IOWR('i', 192, struct lifreq)
17412 + #endif
17413 + #define DEV_PREFIX "/dev/"
17414 #endif
17416 #ifdef LIFNAMSIZ
17417 @@ -135,6 +146,11 @@
17418 const struct in_addr *addr, unsigned char *buf);
17419 static int getMTU(JNIEnv *env, int sock, const char *ifname);
17421 +#if defined(__solaris__)
17422 +static int getMacFromDevice(JNIEnv *env, const char *ifname,
17423 + unsigned char *retbuf);
17424 +#endif
17426 /******************* Java entry points *****************************/
17429 @@ -1658,6 +1674,372 @@
17431 #endif /* _AIX */
17433 +/** Solaris **/
17434 +#if defined(__solaris__)
17437 + * Opens a socket for further ioctl calls. Tries AF_INET socket first and
17438 + * if it fails return AF_INET6 socket.
17439 + */
17440 +static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
17441 + int sock, alreadyV6 = 0;
17442 + struct lifreq if2;
17444 + if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
17445 + if (errno == EPROTONOSUPPORT || errno == EAFNOSUPPORT) {
17446 + if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
17447 + JNU_ThrowByNameWithMessageAndLastError
17448 + (env, JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
17449 + return -1;
17451 + alreadyV6 = 1;
17452 + } else { // errno is not NOSUPPORT
17453 + JNU_ThrowByNameWithMessageAndLastError
17454 + (env, JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed");
17455 + return -1;
17459 + // Solaris requires that we have an IPv6 socket to query an interface
17460 + // without an IPv4 address - check it here. POSIX 1 require the kernel to
17461 + // return ENOTTY if the call is inappropriate for a device e.g. the NETMASK
17462 + // for a device having IPv6 only address but not all devices follow the
17463 + // standard so fall back on any error. It's not an ecologically friendly
17464 + // gesture but more reliable.
17465 + if (!alreadyV6) {
17466 + memset((char *)&if2, 0, sizeof(if2));
17467 + strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
17468 + if (ioctl(sock, SIOCGLIFNETMASK, (char *)&if2) < 0) {
17469 + close(sock);
17470 + if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
17471 + JNU_ThrowByNameWithMessageAndLastError
17472 + (env, JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
17473 + return -1;
17478 + return sock;
17482 + * Enumerates and returns all IPv4 interfaces on Solaris.
17483 + */
17484 +static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
17485 + struct lifconf ifc;
17486 + struct lifreq *ifreqP;
17487 + struct lifnum numifs;
17488 + char *buf = NULL;
17489 + unsigned i;
17491 + // call SIOCGLIFNUM to get the interface count
17492 + numifs.lifn_family = AF_INET;
17493 + numifs.lifn_flags = 0;
17494 + if (ioctl(sock, SIOCGLIFNUM, (char *)&numifs) < 0) {
17495 + JNU_ThrowByNameWithMessageAndLastError
17496 + (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFNUM) failed");
17497 + return ifs;
17500 + // call SIOCGLIFCONF to enumerate the interfaces
17501 + ifc.lifc_len = numifs.lifn_count * sizeof(struct lifreq);
17502 + CHECKED_MALLOC3(buf, char *, ifc.lifc_len);
17503 + ifc.lifc_buf = buf;
17504 + ifc.lifc_family = AF_INET;
17505 + ifc.lifc_flags = 0;
17506 + if (ioctl(sock, SIOCGLIFCONF, (char *)&ifc) < 0) {
17507 + JNU_ThrowByNameWithMessageAndLastError
17508 + (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFCONF) failed");
17509 + free(buf);
17510 + return ifs;
17513 + // iterate through each interface
17514 + ifreqP = ifc.lifc_req;
17515 + for (i = 0; i < numifs.lifn_count; i++, ifreqP++) {
17516 + struct sockaddr addr, *broadaddrP = NULL;
17518 + // ignore non IPv4 addresses
17519 + if (ifreqP->lifr_addr.ss_family != AF_INET) {
17520 + continue;
17523 + // save socket address
17524 + memcpy(&addr, &(ifreqP->lifr_addr), sizeof(struct sockaddr));
17526 + // determine broadcast address, if applicable
17527 + if ((ioctl(sock, SIOCGLIFFLAGS, ifreqP) == 0) &&
17528 + ifreqP->lifr_flags & IFF_BROADCAST) {
17530 + // restore socket address to ifreqP
17531 + memcpy(&(ifreqP->lifr_addr), &addr, sizeof(struct sockaddr));
17533 + // query broadcast address and set pointer to it
17534 + if (ioctl(sock, SIOCGLIFBRDADDR, ifreqP) == 0) {
17535 + broadaddrP = (struct sockaddr *)&(ifreqP->lifr_broadaddr);
17539 + // add to the list
17540 + ifs = addif(env, sock, ifreqP->lifr_name, ifs,
17541 + &addr, broadaddrP, AF_INET, (short)ifreqP->lifr_addrlen);
17543 + // if an exception occurred we return immediately
17544 + if ((*env)->ExceptionOccurred(env)) {
17545 + free(buf);
17546 + return ifs;
17550 + // free buffer
17551 + free(buf);
17552 + return ifs;
17556 + * Enumerates and returns all IPv6 interfaces on Solaris.
17557 + */
17558 +static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
17559 + struct lifconf ifc;
17560 + struct lifreq *ifreqP;
17561 + struct lifnum numifs;
17562 + char *buf = NULL;
17563 + unsigned i;
17565 + // call SIOCGLIFNUM to get the interface count
17566 + numifs.lifn_family = AF_INET6;
17567 + numifs.lifn_flags = 0;
17568 + if (ioctl(sock, SIOCGLIFNUM, (char *)&numifs) < 0) {
17569 + JNU_ThrowByNameWithMessageAndLastError
17570 + (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFNUM) failed");
17571 + return ifs;
17574 + // call SIOCGLIFCONF to enumerate the interfaces
17575 + ifc.lifc_len = numifs.lifn_count * sizeof(struct lifreq);
17576 + CHECKED_MALLOC3(buf, char *, ifc.lifc_len);
17577 + ifc.lifc_buf = buf;
17578 + ifc.lifc_family = AF_INET6;
17579 + ifc.lifc_flags = 0;
17580 + if (ioctl(sock, SIOCGLIFCONF, (char *)&ifc) < 0) {
17581 + JNU_ThrowByNameWithMessageAndLastError
17582 + (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFCONF) failed");
17583 + free(buf);
17584 + return ifs;
17587 + // iterate through each interface
17588 + ifreqP = ifc.lifc_req;
17589 + for (i = 0; i < numifs.lifn_count; i++, ifreqP++) {
17591 + // ignore non IPv6 addresses
17592 + if (ifreqP->lifr_addr.ss_family != AF_INET6) {
17593 + continue;
17596 + // set scope ID to interface index
17597 + ((struct sockaddr_in6 *)&(ifreqP->lifr_addr))->sin6_scope_id =
17598 + getIndex(sock, ifreqP->lifr_name);
17600 + // add to the list
17601 + ifs = addif(env, sock, ifreqP->lifr_name, ifs,
17602 + (struct sockaddr *)&(ifreqP->lifr_addr),
17603 + NULL, AF_INET6, (short)ifreqP->lifr_addrlen);
17605 + // if an exception occurred we return immediately
17606 + if ((*env)->ExceptionOccurred(env)) {
17607 + free(buf);
17608 + return ifs;
17612 + // free buffer
17613 + free(buf);
17614 + return ifs;
17618 + * Try to get the interface index.
17619 + * (Not supported on Solaris 2.6 or 7)
17620 + */
17621 +static int getIndex(int sock, const char *name) {
17622 + struct lifreq if2;
17623 + memset((char *)&if2, 0, sizeof(if2));
17624 + strncpy(if2.lifr_name, name, sizeof(if2.lifr_name) - 1);
17626 + if (ioctl(sock, SIOCGLIFINDEX, (char *)&if2) < 0) {
17627 + return -1;
17630 + return if2.lifr_index;
17634 + * Solaris specific DLPI code to get hardware address from a device.
17635 + * Unfortunately, at least up to Solaris X, you have to have special
17636 + * privileges (i.e. be root).
17637 + */
17638 +static int getMacFromDevice
17639 + (JNIEnv *env, const char *ifname, unsigned char *retbuf)
17641 + char style1dev[MAXPATHLEN];
17642 + int fd;
17643 + dl_phys_addr_req_t dlpareq;
17644 + dl_phys_addr_ack_t *dlpaack;
17645 + dl_error_ack_t *dlerack;
17646 + struct strbuf msg;
17647 + char buf[128];
17648 + int flags = 0;
17650 + // Device is in /dev. e.g.: /dev/bge0
17651 + strcpy(style1dev, DEV_PREFIX);
17652 + strcat(style1dev, ifname);
17653 + if ((fd = open(style1dev, O_RDWR)) < 0) {
17654 + // Can't open it. We probably are missing the privilege.
17655 + // We'll have to try something else
17656 + return 0;
17659 + dlpareq.dl_primitive = DL_PHYS_ADDR_REQ;
17660 + dlpareq.dl_addr_type = DL_CURR_PHYS_ADDR;
17662 + msg.buf = (char *)&dlpareq;
17663 + msg.len = DL_PHYS_ADDR_REQ_SIZE;
17665 + if (putmsg(fd, &msg, NULL, 0) < 0) {
17666 + JNU_ThrowByNameWithMessageAndLastError
17667 + (env, JNU_JAVANETPKG "SocketException", "putmsg() failed");
17668 + return -1;
17671 + dlpaack = (dl_phys_addr_ack_t *)buf;
17673 + msg.buf = (char *)buf;
17674 + msg.len = 0;
17675 + msg.maxlen = sizeof (buf);
17676 + if (getmsg(fd, &msg, NULL, &flags) < 0) {
17677 + JNU_ThrowByNameWithMessageAndLastError
17678 + (env, JNU_JAVANETPKG "SocketException", "getmsg() failed");
17679 + return -1;
17682 + if (dlpaack->dl_primitive == DL_ERROR_ACK) {
17683 + dlerack = (dl_error_ack_t *)buf;
17684 + if (dlerack->dl_error_primitive != DL_PHYS_ADDR_REQ) {
17685 + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
17686 + "Couldn't obtain physical address\n");
17687 + return -1;
17689 + if (dlerack->dl_errno == DL_UNSUPPORTED) {
17690 + // fallback to lookup in the ARP table
17691 + return 0;
17695 + if (msg.len < DL_PHYS_ADDR_ACK_SIZE || dlpaack->dl_primitive != DL_PHYS_ADDR_ACK) {
17696 + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
17697 + "Couldn't obtain phys addr\n");
17698 + return -1;
17701 + memcpy(retbuf, &buf[dlpaack->dl_addr_offset], dlpaack->dl_addr_length);
17702 + return dlpaack->dl_addr_length;
17706 + * Gets the Hardware address (usually MAC address) for the named interface.
17707 + * On return puts the data in buf, and returns the length, in byte, of the
17708 + * MAC address. Returns -1 if there is no hardware address on that interface.
17709 + */
17710 +static int getMacAddress
17711 + (JNIEnv *env, const char *ifname, const struct in_addr *addr,
17712 + unsigned char *buf)
17714 + struct lifreq if2;
17715 + int len, i, sock;
17717 + if ((sock = openSocketWithFallback(env, ifname)) < 0) {
17718 + return -1;
17721 + // First, try the new (S11) SIOCGLIFHWADDR ioctl(). If that fails
17722 + // try the old way.
17723 + memset((char *)&if2, 0, sizeof(if2));
17724 + strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
17726 + if (ioctl(sock, SIOCGLIFHWADDR, &if2) != -1) {
17727 + struct sockaddr_dl *sp;
17728 + sp = (struct sockaddr_dl *)&if2.lifr_addr;
17729 + memcpy(buf, &sp->sdl_data[0], sp->sdl_alen);
17730 + close(sock);
17731 + return sp->sdl_alen;
17734 + // On Solaris we have to use DLPI, but it will only work if we have
17735 + // privileged access (i.e. root). If that fails, we try a lookup
17736 + // in the ARP table, which requires an IPv4 address.
17737 + if (((len = getMacFromDevice(env, ifname, buf)) == 0) && (addr != NULL)) {
17738 + struct arpreq arpreq;
17739 + struct sockaddr_in *sin;
17740 + struct sockaddr_in ipAddr;
17742 + len = 6; //???
17744 + sin = (struct sockaddr_in *)&arpreq.arp_pa;
17745 + memset((char *)&arpreq, 0, sizeof(struct arpreq));
17746 + ipAddr.sin_port = 0;
17747 + ipAddr.sin_family = AF_INET;
17748 + memcpy(&ipAddr.sin_addr, addr, sizeof(struct in_addr));
17749 + memcpy(&arpreq.arp_pa, &ipAddr, sizeof(struct sockaddr_in));
17750 + arpreq.arp_flags= ATF_PUBL;
17752 + if (ioctl(sock, SIOCGARP, &arpreq) < 0) {
17753 + close(sock);
17754 + return -1;
17757 + memcpy(buf, &arpreq.arp_ha.sa_data[0], len);
17759 + close(sock);
17761 + // all bytes to 0 means no hardware address
17762 + for (i = 0; i < len; i++) {
17763 + if (buf[i] != 0)
17764 + return len;
17767 + return -1;
17770 +static int getMTU(JNIEnv *env, int sock, const char *ifname) {
17771 + struct lifreq if2;
17772 + memset((char *)&if2, 0, sizeof(if2));
17773 + strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
17775 + if (ioctl(sock, SIOCGLIFMTU, (char *)&if2) < 0) {
17776 + JNU_ThrowByNameWithMessageAndLastError
17777 + (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFMTU) failed");
17778 + return -1;
17781 + return if2.lifr_mtu;
17784 +static int getFlags(int sock, const char *ifname, int *flags) {
17785 + struct lifreq if2;
17786 + memset((char *)&if2, 0, sizeof(if2));
17787 + strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
17789 + if (ioctl(sock, SIOCGLIFFLAGS, (char *)&if2) < 0) {
17790 + return -1;
17793 + *flags = if2.lifr_flags;
17794 + return 0;
17797 +#endif /* __solaris__ */
17799 /** BSD **/
17800 #if defined(_ALLBSD_SOURCE)
17802 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libnet/portconfig.c jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libnet/portconfig.c
17803 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libnet/portconfig.c 2024-07-09 10:07:16.000000000 +0200
17804 +++ jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libnet/portconfig.c 2024-08-17 19:13:01.414264132 +0200
17805 @@ -60,6 +60,13 @@
17807 return -1;
17810 +#elif defined(__solaris__)
17812 + range->higher = net_getParam("/dev/tcp", "tcp_largest_anon_port");
17813 + range->lower = net_getParam("/dev/tcp", "tcp_smallest_anon_port");
17814 + return 0;
17816 #elif defined(_ALLBSD_SOURCE)
17818 int ret;
17819 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libnet/SdpSupport.c jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libnet/SdpSupport.c
17820 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libnet/SdpSupport.c 2024-07-09 10:07:16.000000000 +0200
17821 +++ jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libnet/SdpSupport.c 2024-08-17 19:13:01.412387664 +0200
17822 @@ -27,7 +27,11 @@
17823 #include <sys/socket.h>
17824 #include <errno.h>
17826 -#if defined(__linux__)
17827 +#if defined(__solaris__)
17828 + #if !defined(PROTO_SDP)
17829 + #define PROTO_SDP 257
17830 + #endif
17831 +#elif defined(__linux__)
17832 #if !defined(AF_INET_SDP)
17833 #define AF_INET_SDP 27
17834 #endif
17835 @@ -51,7 +55,10 @@
17837 int s;
17839 -#if defined(__linux__)
17840 +#if defined(__solaris__)
17841 + int domain = ipv6_available() ? AF_INET6 : AF_INET;
17842 + s = socket(domain, SOCK_STREAM, PROTO_SDP);
17843 +#elif defined(__linux__)
17845 * IPv6 not supported by SDP on Linux
17847 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libnio/ch/DatagramChannelImpl.c jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libnio/ch/DatagramChannelImpl.c
17848 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libnio/ch/DatagramChannelImpl.c 2024-07-09 10:07:16.000000000 +0200
17849 +++ jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libnio/ch/DatagramChannelImpl.c 2024-08-17 19:13:01.414833966 +0200
17850 @@ -50,6 +50,9 @@
17851 jint fd = fdval(env, fdo);
17852 int rv;
17854 +#if defined(__solaris__)
17855 + rv = connect(fd, 0, 0);
17856 +#else
17857 #if defined(__APPLE__)
17858 // On macOS systems we use disconnectx
17859 rv = disconnectx(fd, SAE_ASSOCID_ANY, SAE_CONNID_ANY);
17860 @@ -83,6 +86,8 @@
17861 rv = errno = 0;
17862 #endif // defined(_ALLBSD_SOURCE) || defined(_AIX)
17864 +#endif // defined(__solaris__)
17866 if (rv < 0)
17867 handleSocketError(env, errno);
17869 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libnio/ch/NativeThread.c jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libnio/ch/NativeThread.c
17870 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libnio/ch/NativeThread.c 2024-07-09 10:07:16.000000000 +0200
17871 +++ jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libnio/ch/NativeThread.c 2024-08-17 19:13:01.415283993 +0200
17872 @@ -40,6 +40,9 @@
17873 #elif defined(_AIX)
17874 /* Also defined in net/aix_close.c */
17875 #define INTERRUPT_SIGNAL (SIGRTMAX - 1)
17876 +#elif defined(__solaris__)
17877 + #include <thread.h>
17878 + #define INTERRUPT_SIGNAL (SIGRTMAX - 2)
17879 #elif defined(_ALLBSD_SOURCE)
17880 /* Also defined in net/bsd_close.c */
17881 #define INTERRUPT_SIGNAL SIGIO
17882 @@ -73,14 +76,22 @@
17883 JNIEXPORT jlong JNICALL
17884 Java_sun_nio_ch_NativeThread_current0(JNIEnv *env, jclass cl)
17886 +#ifdef __solaris__
17887 + return (jlong)thr_self();
17888 +#else
17889 return (jlong)pthread_self();
17890 +#endif
17893 JNIEXPORT void JNICALL
17894 Java_sun_nio_ch_NativeThread_signal0(JNIEnv *env, jclass cl, jlong thread)
17896 int ret;
17897 +#ifdef __solaris__
17898 + ret = thr_kill((thread_t)thread, INTERRUPT_SIGNAL);
17899 +#else
17900 ret = pthread_kill((pthread_t)thread, INTERRUPT_SIGNAL);
17901 +#endif
17902 #ifdef MACOSX
17903 if (ret != 0 && ret != ESRCH)
17904 #else
17905 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libnio/ch/Net.c jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libnio/ch/Net.c
17906 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libnio/ch/Net.c 2024-07-09 10:07:16.000000000 +0200
17907 +++ jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libnio/ch/Net.c 2024-08-17 19:13:01.415864488 +0200
17908 @@ -215,7 +215,7 @@
17909 JNIEXPORT jboolean JNICALL
17910 Java_sun_nio_ch_Net_canIPv6SocketJoinIPv4Group0(JNIEnv* env, jclass cl)
17912 -#if defined(__linux__) || defined(__APPLE__)
17913 +#if defined(__linux__) || defined(__APPLE__) || defined(__solaris__)
17914 /* IPv6 sockets can join IPv4 multicast groups */
17915 return JNI_TRUE;
17916 #else
17917 @@ -227,7 +227,7 @@
17918 JNIEXPORT jboolean JNICALL
17919 Java_sun_nio_ch_Net_canJoin6WithIPv4Group0(JNIEnv* env, jclass cl)
17921 -#if defined(__APPLE__)
17922 +#if defined(__APPLE__) || defined(__solaris__)
17923 /* IPV6_ADD_MEMBERSHIP can be used to join IPv4 multicast groups */
17924 return JNI_TRUE;
17925 #else
17926 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libnio/ch/nio_util.h jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libnio/ch/nio_util.h
17927 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libnio/ch/nio_util.h 2024-07-09 10:07:16.000000000 +0200
17928 +++ jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libnio/ch/nio_util.h 2024-08-17 19:13:01.416275610 +0200
17929 @@ -41,6 +41,8 @@
17930 #ifndef SO_REUSEPORT
17931 #ifdef __linux__
17932 #define SO_REUSEPORT 15
17933 +#elif defined(__solaris__)
17934 +#define SO_REUSEPORT 0x100e
17935 #elif defined(AIX) || defined(MACOSX)
17936 #define SO_REUSEPORT 0x0200
17937 #else
17938 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c
17939 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c 2024-07-09 10:07:16.000000000 +0200
17940 +++ jdk21u-jdk-21.0.4-ga/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c 2024-08-17 19:13:01.417057184 +0200
17941 @@ -45,10 +45,17 @@
17942 #include <sys/xattr.h>
17943 #endif
17945 -/* For POSIX-compliant getpwuid_r */
17946 +/* For POSIX-compliant getpwuid_r, getgrgid_r on Solaris */
17947 +#if defined(__solaris__)
17948 +#define _POSIX_PTHREAD_SEMANTICS
17949 +#endif
17950 #include <pwd.h>
17951 #include <grp.h>
17953 +#ifdef __solaris__
17954 +#include <strings.h>
17955 +#endif
17957 #ifdef __linux__
17958 #include <sys/syscall.h>
17959 #include <sys/sysmacros.h> // makedev macros
17960 @@ -374,7 +381,8 @@
17962 /* system calls that might not be available at run time */
17964 -#if defined(_ALLBSD_SOURCE)
17965 +#if (defined(__solaris__) && defined(_LP64)) || defined(_ALLBSD_SOURCE)
17966 + /* Solaris 64-bit does not have openat64/fstatat64 */
17967 my_openat64_func = (openat64_func*)dlsym(RTLD_DEFAULT, "openat");
17968 my_fstatat64_func = (fstatat64_func*)dlsym(RTLD_DEFAULT, "fstatat");
17969 #else
17970 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.base/windows/native/libnet/net_util_md.c jdk21u-jdk-21.0.4-ga/src/java.base/windows/native/libnet/net_util_md.c
17971 --- jdk21u-jdk-21.0.4-ga.orig/src/java.base/windows/native/libnet/net_util_md.c 2024-07-09 10:07:16.000000000 +0200
17972 +++ jdk21u-jdk-21.0.4-ga/src/java.base/windows/native/libnet/net_util_md.c 2024-08-17 19:13:01.417691504 +0200
17973 @@ -125,6 +125,8 @@
17975 return TRUE;
17978 +void parseExclusiveBindProperty(JNIEnv *env) {}
17981 * Since winsock doesn't have the equivalent of strerror(errno)
17982 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/share/classes/sun/awt/FontConfiguration.java jdk21u-jdk-21.0.4-ga/src/java.desktop/share/classes/sun/awt/FontConfiguration.java
17983 --- jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/share/classes/sun/awt/FontConfiguration.java 2024-07-09 10:07:16.000000000 +0200
17984 +++ jdk21u-jdk-21.0.4-ga/src/java.desktop/share/classes/sun/awt/FontConfiguration.java 2024-08-17 19:13:01.418775951 +0200
17985 @@ -1422,6 +1422,22 @@
17989 + if (OSInfo.getOSType() == OSInfo.OSType.SOLARIS) {
17990 + for (int ii = 0; ii < table_awtfontpaths.length; ii++) {
17991 + if (table_awtfontpaths[ii] == 0) {
17992 + String script = getString(table_scriptIDs[ii]);
17993 + if (script.contains("dingbats") ||
17994 + script.contains("symbol")) {
17995 + continue;
17997 + System.err.println("\nError: "
17998 + + "<awtfontpath."
17999 + + script
18000 + + "> entry is missing!!!");
18001 + errors++;
18005 if (errors != 0) {
18006 System.err.println("!!THERE ARE " + errors + " ERROR(S) IN "
18007 + "THE FONTCONFIG FILE, PLEASE CHECK ITS CONTENT!!\n");
18008 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/share/classes/sun/awt/OSInfo.java jdk21u-jdk-21.0.4-ga/src/java.desktop/share/classes/sun/awt/OSInfo.java
18009 --- jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/share/classes/sun/awt/OSInfo.java 2024-07-09 10:07:16.000000000 +0200
18010 +++ jdk21u-jdk-21.0.4-ga/src/java.desktop/share/classes/sun/awt/OSInfo.java 2024-08-17 19:13:01.419257845 +0200
18011 @@ -39,6 +39,7 @@
18012 public static enum OSType {
18013 WINDOWS,
18014 LINUX,
18015 + SOLARIS,
18016 MACOSX,
18017 AIX,
18018 UNKNOWN
18019 @@ -95,6 +96,7 @@
18020 // Map OperatingSystem enum values to OSType enum values.
18021 case WINDOWS -> WINDOWS;
18022 case LINUX -> LINUX;
18023 + case SOLARIS -> SOLARIS;
18024 case MACOS -> MACOSX;
18025 case AIX -> AIX;
18026 default -> UNKNOWN;
18027 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/share/classes/sun/font/FontUtilities.java jdk21u-jdk-21.0.4-ga/src/java.desktop/share/classes/sun/font/FontUtilities.java
18028 --- jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/share/classes/sun/font/FontUtilities.java 2024-07-09 10:07:16.000000000 +0200
18029 +++ jdk21u-jdk-21.0.4-ga/src/java.desktop/share/classes/sun/font/FontUtilities.java 2024-08-17 19:13:01.419939081 +0200
18030 @@ -41,6 +41,8 @@
18032 public final class FontUtilities {
18034 + public static boolean isSolaris;
18036 public static boolean isLinux;
18038 public static boolean isMacOSX;
18039 @@ -66,6 +68,8 @@
18040 @Override
18041 public Object run() {
18043 + isSolaris = OSInfo.getOSType() == OSInfo.OSType.SOLARIS;
18045 isLinux = OSInfo.getOSType() == OSInfo.OSType.LINUX;
18047 isMacOSX = OSInfo.getOSType() == OSInfo.OSType.MACOSX;
18048 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/share/native/libjsound/SoundDefs.h jdk21u-jdk-21.0.4-ga/src/java.desktop/share/native/libjsound/SoundDefs.h
18049 --- jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/share/native/libjsound/SoundDefs.h 2024-07-09 10:07:16.000000000 +0200
18050 +++ jdk21u-jdk-21.0.4-ga/src/java.desktop/share/native/libjsound/SoundDefs.h 2024-08-17 19:13:01.420525303 +0200
18051 @@ -29,9 +29,10 @@
18053 // types for X_PLATFORM
18054 #define X_WINDOWS 1
18055 -#define X_LINUX 2
18056 -#define X_BSD 3
18057 -#define X_MACOSX 4
18058 +#define X_SOLARIS 2
18059 +#define X_LINUX 3
18060 +#define X_BSD 4
18061 +#define X_MACOSX 5
18063 // **********************************
18064 // Make sure you set X_PLATFORM defines correctly.
18065 @@ -44,7 +45,7 @@
18068 // following is needed for _LP64
18069 -#if ((X_PLATFORM == X_LINUX) || (X_PLATFORM == X_MACOSX))
18070 +#if ((X_PLATFORM == X_SOLARIS) || (X_PLATFORM == X_LINUX) || (X_PLATFORM == X_MACOSX))
18071 #include <sys/types.h>
18072 #endif
18074 @@ -114,6 +115,11 @@
18075 #endif
18078 +#if X_PLATFORM == X_SOLARIS
18079 +#define INLINE
18080 +#endif
18083 #if X_PLATFORM == X_LINUX
18084 #define INLINE inline
18085 #endif
18086 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/solaris/classes/sun/font/X11CNS11643.java jdk21u-jdk-21.0.4-ga/src/java.desktop/solaris/classes/sun/font/X11CNS11643.java
18087 --- jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/solaris/classes/sun/font/X11CNS11643.java 1970-01-01 01:00:00.000000000 +0100
18088 +++ jdk21u-jdk-21.0.4-ga/src/java.desktop/solaris/classes/sun/font/X11CNS11643.java 2024-08-17 19:13:01.469081559 +0200
18089 @@ -0,0 +1,178 @@
18091 + * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
18092 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
18094 + * This code is free software; you can redistribute it and/or modify it
18095 + * under the terms of the GNU General Public License version 2 only, as
18096 + * published by the Free Software Foundation. Oracle designates this
18097 + * particular file as subject to the "Classpath" exception as provided
18098 + * by Oracle in the LICENSE file that accompanied this code.
18100 + * This code is distributed in the hope that it will be useful, but WITHOUT
18101 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18102 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18103 + * version 2 for more details (a copy is included in the LICENSE file that
18104 + * accompanied this code).
18106 + * You should have received a copy of the GNU General Public License version
18107 + * 2 along with this work; if not, write to the Free Software Foundation,
18108 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18110 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
18111 + * or visit www.oracle.com if you need additional information or have any
18112 + * questions.
18113 + */
18115 +package sun.font;
18117 +import java.nio.CharBuffer;
18118 +import java.nio.ByteBuffer;
18119 +import java.nio.charset.*;
18120 +import sun.nio.cs.*;
18122 +public abstract class X11CNS11643 extends Charset {
18123 + private final int plane;
18124 + public X11CNS11643 (int plane, String name) {
18125 + super(name, null);
18126 + switch (plane) {
18127 + case 1:
18128 + this.plane = 0; // CS1
18129 + break;
18130 + case 2:
18131 + case 3:
18132 + this.plane = plane;
18133 + break;
18134 + default:
18135 + throw new IllegalArgumentException
18136 + ("Only planes 1, 2, and 3 supported");
18140 + public CharsetEncoder newEncoder() {
18141 + return new Encoder(this, plane);
18144 + public CharsetDecoder newDecoder() {
18145 + return new Decoder(this, plane);
18148 + public boolean contains(Charset cs) {
18149 + return cs instanceof X11CNS11643;
18152 + private class Encoder extends EUC_TW.Encoder {
18153 + private int plane;
18154 + public Encoder(Charset cs, int plane) {
18155 + super(cs);
18156 + this.plane = plane;
18159 + private byte[] bb = new byte[4];
18160 + public boolean canEncode(char c) {
18161 + if (c <= 0x7F) {
18162 + return false;
18164 + int nb = toEUC(c, bb);
18165 + if (nb == -1)
18166 + return false;
18167 + int p = 0;
18168 + if (nb == 4)
18169 + p = (bb[1] & 0xff) - 0xa0;
18170 + return (p == plane);
18173 + public boolean isLegalReplacement(byte[] repl) {
18174 + return true;
18177 + protected CoderResult encodeLoop(CharBuffer src, ByteBuffer dst) {
18178 + char[] sa = src.array();
18179 + int sp = src.arrayOffset() + src.position();
18180 + int sl = src.arrayOffset() + src.limit();
18181 + byte[] da = dst.array();
18182 + int dp = dst.arrayOffset() + dst.position();
18183 + int dl = dst.arrayOffset() + dst.limit();
18185 + try {
18186 + while (sp < sl) {
18187 + char c = sa[sp];
18188 + if ( c > '\u007f'&& c < '\uFFFE') {
18189 + int nb = toEUC(c, bb);
18190 + if (nb != -1) {
18191 + int p = 0;
18192 + if (nb == 4)
18193 + p = (bb[1] & 0xff) - 0xa0;
18194 + if (p == plane) {
18195 + if (dl - dp < 2)
18196 + return CoderResult.OVERFLOW;
18197 + if (nb == 2) {
18198 + da[dp++] = (byte)(bb[0] & 0x7f);
18199 + da[dp++] = (byte)(bb[1] & 0x7f);
18200 + } else {
18201 + da[dp++] = (byte)(bb[2] & 0x7f);
18202 + da[dp++] = (byte)(bb[3] & 0x7f);
18204 + sp++;
18205 + continue;
18209 + return CoderResult.unmappableForLength(1);
18211 + return CoderResult.UNDERFLOW;
18212 + } finally {
18213 + src.position(sp - src.arrayOffset());
18214 + dst.position(dp - dst.arrayOffset());
18219 + private class Decoder extends EUC_TW.Decoder {
18220 + int plane;
18221 + private String table;
18222 + protected Decoder(Charset cs, int plane) {
18223 + super(cs);
18224 + if (plane == 0)
18225 + this.plane = plane;
18226 + else if (plane == 2 || plane == 3)
18227 + this.plane = plane - 1;
18228 + else
18229 + throw new IllegalArgumentException
18230 + ("Only planes 1, 2, and 3 supported");
18233 + //we only work on array backed buffer.
18234 + protected CoderResult decodeLoop(ByteBuffer src, CharBuffer dst) {
18235 + byte[] sa = src.array();
18236 + int sp = src.arrayOffset() + src.position();
18237 + int sl = src.arrayOffset() + src.limit();
18239 + char[] da = dst.array();
18240 + int dp = dst.arrayOffset() + dst.position();
18241 + int dl = dst.arrayOffset() + dst.limit();
18243 + try {
18244 + while (sp < sl) {
18245 + if ( sl - sp < 2) {
18246 + return CoderResult.UNDERFLOW;
18248 + int b1 = (sa[sp] & 0xff) | 0x80;
18249 + int b2 = (sa[sp + 1] & 0xff) | 0x80;
18250 + char[] cc = toUnicode(b1, b2, plane);
18251 + // plane3 has non-bmp characters(added), x11cnsp3
18252 + // however does not support them
18253 + if (cc == null || cc.length == 2)
18254 + return CoderResult.unmappableForLength(2);
18255 + if (dl - dp < 1)
18256 + return CoderResult.OVERFLOW;
18257 + da[dp++] = cc[0];
18258 + sp +=2;
18260 + return CoderResult.UNDERFLOW;
18261 + } finally {
18262 + src.position(sp - src.arrayOffset());
18263 + dst.position(dp - dst.arrayOffset());
18268 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/solaris/classes/sun/font/X11CNS11643P1.java jdk21u-jdk-21.0.4-ga/src/java.desktop/solaris/classes/sun/font/X11CNS11643P1.java
18269 --- jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/solaris/classes/sun/font/X11CNS11643P1.java 1970-01-01 01:00:00.000000000 +0100
18270 +++ jdk21u-jdk-21.0.4-ga/src/java.desktop/solaris/classes/sun/font/X11CNS11643P1.java 2024-08-17 19:13:01.469403527 +0200
18271 @@ -0,0 +1,33 @@
18273 + * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
18274 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
18276 + * This code is free software; you can redistribute it and/or modify it
18277 + * under the terms of the GNU General Public License version 2 only, as
18278 + * published by the Free Software Foundation. Oracle designates this
18279 + * particular file as subject to the "Classpath" exception as provided
18280 + * by Oracle in the LICENSE file that accompanied this code.
18282 + * This code is distributed in the hope that it will be useful, but WITHOUT
18283 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18284 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18285 + * version 2 for more details (a copy is included in the LICENSE file that
18286 + * accompanied this code).
18288 + * You should have received a copy of the GNU General Public License version
18289 + * 2 along with this work; if not, write to the Free Software Foundation,
18290 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18292 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
18293 + * or visit www.oracle.com if you need additional information or have any
18294 + * questions.
18295 + */
18298 +package sun.font;
18300 +public class X11CNS11643P1 extends X11CNS11643 {
18301 + public X11CNS11643P1() {
18302 + super(1, "X11CNS11643P1");
18305 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/solaris/classes/sun/font/X11CNS11643P2.java jdk21u-jdk-21.0.4-ga/src/java.desktop/solaris/classes/sun/font/X11CNS11643P2.java
18306 --- jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/solaris/classes/sun/font/X11CNS11643P2.java 1970-01-01 01:00:00.000000000 +0100
18307 +++ jdk21u-jdk-21.0.4-ga/src/java.desktop/solaris/classes/sun/font/X11CNS11643P2.java 2024-08-17 19:13:01.469712553 +0200
18308 @@ -0,0 +1,32 @@
18310 + * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
18311 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
18313 + * This code is free software; you can redistribute it and/or modify it
18314 + * under the terms of the GNU General Public License version 2 only, as
18315 + * published by the Free Software Foundation. Oracle designates this
18316 + * particular file as subject to the "Classpath" exception as provided
18317 + * by Oracle in the LICENSE file that accompanied this code.
18319 + * This code is distributed in the hope that it will be useful, but WITHOUT
18320 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18321 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18322 + * version 2 for more details (a copy is included in the LICENSE file that
18323 + * accompanied this code).
18325 + * You should have received a copy of the GNU General Public License version
18326 + * 2 along with this work; if not, write to the Free Software Foundation,
18327 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18329 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
18330 + * or visit www.oracle.com if you need additional information or have any
18331 + * questions.
18332 + */
18334 +package sun.font;
18336 +public class X11CNS11643P2 extends X11CNS11643 {
18337 + public X11CNS11643P2() {
18338 + super(2, "X11CNS11643P2");
18341 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/solaris/classes/sun/font/X11CNS11643P3.java jdk21u-jdk-21.0.4-ga/src/java.desktop/solaris/classes/sun/font/X11CNS11643P3.java
18342 --- jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/solaris/classes/sun/font/X11CNS11643P3.java 1970-01-01 01:00:00.000000000 +0100
18343 +++ jdk21u-jdk-21.0.4-ga/src/java.desktop/solaris/classes/sun/font/X11CNS11643P3.java 2024-08-17 19:13:01.470001626 +0200
18344 @@ -0,0 +1,32 @@
18346 + * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved.
18347 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
18349 + * This code is free software; you can redistribute it and/or modify it
18350 + * under the terms of the GNU General Public License version 2 only, as
18351 + * published by the Free Software Foundation. Oracle designates this
18352 + * particular file as subject to the "Classpath" exception as provided
18353 + * by Oracle in the LICENSE file that accompanied this code.
18355 + * This code is distributed in the hope that it will be useful, but WITHOUT
18356 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18357 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18358 + * version 2 for more details (a copy is included in the LICENSE file that
18359 + * accompanied this code).
18361 + * You should have received a copy of the GNU General Public License version
18362 + * 2 along with this work; if not, write to the Free Software Foundation,
18363 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18365 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
18366 + * or visit www.oracle.com if you need additional information or have any
18367 + * questions.
18368 + */
18370 +package sun.font;
18372 +public class X11CNS11643P3 extends X11CNS11643 {
18373 + public X11CNS11643P3() {
18374 + super(3, "X11CNS11643P3");
18377 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/solaris/data/fontconfig/fontconfig.properties jdk21u-jdk-21.0.4-ga/src/java.desktop/solaris/data/fontconfig/fontconfig.properties
18378 --- jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/solaris/data/fontconfig/fontconfig.properties 1970-01-01 01:00:00.000000000 +0100
18379 +++ jdk21u-jdk-21.0.4-ga/src/java.desktop/solaris/data/fontconfig/fontconfig.properties 2024-08-17 19:13:01.440087324 +0200
18380 @@ -0,0 +1,516 @@
18383 +# Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
18384 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
18386 +# This code is free software; you can redistribute it and/or modify it
18387 +# under the terms of the GNU General Public License version 2 only, as
18388 +# published by the Free Software Foundation. Oracle designates this
18389 +# particular file as subject to the "Classpath" exception as provided
18390 +# by Oracle in the LICENSE file that accompanied this code.
18392 +# This code is distributed in the hope that it will be useful, but WITHOUT
18393 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18394 +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18395 +# version 2 for more details (a copy is included in the LICENSE file that
18396 +# accompanied this code).
18398 +# You should have received a copy of the GNU General Public License version
18399 +# 2 along with this work; if not, write to the Free Software Foundation,
18400 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18402 +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
18403 +# or visit www.oracle.com if you need additional information or have any
18404 +# questions.
18407 +# Version
18409 +version=1
18411 +# Component Font Mappings
18413 +allfonts.chinese-gb2312=-arphic-uming-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18414 +allfonts.chinese-gbk=-arphic-uming-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18415 +allfonts.chinese-gb18030-0=-arphic-uming-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18416 +allfonts.chinese-gb18030-1=-arphic-uming-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18417 +allfonts.chinese-cns11643-1=-arphic-uming-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18418 +allfonts.chinese-cns11643-2=-arphic-uming-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18419 +allfonts.chinese-cns11643-3=-arphic-uming-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18420 +allfonts.chinese-big5=-arphic-uming-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18421 +allfonts.chinese-hkscs=-arphic-uming-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18422 +allfonts.dingbats=-microsoft-wingdings-medium-r-normal--*-%d-*-*-p-*-adobe-fontspecific
18423 +allfonts.japanese-x0212=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18424 +allfonts.korean=-hanyang-gothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18425 +allfonts.korean-johab=-hanyang-gothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18426 +allfonts.symbol=-monotype-symbol-medium-r-normal--*-%d-*-*-p-*-adobe-symbol
18427 +allfonts.bengali=-misc-lohit bengali-medium-r-normal--0-0-0-0-p-0-iso10646-1
18428 +allfonts.gujarati=-misc-lohit gujarati-medium-r-normal--0-0-0-0-p-0-iso10646-1
18429 +allfonts.hindi=-misc-lohit hindi-medium-r-normal--0-0-0-0-p-0-iso10646-1
18430 +allfonts.kannada=-misc-lohit kannada-medium-r-normal--0-0-0-0-p-0-iso10646-1
18431 +allfonts.malayalam=-misc-lohit malayalam-medium-r-normal--0-0-0-0-p-0-iso10646-1
18432 +allfonts.marathi=-misc-lohit marathi-medium-r-normal--0-0-0-0-p-0-iso10646-1
18433 +allfonts.tamil=-misc-lohit tamil-medium-r-normal--0-0-0-0-p-0-iso10646-1
18434 +allfonts.telugu=-misc-lohit telugu-medium-r-normal--0-0-0-0-p-0-iso10646-1
18435 +allfonts.dejavusans=-misc-dejavu sans-medium-r-normal--0-0-0-0-p-0-iso10646-1
18437 +serif.plain.arabic=-monotype-times new roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18438 +serif.plain.cyrillic-iso8859-5=-monotype-times new roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18439 +serif.plain.cyrillic-cp1251=-monotype-times new roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18440 +serif.plain.cyrillic-koi8-r=-monotype-times new roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18441 +serif.plain.greek=-monotype-times new roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18442 +serif.plain.hebrew=-monotype-times new roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18443 +serif.plain.japanese-x0201=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18444 +serif.plain.japanese-x0208=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18445 +serif.plain.latin-1=-monotype-times new roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18446 +serif.plain.latin-2=-monotype-times new roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18447 +serif.plain.latin-5=-monotype-times new roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18448 +serif.plain.latin-7=-monotype-times new roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18449 +serif.plain.latin-9=-monotype-times new roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18450 +serif.plain.thai=-monotype-angsana new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18452 +serif.bold.arabic=-monotype-times new roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18453 +serif.bold.cyrillic-iso8859-5=-monotype-times new roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18454 +serif.bold.cyrillic-cp1251=-monotype-times new roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18455 +serif.bold.cyrillic-koi8-r=-monotype-times new roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18456 +serif.bold.greek=-monotype-times new roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18457 +serif.bold.hebrew=-monotype-times new roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18458 +serif.bold.japanese-x0201=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18459 +serif.bold.japanese-x0208=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18460 +serif.bold.latin-1=-monotype-times new roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18461 +serif.bold.latin-2=-monotype-times new roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18462 +serif.bold.latin-5=-monotype-times new roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18463 +serif.bold.latin-7=-monotype-times new roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18464 +serif.bold.latin-9=-monotype-times new roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18465 +serif.bold.thai=-monotype-angsana new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18467 +serif.italic.arabic=-monotype-times new roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18468 +serif.italic.cyrillic-iso8859-5=-monotype-times new roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18469 +serif.italic.cyrillic-cp1251=-monotype-times new roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18470 +serif.italic.cyrillic-koi8-r=-monotype-times new roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18471 +serif.italic.greek=-monotype-times new roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18472 +serif.italic.hebrew=-monotype-times new roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18473 +serif.italic.japanese-x0201=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18474 +serif.italic.japanese-x0208=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18475 +serif.italic.latin-1=-monotype-times new roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18476 +serif.italic.latin-2=-monotype-times new roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18477 +serif.italic.latin-5=-monotype-times new roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18478 +serif.italic.latin-7=-monotype-times new roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18479 +serif.italic.latin-9=-monotype-times new roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18480 +serif.italic.thai=-monotype-angsana new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18482 +serif.bolditalic.arabic=-monotype-times new roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18483 +serif.bolditalic.cyrillic-iso8859-5=-monotype-times new roman-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18484 +serif.bolditalic.cyrillic-cp1251=-monotype-times new roman-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18485 +serif.bolditalic.cyrillic-koi8-r=-monotype-times new roman-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18486 +serif.bolditalic.greek=-monotype-times new roman-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18487 +serif.bolditalic.hebrew=-monotype-times new roman-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18488 +serif.bolditalic.japanese-x0201=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18489 +serif.bolditalic.japanese-x0208=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18490 +serif.bolditalic.latin-1=-monotype-times new roman-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18491 +serif.bolditalic.latin-2=-monotype-times new roman-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18492 +serif.bolditalic.latin-5=-monotype-times new roman-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18493 +serif.bolditalic.latin-7=-monotype-times new roman-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18494 +serif.bolditalic.latin-9=-monotype-times new roman-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18495 +serif.bolditalic.thai=-monotype-angsana new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18497 +sansserif.plain.arabic=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18498 +sansserif.plain.cyrillic-iso8859-5=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18499 +sansserif.plain.cyrillic-cp1251=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18500 +sansserif.plain.cyrillic-koi8-r=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18501 +sansserif.plain.greek=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18502 +sansserif.plain.hebrew=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18503 +sansserif.plain.japanese-x0201=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18504 +sansserif.plain.japanese-x0208=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18505 +sansserif.plain.latin-1=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18506 +sansserif.plain.latin-2=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18507 +sansserif.plain.latin-5=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18508 +sansserif.plain.latin-7=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18509 +sansserif.plain.latin-9=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18510 +sansserif.plain.thai=-monotype-browallia new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18512 +sansserif.bold.arabic=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18513 +sansserif.bold.cyrillic-iso8859-5=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18514 +sansserif.bold.cyrillic-cp1251=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18515 +sansserif.bold.cyrillic-koi8-r=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18516 +sansserif.bold.greek=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18517 +sansserif.bold.hebrew=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18518 +sansserif.bold.japanese-x0201=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18519 +sansserif.bold.japanese-x0208=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18520 +sansserif.bold.latin-1=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18521 +sansserif.bold.latin-2=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18522 +sansserif.bold.latin-5=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18523 +sansserif.bold.latin-7=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18524 +sansserif.bold.latin-9=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18525 +sansserif.bold.thai=-monotype-browallia new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18527 +sansserif.italic.arabic=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18528 +sansserif.italic.cyrillic-iso8859-5=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18529 +sansserif.italic.cyrillic-cp1251=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18530 +sansserif.italic.cyrillic-koi8-r=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18531 +sansserif.italic.greek=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18532 +sansserif.italic.hebrew=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18533 +sansserif.italic.japanese-x0201=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18534 +sansserif.italic.japanese-x0208=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18535 +sansserif.italic.latin-1=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18536 +sansserif.italic.latin-2=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18537 +sansserif.italic.latin-5=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18538 +sansserif.italic.latin-7=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18539 +sansserif.italic.latin-9=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18540 +sansserif.italic.thai=-monotype-browallia new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18542 +sansserif.bolditalic.arabic=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18543 +sansserif.bolditalic.cyrillic-iso8859-5=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18544 +sansserif.bolditalic.cyrillic-cp1251=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18545 +sansserif.bolditalic.cyrillic-koi8-r=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18546 +sansserif.bolditalic.greek=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18547 +sansserif.bolditalic.hebrew=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18548 +sansserif.bolditalic.japanese-x0201=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18549 +sansserif.bolditalic.japanese-x0208=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18550 +sansserif.bolditalic.latin-1=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18551 +sansserif.bolditalic.latin-2=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18552 +sansserif.bolditalic.latin-5=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18553 +sansserif.bolditalic.latin-7=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18554 +sansserif.bolditalic.latin-9=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18555 +sansserif.bolditalic.thai=-monotype-browallia new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18557 +monospaced.plain.arabic=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18558 +monospaced.plain.cyrillic-iso8859-5=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18559 +monospaced.plain.cyrillic-cp1251=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18560 +monospaced.plain.cyrillic-koi8-r=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18561 +monospaced.plain.greek=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18562 +monospaced.plain.hebrew=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18563 +monospaced.plain.japanese-x0201=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18564 +monospaced.plain.japanese-x0208=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18565 +monospaced.plain.latin-1=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18566 +monospaced.plain.latin-2=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18567 +monospaced.plain.latin-5=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18568 +monospaced.plain.latin-7=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18569 +monospaced.plain.latin-9=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18570 +monospaced.plain.thai=-monotype-cordia new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18572 +monospaced.bold.arabic=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18573 +monospaced.bold.cyrillic-iso8859-5=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18574 +monospaced.bold.cyrillic-cp1251=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18575 +monospaced.bold.cyrillic-koi8-r=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18576 +monospaced.bold.greek=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18577 +monospaced.bold.hebrew=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18578 +monospaced.bold.japanese-x0201=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18579 +monospaced.bold.japanese-x0208=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18580 +monospaced.bold.latin-1=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18581 +monospaced.bold.latin-2=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18582 +monospaced.bold.latin-5=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18583 +monospaced.bold.latin-7=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18584 +monospaced.bold.latin-9=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18585 +monospaced.bold.thai=-monotype-cordia new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18587 +monospaced.italic.arabic=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18588 +monospaced.italic.cyrillic-iso8859-5=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18589 +monospaced.italic.cyrillic-cp1251=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18590 +monospaced.italic.cyrillic-koi8-r=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18591 +monospaced.italic.greek=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18592 +monospaced.italic.hebrew=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18593 +monospaced.italic.japanese-x0201=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18594 +monospaced.italic.japanese-x0208=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18595 +monospaced.italic.latin-1=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18596 +monospaced.italic.latin-2=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18597 +monospaced.italic.latin-5=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18598 +monospaced.italic.latin-7=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18599 +monospaced.italic.latin-9=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18600 +monospaced.italic.thai=-monotype-cordia new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18602 +monospaced.bolditalic.arabic=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18603 +monospaced.bolditalic.cyrillic-iso8859-5=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18604 +monospaced.bolditalic.cyrillic-cp1251=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18605 +monospaced.bolditalic.cyrillic-koi8-r=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18606 +monospaced.bolditalic.greek=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18607 +monospaced.bolditalic.hebrew=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18608 +monospaced.bolditalic.japanese-x0201=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18609 +monospaced.bolditalic.japanese-x0208=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18610 +monospaced.bolditalic.latin-1=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18611 +monospaced.bolditalic.latin-2=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18612 +monospaced.bolditalic.latin-5=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18613 +monospaced.bolditalic.latin-7=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18614 +monospaced.bolditalic.latin-9=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18615 +monospaced.bolditalic.thai=-monotype-cordia new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18617 +dialog.plain.arabic=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18618 +dialog.plain.cyrillic-iso8859-5=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18619 +dialog.plain.cyrillic-cp1251=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18620 +dialog.plain.cyrillic-koi8-r=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18621 +dialog.plain.greek=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18622 +dialog.plain.hebrew=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18623 +dialog.plain.japanese-x0201=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18624 +dialog.plain.japanese-x0208=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18625 +dialog.plain.latin-1=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18626 +dialog.plain.latin-2=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18627 +dialog.plain.latin-5=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18628 +dialog.plain.latin-7=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18629 +dialog.plain.latin-9=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18630 +dialog.plain.thai=-monotype-browallia new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18632 +dialog.bold.arabic=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18633 +dialog.bold.cyrillic-iso8859-5=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18634 +dialog.bold.cyrillic-cp1251=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18635 +dialog.bold.cyrillic-koi8-r=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18636 +dialog.bold.greek=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18637 +dialog.bold.hebrew=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18638 +dialog.bold.japanese-x0201=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18639 +dialog.bold.japanese-x0208=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18640 +dialog.bold.latin-1=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18641 +dialog.bold.latin-2=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18642 +dialog.bold.latin-5=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18643 +dialog.bold.latin-7=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18644 +dialog.bold.latin-9=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18645 +dialog.bold.thai=-monotype-browallia new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18647 +dialog.italic.arabic=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18648 +dialog.italic.cyrillic-iso8859-5=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18649 +dialog.italic.cyrillic-cp1251=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18650 +dialog.italic.cyrillic-koi8-r=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18651 +dialog.italic.greek=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18652 +dialog.italic.hebrew=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18653 +dialog.italic.japanese-x0201=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18654 +dialog.italic.japanese-x0208=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18655 +dialog.italic.latin-1=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18656 +dialog.italic.latin-2=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18657 +dialog.italic.latin-5=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18658 +dialog.italic.latin-7=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18659 +dialog.italic.latin-9=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18660 +dialog.italic.thai=-monotype-browallia new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18662 +dialog.bolditalic.arabic=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18663 +dialog.bolditalic.cyrillic-iso8859-5=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18664 +dialog.bolditalic.cyrillic-cp1251=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18665 +dialog.bolditalic.cyrillic-koi8-r=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18666 +dialog.bolditalic.greek=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18667 +dialog.bolditalic.hebrew=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18668 +dialog.bolditalic.japanese-x0201=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18669 +dialog.bolditalic.japanese-x0208=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18670 +dialog.bolditalic.latin-1=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18671 +dialog.bolditalic.latin-2=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18672 +dialog.bolditalic.latin-5=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18673 +dialog.bolditalic.latin-7=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18674 +dialog.bolditalic.latin-9=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18675 +dialog.bolditalic.thai=-monotype-browallia new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18677 +dialoginput.plain.arabic=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18678 +dialoginput.plain.cyrillic-iso8859-5=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18679 +dialoginput.plain.cyrillic-cp1251=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18680 +dialoginput.plain.cyrillic-koi8-r=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18681 +dialoginput.plain.greek=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18682 +dialoginput.plain.hebrew=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18683 +dialoginput.plain.japanese-x0201=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18684 +dialoginput.plain.japanese-x0208=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18685 +dialoginput.plain.latin-1=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18686 +dialoginput.plain.latin-2=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18687 +dialoginput.plain.latin-5=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18688 +dialoginput.plain.latin-7=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18689 +dialoginput.plain.latin-9=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18690 +dialoginput.plain.thai=-monotype-cordia new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18692 +dialoginput.bold.arabic=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18693 +dialoginput.bold.cyrillic-iso8859-5=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18694 +dialoginput.bold.cyrillic-cp1251=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18695 +dialoginput.bold.cyrillic-koi8-r=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18696 +dialoginput.bold.greek=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18697 +dialoginput.bold.hebrew=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18698 +dialoginput.bold.japanese-x0201=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18699 +dialoginput.bold.japanese-x0208=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18700 +dialoginput.bold.latin-1=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18701 +dialoginput.bold.latin-2=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18702 +dialoginput.bold.latin-5=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18703 +dialoginput.bold.latin-7=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18704 +dialoginput.bold.latin-9=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18705 +dialoginput.bold.thai=-monotype-cordia new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18707 +dialoginput.italic.arabic=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18708 +dialoginput.italic.cyrillic-iso8859-5=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18709 +dialoginput.italic.cyrillic-cp1251=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18710 +dialoginput.italic.cyrillic-koi8-r=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18711 +dialoginput.italic.greek=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18712 +dialoginput.italic.hebrew=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18713 +dialoginput.italic.japanese-x0201=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18714 +dialoginput.italic.japanese-x0208=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18715 +dialoginput.italic.latin-1=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18716 +dialoginput.italic.latin-2=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18717 +dialoginput.italic.latin-5=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18718 +dialoginput.italic.latin-7=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18719 +dialoginput.italic.latin-9=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18720 +dialoginput.italic.thai=-monotype-cordia new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18722 +dialoginput.bolditalic.arabic=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18723 +dialoginput.bolditalic.cyrillic-iso8859-5=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18724 +dialoginput.bolditalic.cyrillic-cp1251=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18725 +dialoginput.bolditalic.cyrillic-koi8-r=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18726 +dialoginput.bolditalic.greek=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18727 +dialoginput.bolditalic.hebrew=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18728 +dialoginput.bolditalic.japanese-x0201=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18729 +dialoginput.bolditalic.japanese-x0208=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18730 +dialoginput.bolditalic.latin-1=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18731 +dialoginput.bolditalic.latin-2=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18732 +dialoginput.bolditalic.latin-5=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18733 +dialoginput.bolditalic.latin-7=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18734 +dialoginput.bolditalic.latin-9=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18735 +dialoginput.bolditalic.thai=-monotype-cordia new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18737 +# Search Sequences
18739 +sequence.allfonts=latin-1
18741 +sequence.allfonts.Big5=latin-1,chinese-big5
18743 +sequence.allfonts.Big5-HKSCS-2001=latin-1,chinese-big5,chinese-hkscs
18745 +sequence.allfonts.windows-1251=cyrillic-cp1251,latin-1
18747 +sequence.allfonts.GB2312=latin-1,chinese-gb2312
18749 +sequence.allfonts.x-eucJP-Open=latin-1,japanese-x0201,japanese-x0208,japanese-x0212
18751 +sequence.allfonts.EUC-KR=latin-1,korean
18753 +sequence.allfonts.x-EUC-TW=latin-1,chinese-cns11643-1,chinese-cns11643-2,chinese-cns11643-3
18755 +sequence.allfonts.GBK=latin-1,chinese-gbk
18757 +sequence.allfonts.GB18030=latin-1,chinese-gb18030-0,chinese-gb18030-1
18759 +sequence.allfonts.ISO-8859-2=latin-2,latin-1
18761 +sequence.allfonts.ISO-8859-5=cyrillic-iso8859-5,latin-1
18763 +sequence.allfonts.ISO-8859-6=arabic,latin-1
18765 +sequence.allfonts.ISO-8859-7=latin-1,greek
18767 +sequence.allfonts.ISO-8859-8=latin-1,hebrew
18769 +sequence.allfonts.ISO-8859-9=latin-5,latin-1
18771 +sequence.allfonts.ISO-8859-13=latin-7,latin-1
18773 +sequence.allfonts.ISO-8859-15=latin-9
18775 +sequence.allfonts.KOI8-R=cyrillic-koi8-r,latin-1
18777 +sequence.allfonts.x-PCK=latin-1,japanese-x0201,japanese-x0208,japanese-x0212
18779 +sequence.allfonts.TIS-620=latin-1,thai
18781 +sequence.allfonts.UTF-8=latin-1
18782 +sequence.allfonts.UTF-8.en=latin-1
18783 +sequence.allfonts.UTF-8.hi=latin-1,hindi
18784 +sequence.allfonts.UTF-8.be=latin-1,bengali
18785 +sequence.allfonts.UTF-8.te=latin-1,telugu
18786 +sequence.allfonts.UTF-8.mr=latin-1,marathi
18787 +sequence.allfonts.UTF-8.ta=latin-1,tamil
18788 +sequence.allfonts.UTF-8.gu=latin-1,gujarati
18789 +sequence.allfonts.UTF-8.kn=latin-1,kannada
18790 +sequence.allfonts.UTF-8.ma=latin-1,malayalam
18792 +sequence.allfonts.UTF-8.ko=latin-1,korean-johab,japanese-x0201,japanese-x0208,japanese-x0212
18794 +sequence.allfonts.UTF-8.th=latin-1,thai
18796 +sequence.allfonts.UTF-8.zh.CN=latin-1,chinese-gb18030-0,chinese-gb18030-1,chinese-big5,chinese-hkscs
18798 +sequence.allfonts.UTF-8.zh.HK=latin-1,chinese-big5,chinese-hkscs,chinese-gb18030-0,chinese-gb18030-1
18800 +sequence.allfonts.UTF-8.zh.TW=latin-1,chinese-big5,chinese-hkscs,chinese-gb18030-0,chinese-gb18030-1
18802 +# the fallback sequence omits the following character subsets:
18803 +# - chinese: all same file : just use chinese-gb18030-0
18804 +# - japanese-x0208: same files as japanese-x0201
18805 +# - japanese-x0212: same files as japanese-x0201
18806 +# - korean: same file as korean-johab
18807 +sequence.fallback=latin-1,latin-2,latin-7,cyrillic-iso8859-5,greek,latin-5,latin-9,\
18808 + arabic,hebrew,thai,\
18809 + chinese-gb18030-0,\
18810 + japanese-x0201,korean-johab,\
18811 + hindi,bengali,telugu,marathi,tamil,gujarati,kannada,malayalam,\
18812 + dejavusans,dingbats,symbol
18814 +# Font File Names
18816 +filename.-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/arial.ttf
18817 +filename.-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/ariali.ttf
18818 +filename.-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/arialbd.ttf
18819 +filename.-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/arialbi.ttf
18820 +filename.-monotype-courier_new-medium-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/cour.ttf
18821 +filename.-monotype-courier_new-medium-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/couri.ttf
18822 +filename.-monotype-courier_new-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/courbd.ttf
18823 +filename.-monotype-courier_new-bold-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/courbi.ttf
18824 +filename.-monotype-times_new_roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/times.ttf
18825 +filename.-monotype-times_new_roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/timesi.ttf
18826 +filename.-monotype-times_new_roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/timesbd.ttf
18827 +filename.-monotype-times_new_roman-bold-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/timesbi.ttf
18829 +filename.-monotype-angsana_new-medium-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/angsa.ttf
18830 +filename.-monotype-angsana_new-medium-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/angsai.ttf
18831 +filename.-monotype-angsana_new-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/angsab.ttf
18832 +filename.-monotype-angsana_new-bold-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/angsaz.ttf
18833 +filename.-monotype-browallia_new-medium-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/browa.ttf
18834 +filename.-monotype-browallia_new-medium-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/browai.ttf
18835 +filename.-monotype-browallia_new-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/browab.ttf
18836 +filename.-monotype-browallia_new-bold-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/browaz.ttf
18837 +filename.-monotype-cordia_new-medium-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/cordia.ttf
18838 +filename.-monotype-cordia_new-medium-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/cordiai.ttf
18839 +filename.-monotype-cordia_new-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/cordiab.ttf
18840 +filename.-monotype-cordia_new-bold-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/cordiaz.ttf
18842 +filename.-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1=/usr/share/fonts/TrueType/ipafont/ipag.otf
18843 +filename.-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1=/usr/share/fonts/TrueType/ipafont/ipam.otf
18844 +filename.-hanyang-gothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1=/usr/share/fonts/TrueType/hanyang/h2gtrm.ttf
18845 +filename.-arphic-uming-medium-r-normal--*-%d-*-*-m-*-iso10646-1=/usr/share/fonts/TrueType/arphic/uming.ttf
18846 +filename.-monotype-symbol-medium-r-normal--*-%d-*-*-p-*-adobe-symbol=/usr/share/fonts/TrueType/core/symbol.ttf
18847 +filename.-microsoft-wingdings-medium-r-normal--*-%d-*-*-p-*-adobe-fontspecific=/usr/share/fonts/TrueType/core/wingdings.ttf
18848 +filename.-misc-lohit_bengali-medium-r-normal--0-0-0-0-p-0-iso10646-1=/usr/share/fonts/TrueType/lohit/Lohit-Bengali.ttf
18849 +filename.-misc-lohit_gujarati-medium-r-normal--0-0-0-0-p-0-iso10646-1=/usr/share/fonts/TrueType/lohit/Lohit-Gujarati.ttf
18850 +filename.-misc-lohit_hindi-medium-r-normal--0-0-0-0-p-0-iso10646-1=/usr/share/fonts/TrueType/lohit/Lohit-Hindi.ttf
18851 +filename.-misc-lohit_kannada-medium-r-normal--0-0-0-0-p-0-iso10646-1=/usr/share/fonts/TrueType/lohit/Lohit-Kannada.ttf
18852 +filename.-misc-lohit_malayalam-medium-r-normal--0-0-0-0-p-0-iso10646-1=/usr/share/fonts/TrueType/lohit/Lohit-Malayalam.ttf
18853 +filename.-misc-lohit_marathi-medium-r-normal--0-0-0-0-p-0-iso10646-1=/usr/share/fonts/TrueType/lohit/Lohit-Marathi.ttf
18854 +filename.-misc-lohit_tamil-medium-r-normal--0-0-0-0-p-0-iso10646-1=/usr/share/fonts/TrueType/lohit/Lohit-Tamil.ttf
18855 +filename.-misc-lohit_telugu-medium-r-normal--0-0-0-0-p-0-iso10646-1=/usr/share/fonts/TrueType/lohit/Lohit-Telugu.ttf
18856 +filename.-misc-dejavu_sans-medium-r-normal--0-0-0-0-p-0-iso10646-1=/usr/share/fonts/TrueType/dejavu/DejaVuSans.ttf
18858 +# AWT X11 font paths
18859 +awtfontpath.latin-1=/usr/share/fonts/TrueType/core
18860 +awtfontpath.latin-2=/usr/share/fonts/TrueType/core
18861 +awtfontpath.latin-5=/usr/share/fonts/TrueType/core
18862 +awtfontpath.latin-7=/usr/share/fonts/TrueType/core
18863 +awtfontpath.latin-9=/usr/share/fonts/TrueType/core
18864 +awtfontpath.hebrew=/usr/share/fonts/TrueType/core
18865 +awtfontpath.arabic=/usr/share/fonts/TrueType/core
18866 +awtfontpath.thai=/usr/share/fonts/TrueType/core
18867 +awtfontpath.greek=/usr/share/fonts/TrueType/core
18868 +awtfontpath.cyrillic-iso8859-5=/usr/share/fonts/TrueType/core
18869 +awtfontpath.cyrillic-cp1251=/usr/share/fonts/TrueType/core
18870 +awtfontpath.cyrillic-koi8-r=/usr/share/fonts/TrueType/core
18871 +awtfontpath.korean=/usr/share/fonts/TrueType/hanyang
18872 +awtfontpath.korean-johab=/usr/share/fonts/TrueType/hanyang
18873 +awtfontpath.japanese-x0201=/usr/share/fonts/TrueType/ipafont
18874 +awtfontpath.japanese-x0208=/usr/share/fonts/TrueType/ipafont
18875 +awtfontpath.japanese-x0212=/usr/share/fonts/TrueType/ipafont
18876 +awtfontpath.chinese-gbk=/usr/share/fonts/TrueType/arphic
18877 +awtfontpath.chinese-cns11643-1=/usr/share/fonts/TrueType/arphic
18878 +awtfontpath.chinese-cns11643-2=/usr/share/fonts/TrueType/arphic
18879 +awtfontpath.chinese-cns11643-3=/usr/share/fonts/TrueType/arphic
18880 +awtfontpath.chinese-big5=/usr/share/fonts/TrueType/arphic
18881 +awtfontpath.chinese-gb2312=/usr/share/fonts/TrueType/arphic
18882 +awtfontpath.chinese-gb18030-0=/usr/share/fonts/TrueType/arphic
18883 +awtfontpath.chinese-gb18030-1=/usr/share/fonts/TrueType/arphic
18884 +awtfontpath.chinese-hkscs=/usr/share/fonts/TrueType/arphic
18885 +awtfontpath.bengali=/usr/share/fonts/TrueType/lohit
18886 +awtfontpath.gujarati=/usr/share/fonts/TrueType/lohit
18887 +awtfontpath.hindi=/usr/share/fonts/TrueType/lohit
18888 +awtfontpath.kannada=/usr/share/fonts/TrueType/lohit
18889 +awtfontpath.malayalam=/usr/share/fonts/TrueType/lohit
18890 +awtfontpath.marathi=/usr/share/fonts/TrueType/lohit
18891 +awtfontpath.tamil=/usr/share/fonts/TrueType/lohit
18892 +awtfontpath.telugu=/usr/share/fonts/TrueType/lohit
18893 +awtfontpath.dejavusans=/usr/share/fonts/TrueType/dejavu
18895 +# Appended Font Path
18897 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_PCM.c jdk21u-jdk-21.0.4-ga/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_PCM.c
18898 --- jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_PCM.c 1970-01-01 01:00:00.000000000 +0100
18899 +++ jdk21u-jdk-21.0.4-ga/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_PCM.c 2024-08-17 19:13:01.470780624 +0200
18900 @@ -0,0 +1,627 @@
18902 + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
18903 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
18905 + * This code is free software; you can redistribute it and/or modify it
18906 + * under the terms of the GNU General Public License version 2 only, as
18907 + * published by the Free Software Foundation. Oracle designates this
18908 + * particular file as subject to the "Classpath" exception as provided
18909 + * by Oracle in the LICENSE file that accompanied this code.
18911 + * This code is distributed in the hope that it will be useful, but WITHOUT
18912 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18913 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18914 + * version 2 for more details (a copy is included in the LICENSE file that
18915 + * accompanied this code).
18917 + * You should have received a copy of the GNU General Public License version
18918 + * 2 along with this work; if not, write to the Free Software Foundation,
18919 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18921 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
18922 + * or visit www.oracle.com if you need additional information or have any
18923 + * questions.
18924 + */
18926 +#define USE_ERROR
18927 +#define USE_TRACE
18929 +#include "PLATFORM_API_SolarisOS_Utils.h"
18930 +#include "DirectAudio.h"
18932 +#if USE_DAUDIO == TRUE
18935 +// The default buffer time
18936 +#define DEFAULT_PERIOD_TIME_MILLIS 50
18938 +///// implemented functions of DirectAudio.h
18940 +INT32 DAUDIO_GetDirectAudioDeviceCount() {
18941 + return (INT32) getAudioDeviceCount();
18945 +INT32 DAUDIO_GetDirectAudioDeviceDescription(INT32 mixerIndex,
18946 + DirectAudioDeviceDescription* description) {
18947 + AudioDeviceDescription desc;
18949 + if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, TRUE)) {
18950 + description->maxSimulLines = desc.maxSimulLines;
18951 + strncpy(description->name, desc.name, DAUDIO_STRING_LENGTH-1);
18952 + description->name[DAUDIO_STRING_LENGTH-1] = 0;
18953 + strncpy(description->vendor, desc.vendor, DAUDIO_STRING_LENGTH-1);
18954 + description->vendor[DAUDIO_STRING_LENGTH-1] = 0;
18955 + strncpy(description->version, desc.version, DAUDIO_STRING_LENGTH-1);
18956 + description->version[DAUDIO_STRING_LENGTH-1] = 0;
18957 + /*strncpy(description->description, desc.description, DAUDIO_STRING_LENGTH-1);*/
18958 + strncpy(description->description, "Solaris Mixer", DAUDIO_STRING_LENGTH-1);
18959 + description->description[DAUDIO_STRING_LENGTH-1] = 0;
18960 + return TRUE;
18962 + return FALSE;
18966 +#define MAX_SAMPLE_RATES 20
18968 +void DAUDIO_GetFormats(INT32 mixerIndex, INT32 deviceID, int isSource, void* creator) {
18969 + int fd = -1;
18970 + AudioDeviceDescription desc;
18971 + am_sample_rates_t *sr;
18972 + /* hardcoded bits and channels */
18973 + int bits[] = {8, 16};
18974 + int bitsCount = 2;
18975 + int channels[] = {1, 2};
18976 + int channelsCount = 2;
18977 + /* for querying sample rates */
18978 + int err;
18979 + int ch, b;
18980 + uint_t s;
18982 + TRACE2("DAUDIO_GetFormats, mixer %d, isSource=%d\n", mixerIndex, isSource);
18983 + if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, FALSE)) {
18984 + fd = open(desc.pathctl, O_RDONLY);
18986 + if (fd < 0) {
18987 + ERROR1("Couldn't open audio device ctl for device %d!\n", mixerIndex);
18988 + return;
18991 + /* get sample rates */
18992 + sr = (am_sample_rates_t*) malloc(AUDIO_MIXER_SAMP_RATES_STRUCT_SIZE(MAX_SAMPLE_RATES));
18993 + if (sr == NULL) {
18994 + ERROR1("DAUDIO_GetFormats: out of memory for mixer %d\n", (int) mixerIndex);
18995 + close(fd);
18996 + return;
18999 + sr->num_samp_rates = MAX_SAMPLE_RATES;
19000 + sr->type = isSource?AUDIO_PLAY:AUDIO_RECORD;
19001 + sr->samp_rates[0] = -2;
19002 + err = ioctl(fd, AUDIO_MIXER_GET_SAMPLE_RATES, sr);
19003 + if (err < 0) {
19004 + ERROR1(" DAUDIO_GetFormats: AUDIO_MIXER_GET_SAMPLE_RATES failed for mixer %d!\n",
19005 + (int)mixerIndex);
19006 + ERROR2(" -> num_sample_rates=%d sample_rates[0] = %d\n",
19007 + (int) sr->num_samp_rates,
19008 + (int) sr->samp_rates[0]);
19009 + /* Some Solaris 8 drivers fail for get sample rates!
19010 + * Do as if we support all sample rates
19011 + */
19012 + sr->flags = MIXER_SR_LIMITS;
19014 + if ((sr->flags & MIXER_SR_LIMITS)
19015 + || (sr->num_samp_rates > MAX_SAMPLE_RATES)) {
19016 +#ifdef USE_TRACE
19017 + if ((sr->flags & MIXER_SR_LIMITS)) {
19018 + TRACE1(" DAUDIO_GetFormats: floating sample rate allowed by mixer %d\n",
19019 + (int)mixerIndex);
19021 + if (sr->num_samp_rates > MAX_SAMPLE_RATES) {
19022 + TRACE2(" DAUDIO_GetFormats: more than %d formats. Use -1 for sample rates mixer %d\n",
19023 + MAX_SAMPLE_RATES, (int)mixerIndex);
19025 +#endif
19026 + /*
19027 + * Fake it to have only one sample rate: -1
19028 + */
19029 + sr->num_samp_rates = 1;
19030 + sr->samp_rates[0] = -1;
19032 + close(fd);
19034 + for (ch = 0; ch < channelsCount; ch++) {
19035 + for (b = 0; b < bitsCount; b++) {
19036 + for (s = 0; s < sr->num_samp_rates; s++) {
19037 + DAUDIO_AddAudioFormat(creator,
19038 + bits[b], /* significant bits */
19039 + 0, /* frameSize: let it be calculated */
19040 + channels[ch],
19041 + (float) ((int) sr->samp_rates[s]),
19042 + DAUDIO_PCM, /* encoding - let's only do PCM */
19043 + (bits[b] > 8)?TRUE:TRUE, /* isSigned */
19044 +#ifdef _LITTLE_ENDIAN
19045 + FALSE /* little endian */
19046 +#else
19047 + (bits[b] > 8)?TRUE:FALSE /* big endian */
19048 +#endif
19049 + );
19053 + free(sr);
19057 +typedef struct {
19058 + int fd;
19059 + audio_info_t info;
19060 + int bufferSizeInBytes;
19061 + int frameSize; /* storage size in Bytes */
19062 + /* how many bytes were written or read */
19063 + INT32 transferedBytes;
19064 + /* if transferedBytes exceed 32-bit boundary,
19065 + * it will be reset and positionOffset will receive
19066 + * the offset
19067 + */
19068 + INT64 positionOffset;
19069 +} SolPcmInfo;
19072 +void* DAUDIO_Open(INT32 mixerIndex, INT32 deviceID, int isSource,
19073 + int encoding, float sampleRate, int sampleSizeInBits,
19074 + int frameSize, int channels,
19075 + int isSigned, int isBigEndian, int bufferSizeInBytes) {
19076 + int err = 0;
19077 + int openMode;
19078 + AudioDeviceDescription desc;
19079 + SolPcmInfo* info;
19081 + TRACE0("> DAUDIO_Open\n");
19082 + if (encoding != DAUDIO_PCM) {
19083 + ERROR1(" DAUDIO_Open: invalid encoding %d\n", (int) encoding);
19084 + return NULL;
19086 + if (channels <= 0) {
19087 + ERROR1(" DAUDIO_Open: Invalid number of channels=%d!\n", channels);
19088 + return NULL;
19091 + info = (SolPcmInfo*) malloc(sizeof(SolPcmInfo));
19092 + if (!info) {
19093 + ERROR0("Out of memory\n");
19094 + return NULL;
19096 + memset(info, 0, sizeof(SolPcmInfo));
19097 + info->frameSize = frameSize;
19098 + info->fd = -1;
19100 + if (isSource) {
19101 + openMode = O_WRONLY;
19102 + } else {
19103 + openMode = O_RDONLY;
19106 +#ifndef __linux__
19107 + /* blackdown does not use NONBLOCK */
19108 + openMode |= O_NONBLOCK;
19109 +#endif
19111 + if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, FALSE)) {
19112 + info->fd = open(desc.path, openMode);
19114 + if (info->fd < 0) {
19115 + ERROR1("Couldn't open audio device for mixer %d!\n", mixerIndex);
19116 + free(info);
19117 + return NULL;
19119 + /* set to multiple open */
19120 + if (ioctl(info->fd, AUDIO_MIXER_MULTIPLE_OPEN, NULL) >= 0) {
19121 + TRACE1("DAUDIO_Open: %s set to multiple open\n", desc.path);
19122 + } else {
19123 + ERROR1("DAUDIO_Open: ioctl AUDIO_MIXER_MULTIPLE_OPEN failed on %s!\n", desc.path);
19126 + AUDIO_INITINFO(&(info->info));
19127 + /* need AUDIO_GETINFO ioctl to get this to work on solaris x86 */
19128 + err = ioctl(info->fd, AUDIO_GETINFO, &(info->info));
19130 + /* not valid to call AUDIO_SETINFO ioctl with all the fields from AUDIO_GETINFO. */
19131 + AUDIO_INITINFO(&(info->info));
19133 + if (isSource) {
19134 + info->info.play.sample_rate = sampleRate;
19135 + info->info.play.precision = sampleSizeInBits;
19136 + info->info.play.channels = channels;
19137 + info->info.play.encoding = AUDIO_ENCODING_LINEAR;
19138 + info->info.play.buffer_size = bufferSizeInBytes;
19139 + info->info.play.pause = 1;
19140 + } else {
19141 + info->info.record.sample_rate = sampleRate;
19142 + info->info.record.precision = sampleSizeInBits;
19143 + info->info.record.channels = channels;
19144 + info->info.record.encoding = AUDIO_ENCODING_LINEAR;
19145 + info->info.record.buffer_size = bufferSizeInBytes;
19146 + info->info.record.pause = 1;
19148 + err = ioctl(info->fd, AUDIO_SETINFO, &(info->info));
19149 + if (err < 0) {
19150 + ERROR0("DAUDIO_Open: could not set info!\n");
19151 + DAUDIO_Close((void*) info, isSource);
19152 + return NULL;
19154 + DAUDIO_Flush((void*) info, isSource);
19156 + err = ioctl(info->fd, AUDIO_GETINFO, &(info->info));
19157 + if (err >= 0) {
19158 + if (isSource) {
19159 + info->bufferSizeInBytes = info->info.play.buffer_size;
19160 + } else {
19161 + info->bufferSizeInBytes = info->info.record.buffer_size;
19163 + TRACE2("DAUDIO: buffersize in bytes: requested=%d, got %d\n",
19164 + (int) bufferSizeInBytes,
19165 + (int) info->bufferSizeInBytes);
19166 + } else {
19167 + ERROR0("DAUDIO_Open: cannot get info!\n");
19168 + DAUDIO_Close((void*) info, isSource);
19169 + return NULL;
19171 + TRACE0("< DAUDIO_Open: Opened device successfully.\n");
19172 + return (void*) info;
19176 +int DAUDIO_Start(void* id, int isSource) {
19177 + SolPcmInfo* info = (SolPcmInfo*) id;
19178 + int err, modified;
19179 + audio_info_t audioInfo;
19181 + TRACE0("> DAUDIO_Start\n");
19183 + AUDIO_INITINFO(&audioInfo);
19184 + err = ioctl(info->fd, AUDIO_GETINFO, &audioInfo);
19185 + if (err >= 0) {
19186 + // unpause
19187 + modified = FALSE;
19188 + if (isSource && audioInfo.play.pause) {
19189 + audioInfo.play.pause = 0;
19190 + modified = TRUE;
19192 + if (!isSource && audioInfo.record.pause) {
19193 + audioInfo.record.pause = 0;
19194 + modified = TRUE;
19196 + if (modified) {
19197 + err = ioctl(info->fd, AUDIO_SETINFO, &audioInfo);
19201 + TRACE1("< DAUDIO_Start %s\n", (err>=0)?"success":"error");
19202 + return (err >= 0)?TRUE:FALSE;
19205 +int DAUDIO_Stop(void* id, int isSource) {
19206 + SolPcmInfo* info = (SolPcmInfo*) id;
19207 + int err, modified;
19208 + audio_info_t audioInfo;
19210 + TRACE0("> DAUDIO_Stop\n");
19212 + AUDIO_INITINFO(&audioInfo);
19213 + err = ioctl(info->fd, AUDIO_GETINFO, &audioInfo);
19214 + if (err >= 0) {
19215 + // pause
19216 + modified = FALSE;
19217 + if (isSource && !audioInfo.play.pause) {
19218 + audioInfo.play.pause = 1;
19219 + modified = TRUE;
19221 + if (!isSource && !audioInfo.record.pause) {
19222 + audioInfo.record.pause = 1;
19223 + modified = TRUE;
19225 + if (modified) {
19226 + err = ioctl(info->fd, AUDIO_SETINFO, &audioInfo);
19230 + TRACE1("< DAUDIO_Stop %s\n", (err>=0)?"success":"error");
19231 + return (err >= 0)?TRUE:FALSE;
19234 +void DAUDIO_Close(void* id, int isSource) {
19235 + SolPcmInfo* info = (SolPcmInfo*) id;
19237 + TRACE0("DAUDIO_Close\n");
19238 + if (info != NULL) {
19239 + if (info->fd >= 0) {
19240 + DAUDIO_Flush(id, isSource);
19241 + close(info->fd);
19243 + free(info);
19247 +#ifndef USE_TRACE
19248 +/* close to 2^31 */
19249 +#define POSITION_MAX 2000000000
19250 +#else
19251 +/* for testing */
19252 +#define POSITION_MAX 1000000
19253 +#endif
19255 +void resetErrorFlagAndAdjustPosition(SolPcmInfo* info, int isSource, int count) {
19256 + audio_info_t audioInfo;
19257 + audio_prinfo_t* prinfo;
19258 + int err;
19259 + int offset = -1;
19260 + int underrun = FALSE;
19261 + int devBytes = 0;
19263 + if (count > 0) {
19264 + info->transferedBytes += count;
19266 + if (isSource) {
19267 + prinfo = &(audioInfo.play);
19268 + } else {
19269 + prinfo = &(audioInfo.record);
19271 + AUDIO_INITINFO(&audioInfo);
19272 + err = ioctl(info->fd, AUDIO_GETINFO, &audioInfo);
19273 + if (err >= 0) {
19274 + underrun = prinfo->error;
19275 + devBytes = prinfo->samples * info->frameSize;
19277 + AUDIO_INITINFO(&audioInfo);
19278 + if (underrun) {
19279 + /* if an underrun occurred, reset */
19280 + ERROR1("DAUDIO_Write/Read: Underrun/overflow: adjusting positionOffset by %d:\n",
19281 + (devBytes - info->transferedBytes));
19282 + ERROR1(" devBytes from %d to 0, ", devBytes);
19283 + ERROR2(" positionOffset from %d to %d ",
19284 + (int) info->positionOffset,
19285 + (int) (info->positionOffset + info->transferedBytes));
19286 + ERROR1(" transferedBytes from %d to 0\n",
19287 + (int) info->transferedBytes);
19288 + prinfo->samples = 0;
19289 + info->positionOffset += info->transferedBytes;
19290 + info->transferedBytes = 0;
19292 + else if (info->transferedBytes > POSITION_MAX) {
19293 + /* we will reset transferedBytes and
19294 + * the samples field in prinfo
19295 + */
19296 + offset = devBytes;
19297 + prinfo->samples = 0;
19299 + /* reset error flag */
19300 + prinfo->error = 0;
19302 + err = ioctl(info->fd, AUDIO_SETINFO, &audioInfo);
19303 + if (err >= 0) {
19304 + if (offset > 0) {
19305 + /* upon exit of AUDIO_SETINFO, the samples parameter
19306 + * was set to the previous value. This is our
19307 + * offset.
19308 + */
19309 + TRACE1("Adjust samplePos: offset=%d, ", (int) offset);
19310 + TRACE2("transferedBytes=%d -> %d, ",
19311 + (int) info->transferedBytes,
19312 + (int) (info->transferedBytes - offset));
19313 + TRACE2("positionOffset=%d -> %d\n",
19314 + (int) (info->positionOffset),
19315 + (int) (((int) info->positionOffset) + offset));
19316 + info->transferedBytes -= offset;
19317 + info->positionOffset += offset;
19319 + } else {
19320 + ERROR0("DAUDIO: resetErrorFlagAndAdjustPosition ioctl failed!\n");
19325 +// returns -1 on error
19326 +int DAUDIO_Write(void* id, char* data, int byteSize) {
19327 + SolPcmInfo* info = (SolPcmInfo*) id;
19328 + int ret = -1;
19330 + TRACE1("> DAUDIO_Write %d bytes\n", byteSize);
19331 + if (info!=NULL) {
19332 + ret = write(info->fd, data, byteSize);
19333 + resetErrorFlagAndAdjustPosition(info, TRUE, ret);
19334 + /* sets ret to -1 if buffer full, no error! */
19335 + if (ret < 0) {
19336 + ret = 0;
19339 + TRACE1("< DAUDIO_Write: returning %d bytes.\n", ret);
19340 + return ret;
19343 +// returns -1 on error
19344 +int DAUDIO_Read(void* id, char* data, int byteSize) {
19345 + SolPcmInfo* info = (SolPcmInfo*) id;
19346 + int ret = -1;
19348 + TRACE1("> DAUDIO_Read %d bytes\n", byteSize);
19349 + if (info != NULL) {
19350 + ret = read(info->fd, data, byteSize);
19351 + resetErrorFlagAndAdjustPosition(info, TRUE, ret);
19352 + /* sets ret to -1 if buffer full, no error! */
19353 + if (ret < 0) {
19354 + ret = 0;
19357 + TRACE1("< DAUDIO_Read: returning %d bytes.\n", ret);
19358 + return ret;
19362 +int DAUDIO_GetBufferSize(void* id, int isSource) {
19363 + SolPcmInfo* info = (SolPcmInfo*) id;
19364 + if (info) {
19365 + return info->bufferSizeInBytes;
19367 + return 0;
19370 +int DAUDIO_StillDraining(void* id, int isSource) {
19371 + SolPcmInfo* info = (SolPcmInfo*) id;
19372 + audio_info_t audioInfo;
19373 + audio_prinfo_t* prinfo;
19374 + int ret = FALSE;
19376 + if (info!=NULL) {
19377 + if (isSource) {
19378 + prinfo = &(audioInfo.play);
19379 + } else {
19380 + prinfo = &(audioInfo.record);
19382 + /* check error flag */
19383 + AUDIO_INITINFO(&audioInfo);
19384 + ioctl(info->fd, AUDIO_GETINFO, &audioInfo);
19385 + ret = (prinfo->error != 0)?FALSE:TRUE;
19387 + return ret;
19391 +int getDevicePosition(SolPcmInfo* info, int isSource) {
19392 + audio_info_t audioInfo;
19393 + audio_prinfo_t* prinfo;
19394 + int err;
19396 + if (isSource) {
19397 + prinfo = &(audioInfo.play);
19398 + } else {
19399 + prinfo = &(audioInfo.record);
19401 + AUDIO_INITINFO(&audioInfo);
19402 + err = ioctl(info->fd, AUDIO_GETINFO, &audioInfo);
19403 + if (err >= 0) {
19404 + /*TRACE2("---> device paused: %d eof=%d\n",
19405 + prinfo->pause, prinfo->eof);
19406 + */
19407 + return (int) (prinfo->samples * info->frameSize);
19409 + ERROR0("DAUDIO: getDevicePosition: ioctl failed!\n");
19410 + return -1;
19413 +int DAUDIO_Flush(void* id, int isSource) {
19414 + SolPcmInfo* info = (SolPcmInfo*) id;
19415 + int err = -1;
19416 + int pos;
19418 + TRACE0("DAUDIO_Flush\n");
19419 + if (info) {
19420 + if (isSource) {
19421 + err = ioctl(info->fd, I_FLUSH, FLUSHW);
19422 + } else {
19423 + err = ioctl(info->fd, I_FLUSH, FLUSHR);
19425 + if (err >= 0) {
19426 + /* resets the transferedBytes parameter to
19427 + * the current samples count of the device
19428 + */
19429 + pos = getDevicePosition(info, isSource);
19430 + if (pos >= 0) {
19431 + info->transferedBytes = pos;
19435 + if (err < 0) {
19436 + ERROR0("ERROR in DAUDIO_Flush\n");
19438 + return (err < 0)?FALSE:TRUE;
19441 +int DAUDIO_GetAvailable(void* id, int isSource) {
19442 + SolPcmInfo* info = (SolPcmInfo*) id;
19443 + int ret = 0;
19444 + int pos;
19446 + if (info) {
19447 + /* unfortunately, the STREAMS architecture
19448 + * seems to not have a method for querying
19449 + * the available bytes to read/write!
19450 + * estimate it...
19451 + */
19452 + pos = getDevicePosition(info, isSource);
19453 + if (pos >= 0) {
19454 + if (isSource) {
19455 + /* we usually have written more bytes
19456 + * to the queue than the device position should be
19457 + */
19458 + ret = (info->bufferSizeInBytes) - (info->transferedBytes - pos);
19459 + } else {
19460 + /* for record, the device stream should
19461 + * be usually ahead of our read actions
19462 + */
19463 + ret = pos - info->transferedBytes;
19465 + if (ret > info->bufferSizeInBytes) {
19466 + ERROR2("DAUDIO_GetAvailable: available=%d, too big at bufferSize=%d!\n",
19467 + (int) ret, (int) info->bufferSizeInBytes);
19468 + ERROR2(" devicePos=%d, transferedBytes=%d\n",
19469 + (int) pos, (int) info->transferedBytes);
19470 + ret = info->bufferSizeInBytes;
19472 + else if (ret < 0) {
19473 + ERROR1("DAUDIO_GetAvailable: available=%d, in theory not possible!\n",
19474 + (int) ret);
19475 + ERROR2(" devicePos=%d, transferedBytes=%d\n",
19476 + (int) pos, (int) info->transferedBytes);
19477 + ret = 0;
19482 + TRACE1("DAUDIO_GetAvailable returns %d bytes\n", ret);
19483 + return ret;
19486 +INT64 DAUDIO_GetBytePosition(void* id, int isSource, INT64 javaBytePos) {
19487 + SolPcmInfo* info = (SolPcmInfo*) id;
19488 + int ret;
19489 + int pos;
19490 + INT64 result = javaBytePos;
19492 + if (info) {
19493 + pos = getDevicePosition(info, isSource);
19494 + if (pos >= 0) {
19495 + result = info->positionOffset + pos;
19499 + //printf("getbyteposition: javaBytePos=%d , return=%d\n", (int) javaBytePos, (int) result);
19500 + return result;
19504 +void DAUDIO_SetBytePosition(void* id, int isSource, INT64 javaBytePos) {
19505 + SolPcmInfo* info = (SolPcmInfo*) id;
19506 + int ret;
19507 + int pos;
19509 + if (info) {
19510 + pos = getDevicePosition(info, isSource);
19511 + if (pos >= 0) {
19512 + info->positionOffset = javaBytePos - pos;
19517 +int DAUDIO_RequiresServicing(void* id, int isSource) {
19518 + // never need servicing on Solaris
19519 + return FALSE;
19522 +void DAUDIO_Service(void* id, int isSource) {
19523 + // never need servicing on Solaris
19527 +#endif // USE_DAUDIO
19528 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Ports.c jdk21u-jdk-21.0.4-ga/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Ports.c
19529 --- jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Ports.c 1970-01-01 01:00:00.000000000 +0100
19530 +++ jdk21u-jdk-21.0.4-ga/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Ports.c 2024-08-17 19:13:01.471372711 +0200
19531 @@ -0,0 +1,600 @@
19533 + * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
19534 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
19536 + * This code is free software; you can redistribute it and/or modify it
19537 + * under the terms of the GNU General Public License version 2 only, as
19538 + * published by the Free Software Foundation. Oracle designates this
19539 + * particular file as subject to the "Classpath" exception as provided
19540 + * by Oracle in the LICENSE file that accompanied this code.
19542 + * This code is distributed in the hope that it will be useful, but WITHOUT
19543 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19544 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19545 + * version 2 for more details (a copy is included in the LICENSE file that
19546 + * accompanied this code).
19548 + * You should have received a copy of the GNU General Public License version
19549 + * 2 along with this work; if not, write to the Free Software Foundation,
19550 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19552 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19553 + * or visit www.oracle.com if you need additional information or have any
19554 + * questions.
19555 + */
19557 +#define USE_ERROR
19558 +//#define USE_TRACE
19560 +#include "Ports.h"
19561 +#include "PLATFORM_API_SolarisOS_Utils.h"
19563 +#if USE_PORTS == TRUE
19565 +#define MONITOR_GAIN_STRING "Monitor Gain"
19567 +#define ALL_TARGET_PORT_COUNT 6
19569 +// define the following to not use audio_prinfo_t.mod_ports
19570 +#define SOLARIS7_COMPATIBLE
19572 +// Solaris audio defines
19573 +static int targetPorts[ALL_TARGET_PORT_COUNT] = {
19574 + AUDIO_SPEAKER,
19575 + AUDIO_HEADPHONE,
19576 + AUDIO_LINE_OUT,
19577 + AUDIO_AUX1_OUT,
19578 + AUDIO_AUX2_OUT,
19579 + AUDIO_SPDIF_OUT
19582 +static char* targetPortNames[ALL_TARGET_PORT_COUNT] = {
19583 + "Speaker",
19584 + "Headphone",
19585 + "Line Out",
19586 + "AUX1 Out",
19587 + "AUX2 Out",
19588 + "SPDIF Out"
19591 +// defined in Ports.h
19592 +static int targetPortJavaSoundMapping[ALL_TARGET_PORT_COUNT] = {
19593 + PORT_DST_SPEAKER,
19594 + PORT_DST_HEADPHONE,
19595 + PORT_DST_LINE_OUT,
19596 + PORT_DST_UNKNOWN,
19597 + PORT_DST_UNKNOWN,
19598 + PORT_DST_UNKNOWN,
19601 +#define ALL_SOURCE_PORT_COUNT 7
19603 +// Solaris audio defines
19604 +static int sourcePorts[ALL_SOURCE_PORT_COUNT] = {
19605 + AUDIO_MICROPHONE,
19606 + AUDIO_LINE_IN,
19607 + AUDIO_CD,
19608 + AUDIO_AUX1_IN,
19609 + AUDIO_AUX2_IN,
19610 + AUDIO_SPDIF_IN,
19611 + AUDIO_CODEC_LOOPB_IN
19614 +static char* sourcePortNames[ALL_SOURCE_PORT_COUNT] = {
19615 + "Microphone In",
19616 + "Line In",
19617 + "Compact Disc In",
19618 + "AUX1 In",
19619 + "AUX2 In",
19620 + "SPDIF In",
19621 + "Internal Loopback"
19624 +// Ports.h defines
19625 +static int sourcePortJavaSoundMapping[ALL_SOURCE_PORT_COUNT] = {
19626 + PORT_SRC_MICROPHONE,
19627 + PORT_SRC_LINE_IN,
19628 + PORT_SRC_COMPACT_DISC,
19629 + PORT_SRC_UNKNOWN,
19630 + PORT_SRC_UNKNOWN,
19631 + PORT_SRC_UNKNOWN,
19632 + PORT_SRC_UNKNOWN
19635 +struct tag_PortControlID;
19637 +typedef struct tag_PortInfo {
19638 + int fd; // file descriptor of the pseudo device
19639 + audio_info_t audioInfo;
19640 + // ports
19641 + int targetPortCount;
19642 + int sourcePortCount;
19643 + // indexes to sourcePorts/targetPorts
19644 + // contains first target ports, then source ports
19645 + int ports[ALL_TARGET_PORT_COUNT + ALL_SOURCE_PORT_COUNT];
19646 + // controls
19647 + int maxControlCount; // upper bound of number of controls
19648 + int usedControlIDs; // number of items already filled in controlIDs
19649 + struct tag_PortControlID* controlIDs; // the control IDs themselves
19650 +} PortInfo;
19652 +#define PORT_CONTROL_TYPE_PLAY 0x4000000
19653 +#define PORT_CONTROL_TYPE_RECORD 0x8000000
19654 +#define PORT_CONTROL_TYPE_SELECT_PORT 1
19655 +#define PORT_CONTROL_TYPE_GAIN 2
19656 +#define PORT_CONTROL_TYPE_BALANCE 3
19657 +#define PORT_CONTROL_TYPE_MONITOR_GAIN 10
19658 +#define PORT_CONTROL_TYPE_OUTPUT_MUTED 11
19659 +#define PORT_CONTROL_TYPE_PLAYRECORD_MASK PORT_CONTROL_TYPE_PLAY | PORT_CONTROL_TYPE_RECORD
19660 +#define PORT_CONTROL_TYPE_MASK 0xFFFFFF
19663 +typedef struct tag_PortControlID {
19664 + PortInfo* portInfo;
19665 + INT32 controlType; // PORT_CONTROL_TYPE_XX
19666 + uint_t port;
19667 +} PortControlID;
19670 +///// implemented functions of Ports.h
19672 +INT32 PORT_GetPortMixerCount() {
19673 + return (INT32) getAudioDeviceCount();
19677 +INT32 PORT_GetPortMixerDescription(INT32 mixerIndex, PortMixerDescription* description) {
19678 + AudioDeviceDescription desc;
19680 + if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, TRUE)) {
19681 + strncpy(description->name, desc.name, PORT_STRING_LENGTH-1);
19682 + description->name[PORT_STRING_LENGTH-1] = 0;
19683 + strncpy(description->vendor, desc.vendor, PORT_STRING_LENGTH-1);
19684 + description->vendor[PORT_STRING_LENGTH-1] = 0;
19685 + strncpy(description->version, desc.version, PORT_STRING_LENGTH-1);
19686 + description->version[PORT_STRING_LENGTH-1] = 0;
19687 + /*strncpy(description->description, desc.description, PORT_STRING_LENGTH-1);*/
19688 + strncpy(description->description, "Solaris Ports", PORT_STRING_LENGTH-1);
19689 + description->description[PORT_STRING_LENGTH-1] = 0;
19690 + return TRUE;
19692 + return FALSE;
19696 +void* PORT_Open(INT32 mixerIndex) {
19697 + PortInfo* info = NULL;
19698 + int fd = -1;
19699 + AudioDeviceDescription desc;
19700 + int success = FALSE;
19702 + TRACE0("PORT_Open\n");
19703 + if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, FALSE)) {
19704 + fd = open(desc.pathctl, O_RDWR);
19706 + if (fd < 0) {
19707 + ERROR1("Couldn't open audio device ctl for device %d!\n", mixerIndex);
19708 + return NULL;
19711 + info = (PortInfo*) malloc(sizeof(PortInfo));
19712 + if (info != NULL) {
19713 + memset(info, 0, sizeof(PortInfo));
19714 + info->fd = fd;
19715 + success = TRUE;
19717 + if (!success) {
19718 + if (fd >= 0) {
19719 + close(fd);
19721 + PORT_Close((void*) info);
19722 + info = NULL;
19724 + return info;
19727 +void PORT_Close(void* id) {
19728 + TRACE0("PORT_Close\n");
19729 + if (id != NULL) {
19730 + PortInfo* info = (PortInfo*) id;
19731 + if (info->fd >= 0) {
19732 + close(info->fd);
19733 + info->fd = -1;
19735 + if (info->controlIDs) {
19736 + free(info->controlIDs);
19737 + info->controlIDs = NULL;
19739 + free(info);
19745 +INT32 PORT_GetPortCount(void* id) {
19746 + int ret = 0;
19747 + PortInfo* info = (PortInfo*) id;
19748 + if (info != NULL) {
19749 + if (!info->targetPortCount && !info->sourcePortCount) {
19750 + int i;
19751 + AUDIO_INITINFO(&info->audioInfo);
19752 + if (ioctl(info->fd, AUDIO_GETINFO, &info->audioInfo) >= 0) {
19753 + for (i = 0; i < ALL_TARGET_PORT_COUNT; i++) {
19754 + if (info->audioInfo.play.avail_ports & targetPorts[i]) {
19755 + info->ports[info->targetPortCount] = i;
19756 + info->targetPortCount++;
19758 +#ifdef SOLARIS7_COMPATIBLE
19759 + TRACE3("Target %d %s: avail=%d\n", i, targetPortNames[i],
19760 + info->audioInfo.play.avail_ports & targetPorts[i]);
19761 +#else
19762 + TRACE4("Target %d %s: avail=%d mod=%d\n", i, targetPortNames[i],
19763 + info->audioInfo.play.avail_ports & targetPorts[i],
19764 + info->audioInfo.play.mod_ports & targetPorts[i]);
19765 +#endif
19767 + for (i = 0; i < ALL_SOURCE_PORT_COUNT; i++) {
19768 + if (info->audioInfo.record.avail_ports & sourcePorts[i]) {
19769 + info->ports[info->targetPortCount + info->sourcePortCount] = i;
19770 + info->sourcePortCount++;
19772 +#ifdef SOLARIS7_COMPATIBLE
19773 + TRACE3("Source %d %s: avail=%d\n", i, sourcePortNames[i],
19774 + info->audioInfo.record.avail_ports & sourcePorts[i]);
19775 +#else
19776 + TRACE4("Source %d %s: avail=%d mod=%d\n", i, sourcePortNames[i],
19777 + info->audioInfo.record.avail_ports & sourcePorts[i],
19778 + info->audioInfo.record.mod_ports & sourcePorts[i]);
19779 +#endif
19783 + ret = info->targetPortCount + info->sourcePortCount;
19785 + return ret;
19788 +int isSourcePort(PortInfo* info, INT32 portIndex) {
19789 + return (portIndex >= info->targetPortCount);
19792 +INT32 PORT_GetPortType(void* id, INT32 portIndex) {
19793 + PortInfo* info = (PortInfo*) id;
19794 + if ((portIndex >= 0) && (portIndex < PORT_GetPortCount(id))) {
19795 + if (isSourcePort(info, portIndex)) {
19796 + return sourcePortJavaSoundMapping[info->ports[portIndex]];
19797 + } else {
19798 + return targetPortJavaSoundMapping[info->ports[portIndex]];
19801 + return 0;
19804 +// pre-condition: portIndex must have been verified!
19805 +char* getPortName(PortInfo* info, INT32 portIndex) {
19806 + char* ret = NULL;
19808 + if (isSourcePort(info, portIndex)) {
19809 + ret = sourcePortNames[info->ports[portIndex]];
19810 + } else {
19811 + ret = targetPortNames[info->ports[portIndex]];
19813 + return ret;
19816 +INT32 PORT_GetPortName(void* id, INT32 portIndex, char* name, INT32 len) {
19817 + PortInfo* info = (PortInfo*) id;
19818 + char* n;
19820 + if ((portIndex >= 0) && (portIndex < PORT_GetPortCount(id))) {
19821 + n = getPortName(info, portIndex);
19822 + if (n) {
19823 + strncpy(name, n, len-1);
19824 + name[len-1] = 0;
19825 + return TRUE;
19828 + return FALSE;
19831 +void createPortControl(PortInfo* info, PortControlCreator* creator, INT32 portIndex,
19832 + INT32 type, void** controlObjects, int* controlCount) {
19833 + PortControlID* controlID;
19834 + void* newControl = NULL;
19835 + int controlIndex;
19836 + char* jsType = NULL;
19837 + int isBoolean = FALSE;
19839 + TRACE0(">createPortControl\n");
19841 + // fill the ControlID structure and add this control
19842 + if (info->usedControlIDs >= info->maxControlCount) {
19843 + ERROR1("not enough free controlIDs !! maxControlIDs = %d\n", info->maxControlCount);
19844 + return;
19846 + controlID = &(info->controlIDs[info->usedControlIDs]);
19847 + controlID->portInfo = info;
19848 + controlID->controlType = type;
19849 + controlIndex = info->ports[portIndex];
19850 + if (isSourcePort(info, portIndex)) {
19851 + controlID->port = sourcePorts[controlIndex];
19852 + } else {
19853 + controlID->port = targetPorts[controlIndex];
19855 + switch (type & PORT_CONTROL_TYPE_MASK) {
19856 + case PORT_CONTROL_TYPE_SELECT_PORT:
19857 + jsType = CONTROL_TYPE_SELECT; isBoolean = TRUE; break;
19858 + case PORT_CONTROL_TYPE_GAIN:
19859 + jsType = CONTROL_TYPE_VOLUME; break;
19860 + case PORT_CONTROL_TYPE_BALANCE:
19861 + jsType = CONTROL_TYPE_BALANCE; break;
19862 + case PORT_CONTROL_TYPE_MONITOR_GAIN:
19863 + jsType = CONTROL_TYPE_VOLUME; break;
19864 + case PORT_CONTROL_TYPE_OUTPUT_MUTED:
19865 + jsType = CONTROL_TYPE_MUTE; isBoolean = TRUE; break;
19867 + if (isBoolean) {
19868 + TRACE0(" PORT_CONTROL_TYPE_BOOLEAN\n");
19869 + newControl = (creator->newBooleanControl)(creator, controlID, jsType);
19871 + else if (jsType == CONTROL_TYPE_BALANCE) {
19872 + TRACE0(" PORT_CONTROL_TYPE_BALANCE\n");
19873 + newControl = (creator->newFloatControl)(creator, controlID, jsType,
19874 + -1.0f, 1.0f, 2.0f / 65.0f, "");
19875 + } else {
19876 + TRACE0(" PORT_CONTROL_TYPE_FLOAT\n");
19877 + newControl = (creator->newFloatControl)(creator, controlID, jsType,
19878 + 0.0f, 1.0f, 1.0f / 256.0f, "");
19880 + if (newControl) {
19881 + controlObjects[*controlCount] = newControl;
19882 + (*controlCount)++;
19883 + info->usedControlIDs++;
19885 + TRACE0("<createPortControl\n");
19889 +void addCompoundControl(PortInfo* info, PortControlCreator* creator, char* name, void** controlObjects, int* controlCount) {
19890 + void* compControl;
19892 + TRACE1(">addCompoundControl %d controls\n", *controlCount);
19893 + if (*controlCount) {
19894 + // create compound control and add it to the vector
19895 + compControl = (creator->newCompoundControl)(creator, name, controlObjects, *controlCount);
19896 + if (compControl) {
19897 + TRACE1(" addCompoundControl: calling addControl %p\n", compControl);
19898 + (creator->addControl)(creator, compControl);
19900 + *controlCount = 0;
19902 + TRACE0("<addCompoundControl\n");
19905 +void addAllControls(PortInfo* info, PortControlCreator* creator, void** controlObjects, int* controlCount) {
19906 + int i = 0;
19908 + TRACE0(">addAllControl\n");
19909 + // go through all controls and add them to the vector
19910 + for (i = 0; i < *controlCount; i++) {
19911 + (creator->addControl)(creator, controlObjects[i]);
19913 + *controlCount = 0;
19914 + TRACE0("<addAllControl\n");
19917 +void PORT_GetControls(void* id, INT32 portIndex, PortControlCreator* creator) {
19918 + PortInfo* info = (PortInfo*) id;
19919 + int portCount = PORT_GetPortCount(id);
19920 + void* controls[4];
19921 + int controlCount = 0;
19922 + INT32 type;
19923 + int selectable = 1;
19924 + memset(controls, 0, sizeof(controls));
19926 + TRACE4(">PORT_GetControls(id=%p, portIndex=%d). controlIDs=%p, maxControlCount=%d\n",
19927 + id, portIndex, info->controlIDs, info->maxControlCount);
19928 + if ((portIndex >= 0) && (portIndex < portCount)) {
19929 + // if the memory isn't reserved for the control structures, allocate it
19930 + if (!info->controlIDs) {
19931 + int maxCount = 0;
19932 + TRACE0("getControl: allocate mem\n");
19933 + // get a maximum number of controls:
19934 + // each port has a select, balance, and volume control.
19935 + maxCount = 3 * portCount;
19936 + // then there is monitorGain and outputMuted
19937 + maxCount += (2 * info->targetPortCount);
19938 + info->maxControlCount = maxCount;
19939 + info->controlIDs = (PortControlID*) malloc(sizeof(PortControlID) * maxCount);
19941 + if (!isSourcePort(info, portIndex)) {
19942 + type = PORT_CONTROL_TYPE_PLAY;
19943 + // add master mute control
19944 + createPortControl(info, creator, portIndex,
19945 + type | PORT_CONTROL_TYPE_OUTPUT_MUTED,
19946 + controls, &controlCount);
19947 + addAllControls(info, creator, controls, &controlCount);
19948 +#ifdef SOLARIS7_COMPATIBLE
19949 + selectable = info->audioInfo.play.avail_ports & targetPorts[info->ports[portIndex]];
19950 +#else
19951 + selectable = info->audioInfo.play.mod_ports & targetPorts[info->ports[portIndex]];
19952 +#endif
19953 + } else {
19954 + type = PORT_CONTROL_TYPE_RECORD;
19955 +#ifdef SOLARIS7_COMPATIBLE
19956 + selectable = info->audioInfo.record.avail_ports & sourcePorts[info->ports[portIndex]];
19957 +#else
19958 + selectable = info->audioInfo.record.mod_ports & sourcePorts[info->ports[portIndex]];
19959 +#endif
19961 + // add a mixer strip with volume, ...
19962 + createPortControl(info, creator, portIndex,
19963 + type | PORT_CONTROL_TYPE_GAIN,
19964 + controls, &controlCount);
19965 + // ... balance, ...
19966 + createPortControl(info, creator, portIndex,
19967 + type | PORT_CONTROL_TYPE_BALANCE,
19968 + controls, &controlCount);
19969 + // ... and select control (if not always on)...
19970 + if (selectable) {
19971 + createPortControl(info, creator, portIndex,
19972 + type | PORT_CONTROL_TYPE_SELECT_PORT,
19973 + controls, &controlCount);
19975 + // ... packaged in a compound control.
19976 + addCompoundControl(info, creator, getPortName(info, portIndex), controls, &controlCount);
19978 + if (type == PORT_CONTROL_TYPE_PLAY) {
19979 + // add a single strip for source ports with monitor gain
19980 + createPortControl(info, creator, portIndex,
19981 + type | PORT_CONTROL_TYPE_MONITOR_GAIN,
19982 + controls, &controlCount);
19983 + // also in a compound control
19984 + addCompoundControl(info, creator, MONITOR_GAIN_STRING, controls, &controlCount);
19987 + TRACE0("< PORT_getControls\n");
19990 +INT32 PORT_GetIntValue(void* controlIDV) {
19991 + PortControlID* controlID = (PortControlID*) controlIDV;
19992 + audio_info_t audioInfo;
19993 + audio_prinfo_t* prinfo;
19995 + AUDIO_INITINFO(&audioInfo);
19996 + if (ioctl(controlID->portInfo->fd, AUDIO_GETINFO, &audioInfo) >= 0) {
19997 + if (controlID->controlType & PORT_CONTROL_TYPE_PLAY) {
19998 + prinfo = &(audioInfo.play);
19999 + } else {
20000 + prinfo = &(audioInfo.record);
20002 + switch (controlID->controlType & PORT_CONTROL_TYPE_MASK) {
20003 + case PORT_CONTROL_TYPE_SELECT_PORT:
20004 + return (prinfo->port & controlID->port)?TRUE:FALSE;
20005 + case PORT_CONTROL_TYPE_OUTPUT_MUTED:
20006 + return (audioInfo.output_muted)?TRUE:FALSE;
20007 + default:
20008 + ERROR1("PORT_GetIntValue: Wrong type %d !\n", controlID->controlType & PORT_CONTROL_TYPE_MASK);
20011 + ERROR0("PORT_GetIntValue: Could not ioctl!\n");
20012 + return 0;
20015 +void PORT_SetIntValue(void* controlIDV, INT32 value) {
20016 + PortControlID* controlID = (PortControlID*) controlIDV;
20017 + audio_info_t audioInfo;
20018 + audio_prinfo_t* prinfo;
20019 + int setPort;
20021 + if (controlID->controlType & PORT_CONTROL_TYPE_PLAY) {
20022 + prinfo = &(audioInfo.play);
20023 + } else {
20024 + prinfo = &(audioInfo.record);
20026 + switch (controlID->controlType & PORT_CONTROL_TYPE_MASK) {
20027 + case PORT_CONTROL_TYPE_SELECT_PORT:
20028 + // first try to just add this port. if that fails, set ONLY to this port.
20029 + AUDIO_INITINFO(&audioInfo);
20030 + if (ioctl(controlID->portInfo->fd, AUDIO_GETINFO, &audioInfo) >= 0) {
20031 + if (value) {
20032 + setPort = (prinfo->port | controlID->port);
20033 + } else {
20034 + setPort = (prinfo->port - controlID->port);
20036 + AUDIO_INITINFO(&audioInfo);
20037 + prinfo->port = setPort;
20038 + if (ioctl(controlID->portInfo->fd, AUDIO_SETINFO, &audioInfo) < 0) {
20039 + // didn't work. Either this line doesn't support to select several
20040 + // ports at once (e.g. record), or a real error
20041 + if (value) {
20042 + // set to ONLY this port (and disable any other currently selected ports)
20043 + AUDIO_INITINFO(&audioInfo);
20044 + prinfo->port = controlID->port;
20045 + if (ioctl(controlID->portInfo->fd, AUDIO_SETINFO, &audioInfo) < 0) {
20046 + ERROR2("Error setting output select port %d to port %d!\n", controlID->port, controlID->port);
20048 + } else {
20049 + // assume it's an error
20050 + ERROR2("Error setting output select port %d to port %d!\n", controlID->port, setPort);
20053 + break;
20054 + case PORT_CONTROL_TYPE_OUTPUT_MUTED:
20055 + AUDIO_INITINFO(&audioInfo);
20056 + audioInfo.output_muted = (value?TRUE:FALSE);
20057 + if (ioctl(controlID->portInfo->fd, AUDIO_SETINFO, &audioInfo) < 0) {
20058 + ERROR2("Error setting output muted on port %d to %d!\n", controlID->port, value);
20060 + break;
20061 + default:
20062 + ERROR1("PORT_SetIntValue: Wrong type %d !\n", controlID->controlType & PORT_CONTROL_TYPE_MASK);
20067 +float PORT_GetFloatValue(void* controlIDV) {
20068 + PortControlID* controlID = (PortControlID*) controlIDV;
20069 + audio_info_t audioInfo;
20070 + audio_prinfo_t* prinfo;
20072 + AUDIO_INITINFO(&audioInfo);
20073 + if (ioctl(controlID->portInfo->fd, AUDIO_GETINFO, &audioInfo) >= 0) {
20074 + if (controlID->controlType & PORT_CONTROL_TYPE_PLAY) {
20075 + prinfo = &(audioInfo.play);
20076 + } else {
20077 + prinfo = &(audioInfo.record);
20079 + switch (controlID->controlType & PORT_CONTROL_TYPE_MASK) {
20080 + case PORT_CONTROL_TYPE_GAIN:
20081 + return ((float) (prinfo->gain - AUDIO_MIN_GAIN))
20082 + / ((float) (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN));
20083 + case PORT_CONTROL_TYPE_BALANCE:
20084 + return ((float) ((prinfo->balance - AUDIO_LEFT_BALANCE - AUDIO_MID_BALANCE) << 1))
20085 + / ((float) (AUDIO_RIGHT_BALANCE - AUDIO_LEFT_BALANCE));
20086 + case PORT_CONTROL_TYPE_MONITOR_GAIN:
20087 + return ((float) (audioInfo.monitor_gain - AUDIO_MIN_GAIN))
20088 + / ((float) (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN));
20089 + default:
20090 + ERROR1("PORT_GetFloatValue: Wrong type %d !\n", controlID->controlType & PORT_CONTROL_TYPE_MASK);
20093 + ERROR0("PORT_GetFloatValue: Could not ioctl!\n");
20094 + return 0.0f;
20097 +void PORT_SetFloatValue(void* controlIDV, float value) {
20098 + PortControlID* controlID = (PortControlID*) controlIDV;
20099 + audio_info_t audioInfo;
20100 + audio_prinfo_t* prinfo;
20102 + AUDIO_INITINFO(&audioInfo);
20104 + if (controlID->controlType & PORT_CONTROL_TYPE_PLAY) {
20105 + prinfo = &(audioInfo.play);
20106 + } else {
20107 + prinfo = &(audioInfo.record);
20109 + switch (controlID->controlType & PORT_CONTROL_TYPE_MASK) {
20110 + case PORT_CONTROL_TYPE_GAIN:
20111 + prinfo->gain = AUDIO_MIN_GAIN
20112 + + (int) ((value * ((float) (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN))) + 0.5f);
20113 + break;
20114 + case PORT_CONTROL_TYPE_BALANCE:
20115 + prinfo->balance = AUDIO_LEFT_BALANCE + AUDIO_MID_BALANCE
20116 + + ((int) (value * ((float) ((AUDIO_RIGHT_BALANCE - AUDIO_LEFT_BALANCE) >> 1))) + 0.5f);
20117 + break;
20118 + case PORT_CONTROL_TYPE_MONITOR_GAIN:
20119 + audioInfo.monitor_gain = AUDIO_MIN_GAIN
20120 + + (int) ((value * ((float) (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN))) + 0.5f);
20121 + break;
20122 + default:
20123 + ERROR1("PORT_SetFloatValue: Wrong type %d !\n", controlID->controlType & PORT_CONTROL_TYPE_MASK);
20124 + return;
20126 + if (ioctl(controlID->portInfo->fd, AUDIO_SETINFO, &audioInfo) < 0) {
20127 + ERROR0("PORT_SetFloatValue: Could not ioctl!\n");
20131 +#endif // USE_PORTS
20132 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Utils.c jdk21u-jdk-21.0.4-ga/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Utils.c
20133 --- jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Utils.c 1970-01-01 01:00:00.000000000 +0100
20134 +++ jdk21u-jdk-21.0.4-ga/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Utils.c 2024-08-17 19:13:01.471726438 +0200
20135 @@ -0,0 +1,193 @@
20137 + * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
20138 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
20140 + * This code is free software; you can redistribute it and/or modify it
20141 + * under the terms of the GNU General Public License version 2 only, as
20142 + * published by the Free Software Foundation. Oracle designates this
20143 + * particular file as subject to the "Classpath" exception as provided
20144 + * by Oracle in the LICENSE file that accompanied this code.
20146 + * This code is distributed in the hope that it will be useful, but WITHOUT
20147 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20148 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20149 + * version 2 for more details (a copy is included in the LICENSE file that
20150 + * accompanied this code).
20152 + * You should have received a copy of the GNU General Public License version
20153 + * 2 along with this work; if not, write to the Free Software Foundation,
20154 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20156 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20157 + * or visit www.oracle.com if you need additional information or have any
20158 + * questions.
20159 + */
20161 +#define USE_ERROR
20162 +#define USE_TRACE
20164 +#include "PLATFORM_API_SolarisOS_Utils.h"
20166 +#define MAX_AUDIO_DEVICES 20
20168 +// not thread safe...
20169 +static AudioDevicePath globalADPaths[MAX_AUDIO_DEVICES];
20170 +static int globalADCount = -1;
20171 +static int globalADCacheTime = -1;
20172 +/* how many seconds do we cache devices */
20173 +#define AD_CACHE_TIME 30
20175 +// return seconds
20176 +long getTimeInSeconds() {
20177 + struct timeval tv;
20178 + gettimeofday(&tv, NULL);
20179 + return tv.tv_sec;
20183 +int getAudioDeviceCount() {
20184 + int count = MAX_AUDIO_DEVICES;
20186 + getAudioDevices(globalADPaths, &count);
20187 + return count;
20190 +/* returns TRUE if the path exists at all */
20191 +int addAudioDevice(char* path, AudioDevicePath* adPath, int* count) {
20192 + int i;
20193 + int found = 0;
20194 + int fileExists = 0;
20195 + // not thread safe...
20196 + static struct stat statBuf;
20198 + // get stats on the file
20199 + if (stat(path, &statBuf) == 0) {
20200 + // file exists.
20201 + fileExists = 1;
20202 + // If it is not yet in the adPath array, add it to the array
20203 + for (i = 0; i < *count; i++) {
20204 + if (adPath[i].st_ino == statBuf.st_ino
20205 + && adPath[i].st_dev == statBuf.st_dev) {
20206 + found = 1;
20207 + break;
20210 + if (!found) {
20211 + adPath[*count].st_ino = statBuf.st_ino;
20212 + adPath[*count].st_dev = statBuf.st_dev;
20213 + strncpy(adPath[*count].path, path, MAX_NAME_LENGTH);
20214 + adPath[*count].path[MAX_NAME_LENGTH - 1] = 0;
20215 + (*count)++;
20216 + TRACE1("Added audio device %s\n", path);
20219 + return fileExists;
20223 +void getAudioDevices(AudioDevicePath* adPath, int* count) {
20224 + int maxCount = *count;
20225 + char* audiodev;
20226 + char devsound[15];
20227 + int i;
20228 + long timeInSeconds = getTimeInSeconds();
20230 + if (globalADCount < 0
20231 + || (getTimeInSeconds() - globalADCacheTime) > AD_CACHE_TIME
20232 + || (adPath != globalADPaths)) {
20233 + *count = 0;
20234 + // first device, if set, is AUDIODEV variable
20235 + audiodev = getenv("AUDIODEV");
20236 + if (audiodev != NULL && audiodev[0] != 0) {
20237 + addAudioDevice(audiodev, adPath, count);
20239 + // then try /dev/audio
20240 + addAudioDevice("/dev/audio", adPath, count);
20241 + // then go through all of the /dev/sound/? devices
20242 + for (i = 0; i < 100; i++) {
20243 + sprintf(devsound, "/dev/sound/%d", i);
20244 + if (!addAudioDevice(devsound, adPath, count)) {
20245 + break;
20248 + if (adPath == globalADPaths) {
20249 + /* commit cache */
20250 + globalADCount = *count;
20251 + /* set cache time */
20252 + globalADCacheTime = timeInSeconds;
20254 + } else {
20255 + /* return cache */
20256 + *count = globalADCount;
20258 + // that's it
20261 +int getAudioDeviceDescriptionByIndex(int index, AudioDeviceDescription* adDesc, int getNames) {
20262 + int count = MAX_AUDIO_DEVICES;
20263 + int ret = 0;
20265 + getAudioDevices(globalADPaths, &count);
20266 + if (index>=0 && index < count) {
20267 + ret = getAudioDeviceDescription(globalADPaths[index].path, adDesc, getNames);
20269 + return ret;
20272 +int getAudioDeviceDescription(char* path, AudioDeviceDescription* adDesc, int getNames) {
20273 + int fd;
20274 + int mixerMode;
20275 + int len;
20276 + audio_info_t info;
20277 + audio_device_t deviceInfo;
20279 + strncpy(adDesc->path, path, MAX_NAME_LENGTH);
20280 + adDesc->path[MAX_NAME_LENGTH] = 0;
20281 + strcpy(adDesc->pathctl, adDesc->path);
20282 + strcat(adDesc->pathctl, "ctl");
20283 + strcpy(adDesc->name, adDesc->path);
20284 + adDesc->vendor[0] = 0;
20285 + adDesc->version[0] = 0;
20286 + adDesc->description[0] = 0;
20287 + adDesc->maxSimulLines = 1;
20289 + // try to open the pseudo device and get more information
20290 + fd = open(adDesc->pathctl, O_WRONLY | O_NONBLOCK);
20291 + if (fd >= 0) {
20292 + close(fd);
20293 + if (getNames) {
20294 + fd = open(adDesc->pathctl, O_RDONLY);
20295 + if (fd >= 0) {
20296 + if (ioctl(fd, AUDIO_GETDEV, &deviceInfo) >= 0) {
20297 + strncpy(adDesc->vendor, deviceInfo.name, MAX_AUDIO_DEV_LEN);
20298 + adDesc->vendor[MAX_AUDIO_DEV_LEN] = 0;
20299 + strncpy(adDesc->version, deviceInfo.version, MAX_AUDIO_DEV_LEN);
20300 + adDesc->version[MAX_AUDIO_DEV_LEN] = 0;
20301 + /* add config string to the dev name
20302 + * creates a string like "/dev/audio (onboard1)"
20303 + */
20304 + len = strlen(adDesc->name) + 1;
20305 + if (MAX_NAME_LENGTH - len > 3) {
20306 + strcat(adDesc->name, " (");
20307 + strncat(adDesc->name, deviceInfo.config, MAX_NAME_LENGTH - len);
20308 + strcat(adDesc->name, ")");
20310 + adDesc->name[MAX_NAME_LENGTH-1] = 0;
20312 + if (ioctl(fd, AUDIO_MIXERCTL_GET_MODE, &mixerMode) >= 0) {
20313 + if (mixerMode == AM_MIXER_MODE) {
20314 + TRACE1(" getAudioDeviceDescription: %s is in mixer mode\n", adDesc->path);
20315 + adDesc->maxSimulLines = -1;
20317 + } else {
20318 + ERROR1("ioctl AUDIO_MIXERCTL_GET_MODE failed on %s!\n", adDesc->path);
20320 + close(fd);
20321 + } else {
20322 + ERROR1("could not open %s!\n", adDesc->pathctl);
20325 + return 1;
20327 + return 0;
20329 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Utils.h jdk21u-jdk-21.0.4-ga/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Utils.h
20330 --- jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Utils.h 1970-01-01 01:00:00.000000000 +0100
20331 +++ jdk21u-jdk-21.0.4-ga/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Utils.h 2024-08-17 19:13:01.472025605 +0200
20332 @@ -0,0 +1,97 @@
20334 + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
20335 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
20337 + * This code is free software; you can redistribute it and/or modify it
20338 + * under the terms of the GNU General Public License version 2 only, as
20339 + * published by the Free Software Foundation. Oracle designates this
20340 + * particular file as subject to the "Classpath" exception as provided
20341 + * by Oracle in the LICENSE file that accompanied this code.
20343 + * This code is distributed in the hope that it will be useful, but WITHOUT
20344 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20345 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20346 + * version 2 for more details (a copy is included in the LICENSE file that
20347 + * accompanied this code).
20349 + * You should have received a copy of the GNU General Public License version
20350 + * 2 along with this work; if not, write to the Free Software Foundation,
20351 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20353 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20354 + * or visit www.oracle.com if you need additional information or have any
20355 + * questions.
20356 + */
20358 +#include <Utilities.h>
20359 +#include <string.h>
20360 +#include <stdlib.h>
20361 +#include <fcntl.h>
20362 +/* does not work on Solaris 2.7 */
20363 +#include <sys/audio.h>
20364 +#include <sys/mixer.h>
20365 +#include <sys/types.h>
20366 +#ifndef __linux__
20367 +#include <stropts.h>
20368 +#endif
20369 +#include <sys/conf.h>
20370 +#include <sys/stat.h>
20371 +#include <unistd.h>
20373 +#ifndef PLATFORM_API_SOLARISOS_UTILS_H_INCLUDED
20374 +#define PLATFORM_API_SOLARISOS_UTILS_H_INCLUDED
20376 +/* defines for Solaris 2.7
20377 + #ifndef AUDIO_AUX1_OUT
20378 + #define AUDIO_AUX1_OUT (0x08) // output to aux1 out
20379 + #define AUDIO_AUX2_OUT (0x10) // output to aux2 out
20380 + #define AUDIO_SPDIF_OUT (0x20) // output to SPDIF port
20381 + #define AUDIO_AUX1_IN (0x08) // input from aux1 in
20382 + #define AUDIO_AUX2_IN (0x10) // input from aux2 in
20383 + #define AUDIO_SPDIF_IN (0x20) // input from SPDIF port
20384 + #endif
20387 +/* input from Codec inter. loopback */
20388 +#ifndef AUDIO_CODEC_LOOPB_IN
20389 +#define AUDIO_CODEC_LOOPB_IN (0x40)
20390 +#endif
20393 +#define MAX_NAME_LENGTH 300
20395 +typedef struct tag_AudioDevicePath {
20396 + char path[MAX_NAME_LENGTH];
20397 + ino_t st_ino; // inode number to detect duplicate devices
20398 + dev_t st_dev; // device ID to detect duplicate audio devices
20399 +} AudioDevicePath;
20401 +typedef struct tag_AudioDeviceDescription {
20402 + INT32 maxSimulLines;
20403 + char path[MAX_NAME_LENGTH+1];
20404 + char pathctl[MAX_NAME_LENGTH+4];
20405 + char name[MAX_NAME_LENGTH+1];
20406 + char vendor[MAX_NAME_LENGTH+1];
20407 + char version[MAX_NAME_LENGTH+1];
20408 + char description[MAX_NAME_LENGTH+1];
20409 +} AudioDeviceDescription;
20411 +int getAudioDeviceCount();
20414 + * adPath is an array of AudioDevicePath structures
20415 + * count contains initially the number of elements in adPath
20416 + * and will be set to the returned number of paths.
20417 + */
20418 +void getAudioDevices(AudioDevicePath* adPath, int* count);
20421 + * fills adDesc from the audio device given in path
20422 + * returns 0 if an error occurred
20423 + * if getNames is 0, only path and pathctl are filled
20424 + */
20425 +int getAudioDeviceDescription(char* path, AudioDeviceDescription* adDesc, int getNames);
20426 +int getAudioDeviceDescriptionByIndex(int index, AudioDeviceDescription* adDesc, int getNames);
20429 +#endif // PLATFORM_API_SOLARISOS_UTILS_H_INCLUDED
20430 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/unix/classes/sun/awt/X11FontManager.java jdk21u-jdk-21.0.4-ga/src/java.desktop/unix/classes/sun/awt/X11FontManager.java
20431 --- jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/unix/classes/sun/awt/X11FontManager.java 2024-07-09 10:07:16.000000000 +0200
20432 +++ jdk21u-jdk-21.0.4-ga/src/java.desktop/unix/classes/sun/awt/X11FontManager.java 2024-08-17 19:13:01.421208422 +0200
20433 @@ -686,7 +686,8 @@
20434 * and do the best we can.
20436 FontConfiguration mFontConfig = new MFontConfiguration(this);
20437 - if ((FontUtilities.isLinux && !mFontConfig.foundOsSpecificFile())) {
20438 + if ((FontUtilities.isLinux && !mFontConfig.foundOsSpecificFile()) ||
20439 + (FontUtilities.isSolaris && !mFontConfig.fontFilesArePresent())) {
20440 FcFontConfiguration fcFontConfig =
20441 new FcFontConfiguration(this);
20442 if (fcFontConfig.init()) {
20443 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/unix/classes/sun/font/MFontConfiguration.java jdk21u-jdk-21.0.4-ga/src/java.desktop/unix/classes/sun/font/MFontConfiguration.java
20444 --- jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/unix/classes/sun/font/MFontConfiguration.java 2024-07-09 10:07:16.000000000 +0200
20445 +++ jdk21u-jdk-21.0.4-ga/src/java.desktop/unix/classes/sun/font/MFontConfiguration.java 2024-08-17 19:13:01.421905850 +0200
20446 @@ -68,7 +68,59 @@
20448 protected void initReorderMap() {
20449 reorderMap = new HashMap<>();
20450 + if (osName == null) { /* null means SunOS */
20451 + initReorderMapForSolaris();
20452 + } else {
20453 + initReorderMapForLinux();
20457 + private void initReorderMapForSolaris() {
20458 + /* Don't create a no-op entry, so we can optimize this case
20459 + * i.e. we don't need to do anything so can avoid slower paths in
20460 + * the code.
20461 + */
20462 +// reorderMap.put("UTF-8", "latin-1");
20463 + reorderMap.put("UTF-8.hi", "devanagari"); // NB is in Lucida.
20464 + reorderMap.put("UTF-8.ja",
20465 + new String[] {"japanese-x0201", "japanese-x0208", "japanese-x0212"});
20466 + reorderMap.put("UTF-8.ko", "korean-johab");
20467 + reorderMap.put("UTF-8.th", "thai");
20468 + reorderMap.put("UTF-8.zh.TW", "chinese-big5");
20469 + reorderMap.put("UTF-8.zh.HK", new String[] {"chinese-big5", "chinese-hkscs"});
20470 + reorderMap.put("UTF-8.zh.CN",
20471 + new String[] {"chinese-gb18030-0", "chinese-gb18030-1"});
20472 + reorderMap.put("UTF-8.zh",
20473 + new String[] {"chinese-big5", "chinese-hkscs", "chinese-gb18030-0,chinese-gb18030-1"});
20474 + reorderMap.put("Big5", "chinese-big5");
20475 + reorderMap.put("Big5-HKSCS", new String[] {"chinese-big5", "chinese-hkscs"});
20476 + reorderMap.put("GB2312", new String[] {"chinese-gbk", "chinese-gb2312"});
20477 + reorderMap.put("x-EUC-TW",
20478 + new String[] {"chinese-cns11643-1", "chinese-cns11643-2", "chinese-cns11643-3"});
20479 + reorderMap.put("GBK", "chinese-gbk");
20480 + reorderMap.put("GB18030",new String[] {"chinese-gb18030-0", "chinese-gb18030-1"});
20482 + reorderMap.put("TIS-620", "thai");
20483 + reorderMap.put("x-PCK",
20484 + new String[] {"japanese-x0201", "japanese-x0208", "japanese-x0212"});
20485 + reorderMap.put("x-eucJP-Open",
20486 + new String[] {"japanese-x0201", "japanese-x0208", "japanese-x0212"});
20487 + reorderMap.put("EUC-KR", "korean");
20488 + /* Don't create a no-op entry, so we can optimize this case */
20489 +// reorderMap.put("ISO-8859-1", "latin-1");
20490 + reorderMap.put("ISO-8859-2", "latin-2");
20491 + reorderMap.put("ISO-8859-5", "cyrillic-iso8859-5");
20492 + reorderMap.put("windows-1251", "cyrillic-cp1251");
20493 + reorderMap.put("KOI8-R", "cyrillic-koi8-r");
20494 + reorderMap.put("ISO-8859-6", "arabic");
20495 + reorderMap.put("ISO-8859-7", "greek");
20496 + reorderMap.put("ISO-8859-8", "hebrew");
20497 + reorderMap.put("ISO-8859-9", "latin-5");
20498 + reorderMap.put("ISO-8859-13", "latin-7");
20499 + reorderMap.put("ISO-8859-15", "latin-9");
20502 + private void initReorderMapForLinux() {
20503 reorderMap.put("UTF-8.ja.JP", "japanese-iso10646");
20504 reorderMap.put("UTF-8.ko.KR", "korean-iso10646");
20505 reorderMap.put("UTF-8.zh.TW", "chinese-tw-iso10646");
20506 @@ -78,7 +130,12 @@
20507 reorderMap.put("GB2312", "chinese-gb18030");
20508 reorderMap.put("Big5", "chinese-big5");
20509 reorderMap.put("EUC-KR", "korean");
20510 - reorderMap.put("GB18030", "chinese-gb18030");
20511 + if (osName.equals("Sun")){
20512 + reorderMap.put("GB18030", "chinese-cn-iso10646");
20514 + else {
20515 + reorderMap.put("GB18030", "chinese-gb18030");
20520 @@ -87,7 +144,10 @@
20521 protected void setOsNameAndVersion(){
20522 super.setOsNameAndVersion();
20524 - if (osName.equals("Linux")) {
20525 + if (osName.equals("SunOS")) {
20526 + //don't care os name on Solaris
20527 + osName = null;
20528 + } else if (osName.equals("Linux")) {
20529 try {
20530 File f;
20531 if ((f = new File("/etc/fedora-release")).canRead()) {
20532 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java jdk21u-jdk-21.0.4-ga/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java
20533 --- jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java 2024-07-09 10:07:16.000000000 +0200
20534 +++ jdk21u-jdk-21.0.4-ga/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java 2024-08-17 19:13:01.422769100 +0200
20535 @@ -150,6 +150,10 @@
20536 return OSInfo.getOSType() == OSInfo.OSType.MACOSX;
20539 + static boolean isSysV() {
20540 + return OSInfo.getOSType() == OSInfo.OSType.SOLARIS;
20543 static boolean isLinux() {
20544 return OSInfo.getOSType() == OSInfo.OSType.LINUX;
20546 @@ -301,7 +305,7 @@
20549 } else {
20550 - if (isMac()) {
20551 + if (isMac() || isSysV()) {
20552 printers = getAllPrinterNamesSysV();
20553 } else if (isAIX()) {
20554 printers = getAllPrinterNamesAIX();
20555 @@ -485,7 +489,7 @@
20557 /* fallback if nothing not having a printer at this point */
20558 PrintService printer = null;
20559 - if (isMac()) {
20560 + if (isMac() || isSysV()) {
20561 printer = getNamedPrinterNameSysV(name);
20562 } else if (isAIX()) {
20563 printer = getNamedPrinterNameAIX(name);
20564 @@ -656,7 +660,7 @@
20565 psuri = printerInfo[1];
20567 } else {
20568 - if (isMac()) {
20569 + if (isMac() || isSysV()) {
20570 defaultPrinter = getDefaultPrinterNameSysV();
20571 } else if (isAIX()) {
20572 defaultPrinter = getDefaultPrinterNameAIX();
20573 @@ -876,7 +880,7 @@
20574 ArrayList<String> results = null;
20575 try {
20576 final String[] cmd = new String[3];
20577 - if (isAIX()) {
20578 + if (isSysV() || isAIX()) {
20579 cmd[0] = "/usr/bin/sh";
20580 cmd[1] = "-c";
20581 cmd[2] = "env LC_ALL=C " + command;
20582 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/unix/classes/sun/print/UnixPrintJob.java jdk21u-jdk-21.0.4-ga/src/java.desktop/unix/classes/sun/print/UnixPrintJob.java
20583 --- jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/unix/classes/sun/print/UnixPrintJob.java 2024-07-09 10:07:16.000000000 +0200
20584 +++ jdk21u-jdk-21.0.4-ga/src/java.desktop/unix/classes/sun/print/UnixPrintJob.java 2024-08-17 19:13:01.423933725 +0200
20585 @@ -872,25 +872,51 @@
20586 isAttributeCategorySupported(JobSheets.class)) {
20587 ncomps+=1;
20589 - execCmd = new String[ncomps];
20590 - execCmd[n++] = "/usr/bin/lpr";
20591 - if ((pFlags & PRINTER) != 0) {
20592 - execCmd[n++] = "-P" + printer;
20594 - if ((pFlags & JOBTITLE) != 0) {
20595 - execCmd[n++] = "-J " + jobTitle;
20597 - if ((pFlags & COPIES) != 0) {
20598 - execCmd[n++] = "-#" + copies;
20600 - if ((pFlags & NOSHEET) != 0) {
20601 - execCmd[n++] = "-h";
20602 - } else if (getPrintService().
20603 - isAttributeCategorySupported(JobSheets.class)) {
20604 - execCmd[n++] = "-o job-sheets=standard";
20606 - if ((pFlags & OPTIONS) != 0) {
20607 - execCmd[n++] = "-o" + options;
20608 + if (PrintServiceLookupProvider.isSysV()) {
20609 + ncomps+=1; // lp uses 1 more arg than lpr (make a copy)
20610 + execCmd = new String[ncomps];
20611 + execCmd[n++] = "/usr/bin/lp";
20612 + execCmd[n++] = "-c"; // make a copy of the spool file
20613 + if ((pFlags & PRINTER) != 0) {
20614 + execCmd[n++] = "-d" + printer;
20616 + if ((pFlags & JOBTITLE) != 0) {
20617 + String quoteChar = "\"";
20618 + execCmd[n++] = "-t " + quoteChar+jobTitle+quoteChar;
20620 + if ((pFlags & COPIES) != 0) {
20621 + execCmd[n++] = "-n " + copies;
20623 + if ((pFlags & NOSHEET) != 0) {
20624 + execCmd[n++] = "-o nobanner";
20625 + } else if (getPrintService().
20626 + isAttributeCategorySupported(JobSheets.class)) {
20627 + execCmd[n++] = "-o job-sheets=standard";
20629 + if ((pFlags & OPTIONS) != 0) {
20630 + execCmd[n++] = "-o " + options;
20632 + } else {
20633 + execCmd = new String[ncomps];
20634 + execCmd[n++] = "/usr/bin/lpr";
20635 + if ((pFlags & PRINTER) != 0) {
20636 + execCmd[n++] = "-P" + printer;
20638 + if ((pFlags & JOBTITLE) != 0) {
20639 + execCmd[n++] = "-J " + jobTitle;
20641 + if ((pFlags & COPIES) != 0) {
20642 + execCmd[n++] = "-#" + copies;
20644 + if ((pFlags & NOSHEET) != 0) {
20645 + execCmd[n++] = "-h";
20646 + } else if (getPrintService().
20647 + isAttributeCategorySupported(JobSheets.class)) {
20648 + execCmd[n++] = "-o job-sheets=standard";
20650 + if ((pFlags & OPTIONS) != 0) {
20651 + execCmd[n++] = "-o" + options;
20654 execCmd[n++] = spoolFile;
20655 if (IPPPrintService.debugPrint) {
20656 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/unix/classes/sun/print/UnixPrintService.java jdk21u-jdk-21.0.4-ga/src/java.desktop/unix/classes/sun/print/UnixPrintService.java
20657 --- jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/unix/classes/sun/print/UnixPrintService.java 2024-07-09 10:07:16.000000000 +0200
20658 +++ jdk21u-jdk-21.0.4-ga/src/java.desktop/unix/classes/sun/print/UnixPrintService.java 2024-08-17 19:13:01.424831416 +0200
20659 @@ -220,6 +220,31 @@
20660 return name;
20663 + private PrinterIsAcceptingJobs getPrinterIsAcceptingJobsSysV() {
20664 + String command = "/usr/bin/lpstat -a " + printer;
20665 + String[] results= PrintServiceLookupProvider.execCmd(command);
20667 + if (results != null && results.length > 0) {
20668 + if (results[0].startsWith(printer + " accepting requests")) {
20669 + return PrinterIsAcceptingJobs.ACCEPTING_JOBS;
20671 + else if (results[0].startsWith(printer)) {
20672 + /* As well as "myprinter accepting requests", look for
20673 + * "myprinter@somehost accepting requests".
20674 + */
20675 + int index = printer.length();
20676 + String str = results[0];
20677 + if (str.length() > index &&
20678 + str.charAt(index) == '@' &&
20679 + str.indexOf(" accepting requests", index) > 0 &&
20680 + str.indexOf(" not accepting requests", index) == -1) {
20681 + return PrinterIsAcceptingJobs.ACCEPTING_JOBS;
20685 + return PrinterIsAcceptingJobs.NOT_ACCEPTING_JOBS ;
20688 private PrinterIsAcceptingJobs getPrinterIsAcceptingJobsBSD() {
20689 if (PrintServiceLookupProvider.cmdIndex ==
20690 PrintServiceLookupProvider.UNINITIALIZED) {
20691 @@ -297,7 +322,9 @@
20694 private PrinterIsAcceptingJobs getPrinterIsAcceptingJobs() {
20695 - if (PrintServiceLookupProvider.isBSD()) {
20696 + if (PrintServiceLookupProvider.isSysV()) {
20697 + return getPrinterIsAcceptingJobsSysV();
20698 + } else if (PrintServiceLookupProvider.isBSD()) {
20699 return getPrinterIsAcceptingJobsBSD();
20700 } else if (PrintServiceLookupProvider.isAIX()) {
20701 return getPrinterIsAcceptingJobsAIX();
20702 @@ -324,6 +351,14 @@
20706 + private QueuedJobCount getQueuedJobCountSysV() {
20707 + String command = "/usr/bin/lpstat -R " + printer;
20708 + String[] results= PrintServiceLookupProvider.execCmd(command);
20709 + int qlen = (results == null) ? 0 : results.length;
20711 + return new QueuedJobCount(qlen);
20714 private QueuedJobCount getQueuedJobCountBSD() {
20715 if (PrintServiceLookupProvider.cmdIndex ==
20716 PrintServiceLookupProvider.UNINITIALIZED) {
20717 @@ -380,7 +415,9 @@
20720 private QueuedJobCount getQueuedJobCount() {
20721 - if (PrintServiceLookupProvider.isBSD()) {
20722 + if (PrintServiceLookupProvider.isSysV()) {
20723 + return getQueuedJobCountSysV();
20724 + } else if (PrintServiceLookupProvider.isBSD()) {
20725 return getQueuedJobCountBSD();
20726 } else if (PrintServiceLookupProvider.isAIX()) {
20727 return getQueuedJobCountAIX();
20728 @@ -389,6 +426,13 @@
20732 + private PrintServiceAttributeSet getSysVServiceAttributes() {
20733 + PrintServiceAttributeSet attrs = new HashPrintServiceAttributeSet();
20734 + attrs.add(getQueuedJobCountSysV());
20735 + attrs.add(getPrinterIsAcceptingJobsSysV());
20736 + return attrs;
20739 private PrintServiceAttributeSet getBSDServiceAttributes() {
20740 PrintServiceAttributeSet attrs = new HashPrintServiceAttributeSet();
20741 attrs.add(getQueuedJobCountBSD());
20742 @@ -427,7 +471,9 @@
20745 private PrintServiceAttributeSet getDynamicAttributes() {
20746 - if (PrintServiceLookupProvider.isAIX()) {
20747 + if (PrintServiceLookupProvider.isSysV()) {
20748 + return getSysVServiceAttributes();
20749 + } else if (PrintServiceLookupProvider.isAIX()) {
20750 return getAIXServiceAttributes();
20751 } else {
20752 return getBSDServiceAttributes();
20753 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/unix/native/common/awt/fontpath.c jdk21u-jdk-21.0.4-ga/src/java.desktop/unix/native/common/awt/fontpath.c
20754 --- jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/unix/native/common/awt/fontpath.c 2024-07-09 10:07:16.000000000 +0200
20755 +++ jdk21u-jdk-21.0.4-ga/src/java.desktop/unix/native/common/awt/fontpath.c 2024-08-17 19:13:01.425696875 +0200
20756 @@ -57,7 +57,57 @@
20758 #define MAXFDIRS 512 /* Max number of directories that contain fonts */
20760 -#if defined( __linux__)
20761 +#if defined(__solaris__)
20763 + * This can be set in the makefile to "/usr/X11" if so desired.
20764 + */
20765 +#ifndef OPENWINHOMELIB
20766 +#define OPENWINHOMELIB "/usr/openwin/lib/"
20767 +#endif
20769 +/* This is all known Solaris X11 directories on Solaris 8, 9 and 10.
20770 + * It is ordered to give precedence to TrueType directories.
20771 + * It is needed if fontconfig is not installed or configured properly.
20772 + */
20773 +static char *fullSolarisFontPath[] = {
20774 + OPENWINHOMELIB "X11/fonts/TrueType",
20775 + OPENWINHOMELIB "locale/euro_fonts/X11/fonts/TrueType",
20776 + OPENWINHOMELIB "locale/iso_8859_2/X11/fonts/TrueType",
20777 + OPENWINHOMELIB "locale/iso_8859_5/X11/fonts/TrueType",
20778 + OPENWINHOMELIB "locale/iso_8859_7/X11/fonts/TrueType",
20779 + OPENWINHOMELIB "locale/iso_8859_8/X11/fonts/TrueType",
20780 + OPENWINHOMELIB "locale/iso_8859_9/X11/fonts/TrueType",
20781 + OPENWINHOMELIB "locale/iso_8859_13/X11/fonts/TrueType",
20782 + OPENWINHOMELIB "locale/iso_8859_15/X11/fonts/TrueType",
20783 + OPENWINHOMELIB "locale/ar/X11/fonts/TrueType",
20784 + OPENWINHOMELIB "locale/hi_IN.UTF-8/X11/fonts/TrueType",
20785 + OPENWINHOMELIB "locale/ja/X11/fonts/TT",
20786 + OPENWINHOMELIB "locale/ko/X11/fonts/TrueType",
20787 + OPENWINHOMELIB "locale/ko.UTF-8/X11/fonts/TrueType",
20788 + OPENWINHOMELIB "locale/KOI8-R/X11/fonts/TrueType",
20789 + OPENWINHOMELIB "locale/ru.ansi-1251/X11/fonts/TrueType",
20790 + OPENWINHOMELIB "locale/th_TH/X11/fonts/TrueType",
20791 + OPENWINHOMELIB "locale/zh_TW/X11/fonts/TrueType",
20792 + OPENWINHOMELIB "locale/zh_TW.BIG5/X11/fonts/TT",
20793 + OPENWINHOMELIB "locale/zh_HK.BIG5HK/X11/fonts/TT",
20794 + OPENWINHOMELIB "locale/zh_CN.GB18030/X11/fonts/TrueType",
20795 + OPENWINHOMELIB "locale/zh/X11/fonts/TrueType",
20796 + OPENWINHOMELIB "locale/zh.GBK/X11/fonts/TrueType",
20797 + OPENWINHOMELIB "X11/fonts/Type1",
20798 + OPENWINHOMELIB "X11/fonts/Type1/sun",
20799 + OPENWINHOMELIB "X11/fonts/Type1/sun/outline",
20800 + OPENWINHOMELIB "locale/iso_8859_2/X11/fonts/Type1",
20801 + OPENWINHOMELIB "locale/iso_8859_4/X11/fonts/Type1",
20802 + OPENWINHOMELIB "locale/iso_8859_5/X11/fonts/Type1",
20803 + OPENWINHOMELIB "locale/iso_8859_7/X11/fonts/Type1",
20804 + OPENWINHOMELIB "locale/iso_8859_8/X11/fonts/Type1",
20805 + OPENWINHOMELIB "locale/iso_8859_9/X11/fonts/Type1",
20806 + OPENWINHOMELIB "locale/iso_8859_13/X11/fonts/Type1",
20807 + OPENWINHOMELIB "locale/ar/X11/fonts/Type1",
20808 + NULL, /* terminates the list */
20811 +#elif defined( __linux__)
20812 /* All the known interesting locations we have discovered on
20813 * various flavors of Linux
20815 @@ -173,6 +223,14 @@
20816 if (strstr(x11Path[i], ".gnome") != NULL) {
20817 continue;
20819 +#ifdef __solaris__
20820 + if (strstr(x11Path[i], "/F3/") != NULL) {
20821 + continue;
20823 + if (strstr(x11Path[i], "bitmap") != NULL) {
20824 + continue;
20826 +#endif
20827 fontdirs[pos] = strdup(x11Path[i]);
20828 slen = strlen(fontdirs[pos]);
20829 if (slen > 0 && fontdirs[pos][slen-1] == '/') {
20830 @@ -322,6 +380,8 @@
20832 #if defined(__linux__)
20833 knowndirs = fullLinuxFontPath;
20834 +#elif defined(__solaris__)
20835 + knowndirs = fullSolarisFontPath;
20836 #elif defined(_AIX)
20837 knowndirs = fullAixFontPath;
20838 #endif
20839 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c jdk21u-jdk-21.0.4-ga/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c
20840 --- jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c 2024-07-09 10:07:16.000000000 +0200
20841 +++ jdk21u-jdk-21.0.4-ga/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c 2024-08-17 19:13:01.426558695 +0200
20842 @@ -402,7 +402,12 @@
20843 xrenderLibHandle = dlopen("libXrender.so", RTLD_LAZY | RTLD_GLOBAL);
20846 -#if defined(_AIX)
20847 +#if defined(__solaris__)
20848 + if (xrenderLibHandle == NULL) {
20849 + xrenderLibHandle = dlopen("libXrender.so.1",
20850 + RTLD_LAZY | RTLD_GLOBAL);
20852 +#elif defined(_AIX)
20853 if (xrenderLibHandle == NULL) {
20854 xrenderLibHandle = dlopen("libXrender.a(libXrender.so.0)",
20855 RTLD_MEMBER | RTLD_LAZY | RTLD_GLOBAL);
20856 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/unix/native/libawt_xawt/java2d/x11/XRBackendNative.c jdk21u-jdk-21.0.4-ga/src/java.desktop/unix/native/libawt_xawt/java2d/x11/XRBackendNative.c
20857 --- jdk21u-jdk-21.0.4-ga.orig/src/java.desktop/unix/native/libawt_xawt/java2d/x11/XRBackendNative.c 2024-07-09 10:07:16.000000000 +0200
20858 +++ jdk21u-jdk-21.0.4-ga/src/java.desktop/unix/native/libawt_xawt/java2d/x11/XRBackendNative.c 2024-08-17 19:13:01.427435133 +0200
20859 @@ -61,6 +61,29 @@
20861 #include <dlfcn.h>
20863 +#if defined(__solaris__)
20864 +/* Solaris 10 will not have these symbols at compile time */
20866 +typedef Picture (*XRenderCreateLinearGradientFuncType)
20867 + (Display *dpy,
20868 + const XLinearGradient *gradient,
20869 + const XFixed *stops,
20870 + const XRenderColor *colors,
20871 + int nstops);
20873 +typedef Picture (*XRenderCreateRadialGradientFuncType)
20874 + (Display *dpy,
20875 + const XRadialGradient *gradient,
20876 + const XFixed *stops,
20877 + const XRenderColor *colors,
20878 + int nstops);
20880 +static
20881 +XRenderCreateLinearGradientFuncType XRenderCreateLinearGradientFunc = NULL;
20882 +static
20883 + XRenderCreateRadialGradientFuncType XRenderCreateRadialGradientFunc = NULL;
20884 +#endif
20886 #define BUILD_TRANSFORM_MATRIX(TRANSFORM, M00, M01, M02, M10, M11, M12) \
20888 TRANSFORM.matrix[0][0] = M00; \
20889 @@ -128,6 +151,27 @@
20890 } else {
20891 available = JNI_FALSE;
20893 +#elif defined(__solaris__)
20894 + xrenderlib = dlopen("libXrender.so",RTLD_GLOBAL|RTLD_LAZY);
20895 + if (xrenderlib != NULL) {
20897 + XRenderCreateLinearGradientFunc =
20898 + (XRenderCreateLinearGradientFuncType)
20899 + dlsym(xrenderlib, "XRenderCreateLinearGradient");
20901 + XRenderCreateRadialGradientFunc =
20902 + (XRenderCreateRadialGradientFuncType)
20903 + dlsym(xrenderlib, "XRenderCreateRadialGradient");
20905 + if (XRenderCreateLinearGradientFunc == NULL ||
20906 + XRenderCreateRadialGradientFunc == NULL)
20908 + available = JNI_FALSE;
20910 + dlclose(xrenderlib);
20911 + } else {
20912 + available = JNI_FALSE;
20914 #else
20915 Dl_info info;
20916 jboolean versionInfoIsFound = JNI_FALSE;
20917 @@ -534,7 +578,13 @@
20918 colors[i].green = pixels[i*4 + 2];
20919 colors[i].blue = pixels[i*4 + 3];
20921 +#ifdef __solaris__
20922 + if (XRenderCreateLinearGradientFunc!=NULL) {
20923 + gradient = (*XRenderCreateLinearGradientFunc)(awt_display, &grad, stops, colors, numStops);
20925 +#else
20926 gradient = XRenderCreateLinearGradient(awt_display, &grad, stops, colors, numStops);
20927 +#endif
20928 free(colors);
20929 free(stops);
20931 @@ -612,7 +662,13 @@
20932 colors[i].green = pixels[i*4 + 2];
20933 colors[i].blue = pixels[i*4 + 3];
20935 +#ifdef __solaris__
20936 + if (XRenderCreateRadialGradientFunc != NULL) {
20937 + gradient = (jint) (*XRenderCreateRadialGradientFunc)(awt_display, &grad, stops, colors, numStops);
20939 +#else
20940 gradient = (jint) XRenderCreateRadialGradient(awt_display, &grad, stops, colors, numStops);
20941 +#endif
20942 free(colors);
20943 free(stops);
20945 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/SunNativeProvider.java jdk21u-jdk-21.0.4-ga/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/SunNativeProvider.java
20946 --- jdk21u-jdk-21.0.4-ga.orig/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/SunNativeProvider.java 2024-07-09 10:07:16.000000000 +0200
20947 +++ jdk21u-jdk-21.0.4-ga/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/SunNativeProvider.java 2024-08-17 19:13:01.428058981 +0200
20948 @@ -91,6 +91,9 @@
20949 = System.getProperty("sun.security.jgss.lib");
20950 if (defaultLib == null || defaultLib.trim().equals("")) {
20951 gssLibs = switch (OperatingSystem.current()) {
20952 + case SOLARIS -> new String[]{
20953 + "libgss.so",
20954 + };
20955 case LINUX -> new String[]{
20956 "libgssapi.so",
20957 "libgssapi_krb5.so",
20958 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.security.jgss/share/classes/sun/security/krb5/Config.java jdk21u-jdk-21.0.4-ga/src/java.security.jgss/share/classes/sun/security/krb5/Config.java
20959 --- jdk21u-jdk-21.0.4-ga.orig/src/java.security.jgss/share/classes/sun/security/krb5/Config.java 2024-07-09 10:07:16.000000000 +0200
20960 +++ jdk21u-jdk-21.0.4-ga/src/java.security.jgss/share/classes/sun/security/krb5/Config.java 2024-08-17 19:13:01.428817836 +0200
20961 @@ -931,6 +931,8 @@
20962 if (name == null) {
20963 name = "c:\\winnt\\krb5.ini";
20965 + } else if (OperatingSystem.isSolaris()) {
20966 + name = "/etc/krb5/krb5.conf";
20967 } else if (OperatingSystem.isMacOS()) {
20968 name = findMacosConfigFile();
20969 } else {
20970 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/DflCache.java jdk21u-jdk-21.0.4-ga/src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/DflCache.java
20971 --- jdk21u-jdk-21.0.4-ga.orig/src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/DflCache.java 2024-07-09 10:07:16.000000000 +0200
20972 +++ jdk21u-jdk-21.0.4-ga/src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/DflCache.java 2024-08-17 19:13:01.429332263 +0200
20973 @@ -107,7 +107,7 @@
20975 private static long uid;
20976 static {
20977 - // Available on Linux and Mac. Otherwise, -1 and no _euid suffix
20978 + // Available on Solaris, Linux and Mac. Otherwise, -1 and no _euid suffix
20979 uid = jdk.internal.misc.VM.geteuid();
20982 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.smartcardio/unix/classes/sun/security/smartcardio/PlatformPCSC.java jdk21u-jdk-21.0.4-ga/src/java.smartcardio/unix/classes/sun/security/smartcardio/PlatformPCSC.java
20983 --- jdk21u-jdk-21.0.4-ga.orig/src/java.smartcardio/unix/classes/sun/security/smartcardio/PlatformPCSC.java 2024-07-09 10:07:16.000000000 +0200
20984 +++ jdk21u-jdk-21.0.4-ga/src/java.smartcardio/unix/classes/sun/security/smartcardio/PlatformPCSC.java 2024-08-17 19:13:01.429848478 +0200
20985 @@ -86,8 +86,12 @@
20986 if (k != -1) {
20987 String libDir;
20988 if ("64".equals(System.getProperty("sun.arch.data.model"))) {
20989 - // assume Linux convention
20990 - libDir = "lib64";
20991 + if ("SunOS".equals(System.getProperty("os.name"))) {
20992 + libDir = "lib/64";
20993 + } else {
20994 + // assume Linux convention
20995 + libDir = "lib64";
20997 } else {
20998 // must be 32-bit
20999 libDir = "lib";
21000 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/output/WriterOutputBuffer.java jdk21u-jdk-21.0.4-ga/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/output/WriterOutputBuffer.java
21001 --- jdk21u-jdk-21.0.4-ga.orig/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/output/WriterOutputBuffer.java 2024-07-09 10:07:16.000000000 +0200
21002 +++ jdk21u-jdk-21.0.4-ga/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/output/WriterOutputBuffer.java 2024-08-17 19:13:01.430548122 +0200
21003 @@ -33,12 +33,21 @@
21004 private static final int KB = 1024;
21005 private static int BUFFER_SIZE = 4 * KB;
21007 + static {
21008 + // Set a larger buffer size for Solaris
21009 + final String osName = SecuritySupport.getSystemProperty("os.name");
21010 + if (osName.equalsIgnoreCase("solaris")) {
21011 + BUFFER_SIZE = 32 * KB;
21015 private Writer _writer;
21018 * Initializes a WriterOutputBuffer by creating an instance of a
21019 * BufferedWriter. The size of the buffer in this writer may have
21020 - * a significant impact on throughput.
21021 + * a significant impact on throughput. Solaris prefers a larger
21022 + * buffer, while Linux works better with a smaller one.
21024 public WriterOutputBuffer(Writer writer) {
21025 _writer = new BufferedWriter(writer, BUFFER_SIZE);
21026 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/jdk.attach/solaris/classes/sun/tools/attach/AttachProviderImpl.java jdk21u-jdk-21.0.4-ga/src/jdk.attach/solaris/classes/sun/tools/attach/AttachProviderImpl.java
21027 --- jdk21u-jdk-21.0.4-ga.orig/src/jdk.attach/solaris/classes/sun/tools/attach/AttachProviderImpl.java 1970-01-01 01:00:00.000000000 +0100
21028 +++ jdk21u-jdk-21.0.4-ga/src/jdk.attach/solaris/classes/sun/tools/attach/AttachProviderImpl.java 2024-08-17 19:13:01.472590754 +0200
21029 @@ -0,0 +1,79 @@
21031 + * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
21032 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
21034 + * This code is free software; you can redistribute it and/or modify it
21035 + * under the terms of the GNU General Public License version 2 only, as
21036 + * published by the Free Software Foundation. Oracle designates this
21037 + * particular file as subject to the "Classpath" exception as provided
21038 + * by Oracle in the LICENSE file that accompanied this code.
21040 + * This code is distributed in the hope that it will be useful, but WITHOUT
21041 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21042 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21043 + * version 2 for more details (a copy is included in the LICENSE file that
21044 + * accompanied this code).
21046 + * You should have received a copy of the GNU General Public License version
21047 + * 2 along with this work; if not, write to the Free Software Foundation,
21048 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21050 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21051 + * or visit www.oracle.com if you need additional information or have any
21052 + * questions.
21053 + */
21054 +package sun.tools.attach;
21056 +import com.sun.tools.attach.VirtualMachine;
21057 +import com.sun.tools.attach.VirtualMachineDescriptor;
21058 +import com.sun.tools.attach.AttachNotSupportedException;
21059 +import java.io.IOException;
21062 + * An AttachProvider implementation for Solaris that use the doors
21063 + * interface to the VM.
21064 + */
21065 +public class AttachProviderImpl extends HotSpotAttachProvider {
21067 + public AttachProviderImpl() {
21070 + public String name() {
21071 + return "sun";
21074 + public String type() {
21075 + return "doors";
21078 + public VirtualMachine attachVirtualMachine(String vmid)
21079 + throws AttachNotSupportedException, IOException
21081 + checkAttachPermission();
21083 + // AttachNotSupportedException will be thrown if the target VM can be determined
21084 + // to be not attachable.
21085 + testAttachable(vmid);
21087 + return new VirtualMachineImpl(this, vmid);
21090 + public VirtualMachine attachVirtualMachine(VirtualMachineDescriptor vmd)
21091 + throws AttachNotSupportedException, IOException
21093 + if (vmd.provider() != this) {
21094 + throw new AttachNotSupportedException("provider mismatch");
21096 + // To avoid re-checking if the VM if attachable, we check if the descriptor
21097 + // is for a hotspot VM - these descriptors are created by the listVirtualMachines
21098 + // implementation which only returns a list of attachable VMs.
21099 + if (vmd instanceof HotSpotVirtualMachineDescriptor) {
21100 + assert ((HotSpotVirtualMachineDescriptor)vmd).isAttachable();
21101 + checkAttachPermission();
21102 + return new VirtualMachineImpl(this, vmd.id());
21103 + } else {
21104 + return attachVirtualMachine(vmd.id());
21109 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/jdk.attach/solaris/classes/sun/tools/attach/VirtualMachineImpl.java jdk21u-jdk-21.0.4-ga/src/jdk.attach/solaris/classes/sun/tools/attach/VirtualMachineImpl.java
21110 --- jdk21u-jdk-21.0.4-ga.orig/src/jdk.attach/solaris/classes/sun/tools/attach/VirtualMachineImpl.java 1970-01-01 01:00:00.000000000 +0100
21111 +++ jdk21u-jdk-21.0.4-ga/src/jdk.attach/solaris/classes/sun/tools/attach/VirtualMachineImpl.java 2024-08-17 19:13:01.472996448 +0200
21112 @@ -0,0 +1,272 @@
21114 + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
21115 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
21117 + * This code is free software; you can redistribute it and/or modify it
21118 + * under the terms of the GNU General Public License version 2 only, as
21119 + * published by the Free Software Foundation. Oracle designates this
21120 + * particular file as subject to the "Classpath" exception as provided
21121 + * by Oracle in the LICENSE file that accompanied this code.
21123 + * This code is distributed in the hope that it will be useful, but WITHOUT
21124 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21125 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21126 + * version 2 for more details (a copy is included in the LICENSE file that
21127 + * accompanied this code).
21129 + * You should have received a copy of the GNU General Public License version
21130 + * 2 along with this work; if not, write to the Free Software Foundation,
21131 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21133 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21134 + * or visit www.oracle.com if you need additional information or have any
21135 + * questions.
21136 + */
21137 +package sun.tools.attach;
21139 +import com.sun.tools.attach.AttachOperationFailedException;
21140 +import com.sun.tools.attach.AgentLoadException;
21141 +import com.sun.tools.attach.AttachNotSupportedException;
21142 +import com.sun.tools.attach.spi.AttachProvider;
21144 +import java.io.InputStream;
21145 +import java.io.IOException;
21146 +import java.io.File;
21147 +import java.io.FileNotFoundException;
21150 + * Solaris implementation of HotSpotVirtualMachine.
21151 + */
21152 +public class VirtualMachineImpl extends HotSpotVirtualMachine {
21153 + // "/tmp" is used as a global well-known location for the files
21154 + // .java_pid<pid>. and .attach_pid<pid>. It is important that this
21155 + // location is the same for all processes, otherwise the tools
21156 + // will not be able to find all Hotspot processes.
21157 + // Any changes to this needs to be synchronized with HotSpot.
21158 + private static final String tmpdir = "/tmp";
21160 + // door descriptor;
21161 + private int fd = -1;
21162 + String socket_path;
21164 + /**
21165 + * Attaches to the target VM
21166 + */
21167 + VirtualMachineImpl(AttachProvider provider, String vmid)
21168 + throws AttachNotSupportedException, IOException
21170 + super(provider, vmid);
21171 + // This provider only understands process-ids (pids).
21172 + int pid;
21173 + try {
21174 + pid = Integer.parseInt(vmid);
21175 + if (pid < 1) {
21176 + throw new NumberFormatException();
21178 + } catch (NumberFormatException x) {
21179 + throw new AttachNotSupportedException("Invalid process identifier: " + vmid);
21182 + // Opens the door file to the target VM. If the file is not
21183 + // found it might mean that the attach mechanism isn't started in the
21184 + // target VM so we attempt to start it and retry.
21185 + try {
21186 + fd = openDoor(pid);
21187 + } catch (FileNotFoundException fnf1) {
21188 + File f = createAttachFile(pid);
21189 + try {
21190 + sigquit(pid);
21192 + // give the target VM time to start the attach mechanism
21193 + final int delay_step = 100;
21194 + final long timeout = attachTimeout();
21195 + long time_spend = 0;
21196 + long delay = 0;
21197 + do {
21198 + // Increase timeout on each attempt to reduce polling
21199 + delay += delay_step;
21200 + try {
21201 + Thread.sleep(delay);
21202 + } catch (InterruptedException x) { }
21203 + try {
21204 + fd = openDoor(pid);
21205 + } catch (FileNotFoundException fnf2) {
21206 + // pass
21209 + time_spend += delay;
21210 + if (time_spend > timeout/2 && fd == -1) {
21211 + // Send QUIT again to give target VM the last chance to react
21212 + sigquit(pid);
21214 + } while (time_spend <= timeout && fd == -1);
21215 + if (fd == -1) {
21216 + throw new AttachNotSupportedException(
21217 + String.format("Unable to open door %s: " +
21218 + "target process %d doesn't respond within %dms " +
21219 + "or HotSpot VM not loaded", socket_path, pid, time_spend));
21221 + } finally {
21222 + f.delete();
21225 + assert fd >= 0;
21228 + /**
21229 + * Detach from the target VM
21230 + */
21231 + public void detach() throws IOException {
21232 + synchronized (this) {
21233 + if (fd != -1) {
21234 + close(fd);
21235 + fd = -1;
21240 + /**
21241 + * Execute the given command in the target VM.
21242 + */
21243 + InputStream execute(String cmd, Object ... args) throws AgentLoadException, IOException {
21244 + assert args.length <= 3; // includes null
21246 + // first check that we are still attached
21247 + int door;
21248 + synchronized (this) {
21249 + if (fd == -1) {
21250 + throw new IOException("Detached from target VM");
21252 + door = fd;
21255 + // enqueue the command via a door call
21256 + int s = enqueue(door, cmd, args);
21257 + assert s >= 0; // valid file descriptor
21259 + // The door call returns a file descriptor (one end of a socket pair).
21260 + // Create an input stream around it.
21261 + SocketInputStream sis = new SocketInputStream(s);
21263 + // Read the command completion status
21264 + int completionStatus;
21265 + try {
21266 + completionStatus = readInt(sis);
21267 + } catch (IOException ioe) {
21268 + sis.close();
21269 + throw ioe;
21272 + // If non-0 it means an error but we need to special-case the
21273 + // "load" command to ensure that the right exception is thrown.
21274 + if (completionStatus != 0) {
21275 + // read from the stream and use that as the error message
21276 + String message = readErrorMessage(sis);
21277 + sis.close();
21278 + if (cmd.equals("load")) {
21279 + String msg = "Failed to load agent library";
21280 + if (!message.isEmpty())
21281 + msg += ": " + message;
21282 + throw new AgentLoadException(msg);
21283 + } else {
21284 + if (message.isEmpty())
21285 + message = "Command failed in target VM";
21286 + throw new AttachOperationFailedException(message);
21290 + // Return the input stream so that the command output can be read
21291 + return sis;
21294 + // InputStream over a socket
21295 + private class SocketInputStream extends InputStream {
21296 + int s;
21298 + public SocketInputStream(int s) {
21299 + this.s = s;
21302 + public synchronized int read() throws IOException {
21303 + byte b[] = new byte[1];
21304 + int n = this.read(b, 0, 1);
21305 + if (n == 1) {
21306 + return b[0] & 0xff;
21307 + } else {
21308 + return -1;
21312 + public synchronized int read(byte[] bs, int off, int len) throws IOException {
21313 + if ((off < 0) || (off > bs.length) || (len < 0) ||
21314 + ((off + len) > bs.length) || ((off + len) < 0)) {
21315 + throw new IndexOutOfBoundsException();
21316 + } else if (len == 0)
21317 + return 0;
21319 + return VirtualMachineImpl.read(s, bs, off, len);
21322 + public synchronized void close() throws IOException {
21323 + if (s != -1) {
21324 + int toClose = s;
21325 + s = -1;
21326 + VirtualMachineImpl.close(toClose);
21331 + // The door is attached to .java_pid<pid> in the temporary directory.
21332 + private int openDoor(int pid) throws IOException {
21333 + socket_path = tmpdir + "/.java_pid" + pid;
21334 + fd = open(socket_path);
21336 + // Check that the file owner/permission to avoid attaching to
21337 + // bogus process
21338 + try {
21339 + checkPermissions(socket_path);
21340 + } catch (IOException ioe) {
21341 + close(fd);
21342 + throw ioe;
21344 + return fd;
21347 + // On Solaris a simple handshake is used to start the attach mechanism
21348 + // if not already started. The client creates a .attach_pid<pid> file in the
21349 + // target VM's working directory (or temporary directory), and the SIGQUIT
21350 + // handler checks for the file.
21351 + private File createAttachFile(int pid) throws IOException {
21352 + String fn = ".attach_pid" + pid;
21353 + String path = "/proc/" + pid + "/cwd/" + fn;
21354 + File f = new File(path);
21355 + try {
21356 + f = f.getCanonicalFile();
21357 + f.createNewFile();
21358 + } catch (IOException x) {
21359 + f = new File(tmpdir, fn);
21360 + f.createNewFile();
21362 + return f;
21365 + //-- native methods
21367 + static native int open(String path) throws IOException;
21369 + static native void close(int fd) throws IOException;
21371 + static native int read(int fd, byte buf[], int off, int buflen) throws IOException;
21373 + static native void checkPermissions(String path) throws IOException;
21375 + static native void sigquit(int pid) throws IOException;
21377 + // enqueue a command (and arguments) to the given door
21378 + static native int enqueue(int fd, String cmd, Object ... args)
21379 + throws IOException;
21381 + static {
21382 + System.loadLibrary("attach");
21385 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/jdk.attach/solaris/native/libattach/VirtualMachineImpl.c jdk21u-jdk-21.0.4-ga/src/jdk.attach/solaris/native/libattach/VirtualMachineImpl.c
21386 --- jdk21u-jdk-21.0.4-ga.orig/src/jdk.attach/solaris/native/libattach/VirtualMachineImpl.c 1970-01-01 01:00:00.000000000 +0100
21387 +++ jdk21u-jdk-21.0.4-ga/src/jdk.attach/solaris/native/libattach/VirtualMachineImpl.c 2024-08-17 19:13:01.473573678 +0200
21388 @@ -0,0 +1,389 @@
21390 + * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
21391 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
21393 + * This code is free software; you can redistribute it and/or modify it
21394 + * under the terms of the GNU General Public License version 2 only, as
21395 + * published by the Free Software Foundation. Oracle designates this
21396 + * particular file as subject to the "Classpath" exception as provided
21397 + * by Oracle in the LICENSE file that accompanied this code.
21399 + * This code is distributed in the hope that it will be useful, but WITHOUT
21400 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21401 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21402 + * version 2 for more details (a copy is included in the LICENSE file that
21403 + * accompanied this code).
21405 + * You should have received a copy of the GNU General Public License version
21406 + * 2 along with this work; if not, write to the Free Software Foundation,
21407 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21409 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21410 + * or visit www.oracle.com if you need additional information or have any
21411 + * questions.
21412 + */
21414 +#include "jni_util.h"
21416 +#include <sys/stat.h>
21417 +#include <sys/types.h>
21418 +#include <door.h>
21419 +#include <errno.h>
21420 +#include <fcntl.h>
21421 +#include <limits.h>
21422 +#include <signal.h>
21423 +#include <stdlib.h>
21424 +#include <string.h>
21425 +#include <unistd.h>
21427 +#include "sun_tools_attach_VirtualMachineImpl.h"
21429 +#define ROOT_UID 0
21431 +#define RESTARTABLE(_cmd, _result) do { \
21432 + do { \
21433 + _result = _cmd; \
21434 + } while((_result == -1) && (errno == EINTR)); \
21435 +} while(0)
21438 + * Declare library specific JNI_Onload entry if static build
21439 + */
21440 +DEF_STATIC_JNI_OnLoad
21443 + * Class: sun_tools_attach_VirtualMachineImpl
21444 + * Method: open
21445 + * Signature: (Ljava/lang/String;)I
21446 + */
21447 +JNIEXPORT jint JNICALL Java_sun_tools_attach_VirtualMachineImpl_open
21448 + (JNIEnv *env, jclass cls, jstring path)
21450 + jboolean isCopy;
21451 + const char* p = GetStringPlatformChars(env, path, &isCopy);
21452 + if (p == NULL) {
21453 + return 0;
21454 + } else {
21455 + int fd;
21456 + int err = 0;
21458 + fd = open(p, O_RDWR);
21459 + if (fd == -1) {
21460 + err = errno;
21463 + if (isCopy) {
21464 + JNU_ReleaseStringPlatformChars(env, path, p);
21467 + if (fd == -1) {
21468 + if (err == ENOENT) {
21469 + JNU_ThrowByName(env, "java/io/FileNotFoundException", NULL);
21470 + } else {
21471 + char* msg = strdup(strerror(err));
21472 + JNU_ThrowIOException(env, msg);
21473 + if (msg != NULL) {
21474 + free(msg);
21478 + return fd;
21483 + * Class: sun_tools_attach_VirtualMachineImpl
21484 + * Method: checkPermissions
21485 + * Signature: (Ljava/lang/String;)V
21486 + */
21487 +JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_checkPermissions
21488 + (JNIEnv *env, jclass cls, jstring path)
21490 + jboolean isCopy;
21491 + const char* p = GetStringPlatformChars(env, path, &isCopy);
21492 + if (p != NULL) {
21493 + struct stat64 sb;
21494 + uid_t uid, gid;
21495 + int res;
21497 + memset(&sb, 0, sizeof(struct stat64));
21499 + /*
21500 + * Check that the path is owned by the effective uid/gid of this
21501 + * process. Also check that group/other access is not allowed.
21502 + */
21503 + uid = geteuid();
21504 + gid = getegid();
21506 + res = stat64(p, &sb);
21507 + if (res != 0) {
21508 + /* save errno */
21509 + res = errno;
21512 + if (res == 0) {
21513 + char msg[100];
21514 + jboolean isError = JNI_FALSE;
21515 + if (sb.st_uid != uid && uid != ROOT_UID) {
21516 + snprintf(msg, sizeof(msg),
21517 + "file should be owned by the current user (which is %d) but is owned by %d", uid, sb.st_uid);
21518 + isError = JNI_TRUE;
21519 + } else if (sb.st_gid != gid && uid != ROOT_UID) {
21520 + snprintf(msg, sizeof(msg),
21521 + "file's group should be the current group (which is %d) but the group is %d", gid, sb.st_gid);
21522 + isError = JNI_TRUE;
21523 + } else if ((sb.st_mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) != 0) {
21524 + snprintf(msg, sizeof(msg),
21525 + "file should only be readable and writable by the owner but has 0%03o access", sb.st_mode & 0777);
21526 + isError = JNI_TRUE;
21528 + if (isError) {
21529 + char buf[256];
21530 + snprintf(buf, sizeof(buf), "well-known file %s is not secure: %s", p, msg);
21531 + JNU_ThrowIOException(env, buf);
21533 + } else {
21534 + char* msg = strdup(strerror(res));
21535 + JNU_ThrowIOException(env, msg);
21536 + if (msg != NULL) {
21537 + free(msg);
21541 + if (isCopy) {
21542 + JNU_ReleaseStringPlatformChars(env, path, p);
21548 + * Class: sun_tools_attach_VirtualMachineImpl
21549 + * Method: close
21550 + * Signature: (I)V
21551 + */
21552 +JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_close
21553 + (JNIEnv *env, jclass cls, jint fd)
21555 + int ret;
21556 + RESTARTABLE(close(fd), ret);
21560 + * Class: sun_tools_attach_VirtualMachineImpl
21561 + * Method: read
21562 + * Signature: (I[BI)I
21563 + */
21564 +JNIEXPORT jint JNICALL Java_sun_tools_attach_VirtualMachineImpl_read
21565 + (JNIEnv *env, jclass cls, jint fd, jbyteArray ba, jint off, jint baLen)
21567 + unsigned char buf[128];
21568 + size_t len = sizeof(buf);
21569 + ssize_t n;
21571 + size_t remaining = (size_t)(baLen - off);
21572 + if (len > remaining) {
21573 + len = remaining;
21576 + RESTARTABLE(read(fd, buf, len), n);
21577 + if (n == -1) {
21578 + JNU_ThrowIOExceptionWithLastError(env, "read");
21579 + } else {
21580 + if (n == 0) {
21581 + n = -1; // EOF
21582 + } else {
21583 + (*env)->SetByteArrayRegion(env, ba, off, (jint)n, (jbyte *)(buf));
21586 + return n;
21590 + * Class: sun_tools_attach_VirtualMachineImpl
21591 + * Method: sigquit
21592 + * Signature: (I)V
21593 + */
21594 +JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_sigquit
21595 + (JNIEnv *env, jclass cls, jint pid)
21597 + if (kill((pid_t)pid, SIGQUIT) == -1) {
21598 + JNU_ThrowIOExceptionWithLastError(env, "kill");
21603 + * A simple table to translate some known errors into reasonable
21604 + * error messages
21605 + */
21606 +static struct {
21607 + jint err;
21608 + const char* msg;
21609 +} const error_messages[] = {
21610 + { 100, "Bad request" },
21611 + { 101, "Protocol mismatch" },
21612 + { 102, "Resource failure" },
21613 + { 103, "Internal error" },
21614 + { 104, "Permission denied" },
21618 + * Lookup the given error code and return the appropriate
21619 + * message. If not found return NULL.
21620 + */
21621 +static const char* translate_error(jint err) {
21622 + int table_size = sizeof(error_messages) / sizeof(error_messages[0]);
21623 + int i;
21625 + for (i = 0; i < table_size; i++) {
21626 + if (err == error_messages[i].err) {
21627 + return error_messages[i].msg;
21630 + return NULL;
21634 + * Current protocol version
21635 + */
21636 +static const char* PROTOCOL_VERSION = "1";
21639 + * Class: sun_tools_attach_VirtualMachineImpl
21640 + * Method: enqueue
21641 + * Signature: (JILjava/lang/String;[Ljava/lang/Object;)V
21642 + */
21643 +JNIEXPORT jint JNICALL Java_sun_tools_attach_VirtualMachineImpl_enqueue
21644 + (JNIEnv *env, jclass cls, jint fd, jstring cmd, jobjectArray args)
21646 + jint arg_count, i;
21647 + size_t size;
21648 + jboolean isCopy;
21649 + door_arg_t door_args;
21650 + char res_buffer[128];
21651 + jint result = -1;
21652 + int rc;
21653 + const char* cstr;
21654 + char* buf;
21656 + /*
21657 + * First we get the command string and create the start of the
21658 + * argument string to send to the target VM:
21659 + * <ver>\0<cmd>\0
21660 + */
21661 + cstr = JNU_GetStringPlatformChars(env, cmd, &isCopy);
21662 + if (cstr == NULL) {
21663 + return -1; /* pending exception */
21665 + size = strlen(PROTOCOL_VERSION) + strlen(cstr) + 2;
21666 + buf = (char*)malloc(size);
21667 + if (buf != NULL) {
21668 + char* pos = buf;
21669 + strcpy(buf, PROTOCOL_VERSION);
21670 + pos += strlen(PROTOCOL_VERSION)+1;
21671 + strcpy(pos, cstr);
21673 + if (isCopy) {
21674 + JNU_ReleaseStringPlatformChars(env, cmd, cstr);
21676 + if (buf == NULL) {
21677 + JNU_ThrowOutOfMemoryError(env, "malloc failed");
21678 + return -1;
21681 + /*
21682 + * Next we iterate over the arguments and extend the buffer
21683 + * to include them.
21684 + */
21685 + arg_count = (*env)->GetArrayLength(env, args);
21687 + for (i = 0; i < arg_count; i++) {
21688 + jobject obj = (*env)->GetObjectArrayElement(env, args, i);
21689 + if (obj != NULL) {
21690 + cstr = JNU_GetStringPlatformChars(env, obj, &isCopy);
21691 + if (cstr != NULL) {
21692 + size_t len = strlen(cstr);
21693 + char* newbuf = (char*)realloc(buf, size+len+1);
21694 + if (newbuf != NULL) {
21695 + buf = newbuf;
21696 + strcpy(buf+size, cstr);
21697 + size += len+1;
21699 + if (isCopy) {
21700 + JNU_ReleaseStringPlatformChars(env, obj, cstr);
21702 + if (newbuf == NULL) {
21703 + free(buf);
21704 + JNU_ThrowOutOfMemoryError(env, "realloc failed");
21705 + return -1;
21708 + } else {
21709 + char* newbuf = (char*)realloc(buf, size + 1);
21710 + if (newbuf == NULL) {
21711 + free(buf);
21712 + JNU_ThrowOutOfMemoryError(env, "realloc failed");
21713 + return -1;
21715 + buf = newbuf;
21716 + buf[size++] = 0;
21718 + if ((*env)->ExceptionOccurred(env)) {
21719 + free(buf);
21720 + return -1;
21724 + /*
21725 + * The arguments to the door function are in 'buf' so we now
21726 + * do the door call
21727 + */
21728 + door_args.data_ptr = buf;
21729 + door_args.data_size = size;
21730 + door_args.desc_ptr = NULL;
21731 + door_args.desc_num = 0;
21732 + door_args.rbuf = (char*)&res_buffer;
21733 + door_args.rsize = sizeof(res_buffer);
21735 + RESTARTABLE(door_call(fd, &door_args), rc);
21737 + /*
21738 + * door_call failed
21739 + */
21740 + if (rc == -1) {
21741 + JNU_ThrowIOExceptionWithLastError(env, "door_call");
21742 + } else {
21743 + /*
21744 + * door_call succeeded but the call didn't return the expected jint.
21745 + */
21746 + if (door_args.data_size < sizeof(jint)) {
21747 + JNU_ThrowIOException(env, "Enqueue error - reason unknown as result is truncated!");
21748 + } else {
21749 + jint* res = (jint*)(door_args.data_ptr);
21750 + if (*res != JNI_OK) {
21751 + const char* msg = translate_error(*res);
21752 + char buf[255];
21753 + if (msg == NULL) {
21754 + sprintf(buf, "Unable to enqueue command to target VM: %d", *res);
21755 + } else {
21756 + sprintf(buf, "Unable to enqueue command to target VM: %s", msg);
21758 + JNU_ThrowIOException(env, buf);
21759 + } else {
21760 + /*
21761 + * The door call should return a file descriptor to one end of
21762 + * a socket pair
21763 + */
21764 + if ((door_args.desc_ptr != NULL) &&
21765 + (door_args.desc_num == 1) &&
21766 + (door_args.desc_ptr->d_attributes & DOOR_DESCRIPTOR)) {
21767 + result = door_args.desc_ptr->d_data.d_desc.d_descriptor;
21768 + } else {
21769 + JNU_ThrowIOException(env, "Reply from enqueue missing descriptor!");
21775 + free(buf);
21776 + return result;
21778 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/jdk.charsets/share/classes/sun/nio/cs/ext/JISAutoDetect.java jdk21u-jdk-21.0.4-ga/src/jdk.charsets/share/classes/sun/nio/cs/ext/JISAutoDetect.java
21779 --- jdk21u-jdk-21.0.4-ga.orig/src/jdk.charsets/share/classes/sun/nio/cs/ext/JISAutoDetect.java 2024-07-09 10:07:16.000000000 +0200
21780 +++ jdk21u-jdk-21.0.4-ga/src/jdk.charsets/share/classes/sun/nio/cs/ext/JISAutoDetect.java 2024-08-17 19:13:01.431254715 +0200
21781 @@ -94,7 +94,7 @@
21782 private static class Decoder extends CharsetDecoder {
21784 private static final String SJISName = getSJISName();
21785 - private static final String EUCJPName = "EUC_JP";
21786 + private static final String EUCJPName = getEUCJPName();
21787 private DelegatableDecoder detectedDecoder = null;
21789 public Decoder(Charset cs) {
21790 @@ -222,11 +222,24 @@
21791 * Returned Shift_JIS Charset name is OS dependent
21793 private static String getSJISName() {
21794 - if (OperatingSystem.isWindows())
21795 + if (OperatingSystem.isSolaris())
21796 + return("PCK");
21797 + else if (OperatingSystem.isWindows())
21798 return("windows-31J");
21799 else
21800 return("Shift_JIS");
21803 + /**
21804 + * Returned EUC-JP Charset name is OS dependent
21805 + */
21807 + private static String getEUCJPName() {
21808 + if (OperatingSystem.isSolaris())
21809 + return("x-eucjp-open");
21810 + else
21811 + return("EUC_JP");
21816 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java jdk21u-jdk-21.0.4-ga/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java
21817 --- jdk21u-jdk-21.0.4-ga.orig/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java 2024-07-09 10:07:16.000000000 +0200
21818 +++ jdk21u-jdk-21.0.4-ga/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java 2024-08-17 19:13:01.431974369 +0200
21819 @@ -711,10 +711,15 @@
21820 lib = expand(lib);
21821 int i = lib.indexOf("/$ISA/");
21822 if (i != -1) {
21823 - // replace "/$ISA/" with "/"
21824 + // replace "/$ISA/" with "/amd64/" on Solaris AMD64.
21825 + // On all other platforms, just turn it into a "/"
21826 String prefix = lib.substring(0, i);
21827 String suffix = lib.substring(i + 5);
21828 - lib = prefix + suffix;
21829 + if (osName.equals("SunOS") && osArch.equals("amd64")) {
21830 + lib = prefix + "/amd64" + suffix;
21831 + } else {
21832 + lib = prefix + suffix;
21835 if (DEBUG) {
21836 System.out.println(keyword + ": " + lib);
21837 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/jdk.crypto.cryptoki/solaris/conf/security/sunpkcs11-solaris.cfg jdk21u-jdk-21.0.4-ga/src/jdk.crypto.cryptoki/solaris/conf/security/sunpkcs11-solaris.cfg
21838 --- jdk21u-jdk-21.0.4-ga.orig/src/jdk.crypto.cryptoki/solaris/conf/security/sunpkcs11-solaris.cfg 1970-01-01 01:00:00.000000000 +0100
21839 +++ jdk21u-jdk-21.0.4-ga/src/jdk.crypto.cryptoki/solaris/conf/security/sunpkcs11-solaris.cfg 2024-08-17 19:13:01.474015922 +0200
21840 @@ -0,0 +1,23 @@
21842 +# Configuration file to allow the SunPKCS11 provider to utilize
21843 +# the Solaris Cryptographic Framework, if it is available
21846 +name = Solaris
21848 +description = SunPKCS11 accessing Solaris Cryptographic Framework
21850 +library = /usr/lib/$ISA/libpkcs11.so
21852 +handleStartupErrors = ignoreAll
21854 +# Use the X9.63 encoding for EC points (do not wrap in an ASN.1 OctetString).
21855 +useEcX963Encoding = true
21857 +attributes = compatibility
21859 +disabledMechanisms = {
21860 + CKM_DSA_KEY_PAIR_GEN
21861 + SecureRandom
21864 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HotSpotSolarisVtblAccess.java jdk21u-jdk-21.0.4-ga/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HotSpotSolarisVtblAccess.java
21865 --- jdk21u-jdk-21.0.4-ga.orig/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HotSpotSolarisVtblAccess.java 1970-01-01 01:00:00.000000000 +0100
21866 +++ jdk21u-jdk-21.0.4-ga/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HotSpotSolarisVtblAccess.java 2024-08-17 19:13:01.474316479 +0200
21867 @@ -0,0 +1,65 @@
21869 + * Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
21870 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
21872 + * This code is free software; you can redistribute it and/or modify it
21873 + * under the terms of the GNU General Public License version 2 only, as
21874 + * published by the Free Software Foundation.
21876 + * This code is distributed in the hope that it will be useful, but WITHOUT
21877 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21878 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21879 + * version 2 for more details (a copy is included in the LICENSE file that
21880 + * accompanied this code).
21882 + * You should have received a copy of the GNU General Public License version
21883 + * 2 along with this work; if not, write to the Free Software Foundation,
21884 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21886 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21887 + * or visit www.oracle.com if you need additional information or have any
21888 + * questions.
21890 + */
21892 +package sun.jvm.hotspot;
21894 +import java.util.*;
21895 +import sun.jvm.hotspot.debugger.*;
21896 +import sun.jvm.hotspot.types.*;
21897 +import sun.jvm.hotspot.types.basic.*;
21899 +/** This class implements the compiler-specific access to the vtbl for
21900 + a given C++ type. */
21901 +public class HotSpotSolarisVtblAccess extends BasicVtblAccess {
21903 + public HotSpotSolarisVtblAccess(SymbolLookup symbolLookup,
21904 + String[] jvmLibNames) {
21905 + super(symbolLookup, jvmLibNames);
21908 + protected String vtblSymbolForType(Type type) {
21909 + String demangledSymbol = type.getName() + "::__vtbl";
21910 + return mangle(demangledSymbol);
21913 + //--------------------------------------------------------------------------------
21914 + // Internals only below this point
21915 + //
21917 + private String mangle(String symbol) {
21918 + String[] parts = symbol.split("::");
21919 + StringBuffer mangled = new StringBuffer("__1c");
21920 + for (int i = 0; i < parts.length; i++) {
21921 + int len = parts[i].length();
21922 + if (len >= 26) {
21923 + mangled.append((char)('a' + (len / 26)));
21924 + len = len % 26;
21926 + mangled.append((char)('A' + len));
21927 + mangled.append(parts[i]);
21929 + mangled.append("_");
21930 + return mangled.toString();
21933 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/solaris_amd64/SolarisAMD64JavaThreadPDAccess.java jdk21u-jdk-21.0.4-ga/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/solaris_amd64/SolarisAMD64JavaThreadPDAccess.java
21934 --- jdk21u-jdk-21.0.4-ga.orig/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/solaris_amd64/SolarisAMD64JavaThreadPDAccess.java 1970-01-01 01:00:00.000000000 +0100
21935 +++ jdk21u-jdk-21.0.4-ga/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/solaris_amd64/SolarisAMD64JavaThreadPDAccess.java 2024-08-17 19:13:01.474760812 +0200
21936 @@ -0,0 +1,140 @@
21938 + * Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved.
21939 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
21941 + * This code is free software; you can redistribute it and/or modify it
21942 + * under the terms of the GNU General Public License version 2 only, as
21943 + * published by the Free Software Foundation.
21945 + * This code is distributed in the hope that it will be useful, but WITHOUT
21946 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21947 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21948 + * version 2 for more details (a copy is included in the LICENSE file that
21949 + * accompanied this code).
21951 + * You should have received a copy of the GNU General Public License version
21952 + * 2 along with this work; if not, write to the Free Software Foundation,
21953 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21955 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21956 + * or visit www.oracle.com if you need additional information or have any
21957 + * questions.
21959 + */
21961 +package sun.jvm.hotspot.runtime.solaris_amd64;
21963 +import java.io.*;
21964 +import java.util.*;
21965 +import sun.jvm.hotspot.debugger.*;
21966 +import sun.jvm.hotspot.debugger.amd64.*;
21967 +import sun.jvm.hotspot.runtime.*;
21968 +import sun.jvm.hotspot.runtime.amd64.*;
21969 +import sun.jvm.hotspot.runtime.x86.*;
21970 +import sun.jvm.hotspot.types.*;
21971 +import sun.jvm.hotspot.utilities.*;
21972 +import sun.jvm.hotspot.utilities.Observable;
21973 +import sun.jvm.hotspot.utilities.Observer;
21975 +public class SolarisAMD64JavaThreadPDAccess implements JavaThreadPDAccess {
21976 + private static AddressField lastJavaFPField;
21977 + private static AddressField osThreadField;
21978 + private static AddressField baseOfStackPointerField;
21980 + // Field from OSThread
21981 + private static CIntegerField osThreadThreadIDField;
21983 + // This is currently unneeded but is being kept in case we change
21984 + // the currentFrameGuess algorithm
21985 + private static final long GUESS_SCAN_RANGE = 128 * 1024;
21988 + static {
21989 + VM.registerVMInitializedObserver(new Observer() {
21990 + public void update(Observable o, Object data) {
21991 + initialize(VM.getVM().getTypeDataBase());
21993 + });
21996 + private static synchronized void initialize(TypeDataBase db) {
21997 + Type type = db.lookupType("JavaThread");
21998 + Type anchorType = db.lookupType("JavaFrameAnchor");
22000 + lastJavaFPField = anchorType.getAddressField("_last_Java_fp");
22001 + osThreadField = type.getAddressField("_osthread");
22003 + type = db.lookupType("OSThread");
22004 + osThreadThreadIDField = type.getCIntegerField("_thread_id");
22007 + public Address getLastJavaFP(Address addr) {
22008 + return lastJavaFPField.getValue(addr.addOffsetTo(sun.jvm.hotspot.runtime.JavaThread.getAnchorField().getOffset()));
22011 + public Address getLastJavaPC(Address addr) {
22012 + return null;
22015 + public Address getBaseOfStackPointer(Address addr) {
22016 + return null;
22019 + public Frame getLastFramePD(JavaThread thread, Address addr) {
22020 + Address fp = thread.getLastJavaFP();
22021 + if (fp == null) {
22022 + return null; // no information
22024 + Address pc = thread.getLastJavaPC();
22025 + if ( pc != null ) {
22026 + return new X86Frame(thread.getLastJavaSP(), fp, pc);
22027 + } else {
22028 + return new X86Frame(thread.getLastJavaSP(), fp);
22032 + public RegisterMap newRegisterMap(JavaThread thread, boolean updateMap) {
22033 + return new X86RegisterMap(thread, updateMap);
22036 + public Frame getCurrentFrameGuess(JavaThread thread, Address addr) {
22037 + ThreadProxy t = getThreadProxy(addr);
22038 + AMD64ThreadContext context = (AMD64ThreadContext) t.getContext();
22039 + AMD64CurrentFrameGuess guesser = new AMD64CurrentFrameGuess(context, thread);
22040 + if (!guesser.run(GUESS_SCAN_RANGE)) {
22041 + return null;
22043 + if (guesser.getPC() == null) {
22044 + return new X86Frame(guesser.getSP(), guesser.getFP());
22045 + } else {
22046 + return new X86Frame(guesser.getSP(), guesser.getFP(), guesser.getPC());
22051 + public void printThreadIDOn(Address addr, PrintStream tty) {
22052 + tty.print(getThreadProxy(addr));
22056 + public void printInfoOn(Address threadAddr, PrintStream tty) {
22059 + public Address getLastSP(Address addr) {
22060 + ThreadProxy t = getThreadProxy(addr);
22061 + AMD64ThreadContext context = (AMD64ThreadContext) t.getContext();
22062 + return context.getRegisterAsAddress(AMD64ThreadContext.RSP);
22065 + public ThreadProxy getThreadProxy(Address addr) {
22066 + // Fetch the OSThread (for now and for simplicity, not making a
22067 + // separate "OSThread" class in this package)
22068 + Address osThreadAddr = osThreadField.getValue(addr);
22069 + // Get the address of the thread ID from the OSThread
22070 + Address tidAddr = osThreadAddr.addOffsetTo(osThreadThreadIDField.getOffset());
22072 + JVMDebugger debugger = VM.getVM().getDebugger();
22073 + return debugger.getThreadForIdentifierAddress(tidAddr);
22077 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/solaris_x86/SolarisX86JavaThreadPDAccess.java jdk21u-jdk-21.0.4-ga/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/solaris_x86/SolarisX86JavaThreadPDAccess.java
22078 --- jdk21u-jdk-21.0.4-ga.orig/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/solaris_x86/SolarisX86JavaThreadPDAccess.java 1970-01-01 01:00:00.000000000 +0100
22079 +++ jdk21u-jdk-21.0.4-ga/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/solaris_x86/SolarisX86JavaThreadPDAccess.java 2024-08-17 19:13:01.475216632 +0200
22080 @@ -0,0 +1,142 @@
22082 + * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
22083 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
22085 + * This code is free software; you can redistribute it and/or modify it
22086 + * under the terms of the GNU General Public License version 2 only, as
22087 + * published by the Free Software Foundation.
22089 + * This code is distributed in the hope that it will be useful, but WITHOUT
22090 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
22091 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22092 + * version 2 for more details (a copy is included in the LICENSE file that
22093 + * accompanied this code).
22095 + * You should have received a copy of the GNU General Public License version
22096 + * 2 along with this work; if not, write to the Free Software Foundation,
22097 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
22099 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22100 + * or visit www.oracle.com if you need additional information or have any
22101 + * questions.
22103 + */
22105 +package sun.jvm.hotspot.runtime.solaris_x86;
22107 +import java.io.*;
22108 +import java.util.*;
22109 +import sun.jvm.hotspot.debugger.*;
22110 +import sun.jvm.hotspot.debugger.x86.*;
22111 +import sun.jvm.hotspot.runtime.*;
22112 +import sun.jvm.hotspot.runtime.x86.*;
22113 +import sun.jvm.hotspot.types.*;
22114 +import sun.jvm.hotspot.utilities.*;
22115 +import sun.jvm.hotspot.utilities.Observable;
22116 +import sun.jvm.hotspot.utilities.Observer;
22118 +/** Placeholder for now to allow us to start the SA without support
22119 + for stack traces */
22121 +public class SolarisX86JavaThreadPDAccess implements JavaThreadPDAccess {
22122 + private static AddressField lastJavaFPField;
22123 + private static AddressField osThreadField;
22124 + private static AddressField baseOfStackPointerField;
22126 + // Field from OSThread
22127 + private static CIntegerField osThreadThreadIDField;
22129 + // This is currently unneeded but is being kept in case we change
22130 + // the currentFrameGuess algorithm
22131 + private static final long GUESS_SCAN_RANGE = 128 * 1024;
22134 + static {
22135 + VM.registerVMInitializedObserver(new Observer() {
22136 + public void update(Observable o, Object data) {
22137 + initialize(VM.getVM().getTypeDataBase());
22139 + });
22142 + private static synchronized void initialize(TypeDataBase db) {
22143 + Type type = db.lookupType("JavaThread");
22144 + Type anchorType = db.lookupType("JavaFrameAnchor");
22146 + lastJavaFPField = anchorType.getAddressField("_last_Java_fp");
22147 + osThreadField = type.getAddressField("_osthread");
22149 + type = db.lookupType("OSThread");
22150 + osThreadThreadIDField = type.getCIntegerField("_thread_id");
22153 + public Address getLastJavaFP(Address addr) {
22154 + return lastJavaFPField.getValue(addr.addOffsetTo(sun.jvm.hotspot.runtime.JavaThread.getAnchorField().getOffset()));
22157 + public Address getLastJavaPC(Address addr) {
22158 + return null;
22161 + public Address getBaseOfStackPointer(Address addr) {
22162 + return null;
22165 + public Frame getLastFramePD(JavaThread thread, Address addr) {
22166 + Address fp = thread.getLastJavaFP();
22167 + if (fp == null) {
22168 + return null; // no information
22170 + Address pc = thread.getLastJavaPC();
22171 + if ( pc != null ) {
22172 + return new X86Frame(thread.getLastJavaSP(), fp, pc);
22173 + } else {
22174 + return new X86Frame(thread.getLastJavaSP(), fp);
22178 + public RegisterMap newRegisterMap(JavaThread thread, boolean updateMap) {
22179 + return new X86RegisterMap(thread, updateMap);
22182 + public Frame getCurrentFrameGuess(JavaThread thread, Address addr) {
22183 + ThreadProxy t = getThreadProxy(addr);
22184 + X86ThreadContext context = (X86ThreadContext) t.getContext();
22185 + X86CurrentFrameGuess guesser = new X86CurrentFrameGuess(context, thread);
22186 + if (!guesser.run(GUESS_SCAN_RANGE)) {
22187 + return null;
22189 + if (guesser.getPC() == null) {
22190 + return new X86Frame(guesser.getSP(), guesser.getFP());
22191 + } else {
22192 + return new X86Frame(guesser.getSP(), guesser.getFP(), guesser.getPC());
22197 + public void printThreadIDOn(Address addr, PrintStream tty) {
22198 + tty.print(getThreadProxy(addr));
22202 + public void printInfoOn(Address threadAddr, PrintStream tty) {
22205 + public Address getLastSP(Address addr) {
22206 + ThreadProxy t = getThreadProxy(addr);
22207 + X86ThreadContext context = (X86ThreadContext) t.getContext();
22208 + return context.getRegisterAsAddress(X86ThreadContext.ESP);
22211 + public ThreadProxy getThreadProxy(Address addr) {
22212 + // Fetch the OSThread (for now and for simplicity, not making a
22213 + // separate "OSThread" class in this package)
22214 + Address osThreadAddr = osThreadField.getValue(addr);
22215 + // Get the address of the thread ID from the OSThread
22216 + Address tidAddr = osThreadAddr.addOffsetTo(osThreadThreadIDField.getOffset());
22218 + JVMDebugger debugger = VM.getVM().getDebugger();
22219 + return debugger.getThreadForIdentifierAddress(tidAddr);
22223 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java jdk21u-jdk-21.0.4-ga/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java
22224 --- jdk21u-jdk-21.0.4-ga.orig/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java 2024-07-09 10:07:16.000000000 +0200
22225 +++ jdk21u-jdk-21.0.4-ga/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java 2024-08-17 19:13:01.432740197 +0200
22226 @@ -28,6 +28,8 @@
22228 import sun.jvm.hotspot.debugger.*;
22229 import sun.jvm.hotspot.types.*;
22230 +import sun.jvm.hotspot.runtime.solaris_x86.SolarisX86JavaThreadPDAccess;
22231 +import sun.jvm.hotspot.runtime.solaris_amd64.SolarisAMD64JavaThreadPDAccess;
22232 import sun.jvm.hotspot.runtime.win32_x86.Win32X86JavaThreadPDAccess;
22233 import sun.jvm.hotspot.runtime.win32_amd64.Win32AMD64JavaThreadPDAccess;
22234 import sun.jvm.hotspot.runtime.win32_aarch64.Win32AARCH64JavaThreadPDAccess;
22235 @@ -97,7 +99,13 @@
22237 access = null;
22238 // FIXME: find the platform specific PD class by reflection?
22239 - if (os.equals("win32")) {
22240 + if (os.equals("solaris")) {
22241 + if (cpu.equals("x86")) {
22242 + access = new SolarisX86JavaThreadPDAccess();
22243 + } else if (cpu.equals("amd64")) {
22244 + access = new SolarisAMD64JavaThreadPDAccess();
22246 + } else if (os.equals("win32")) {
22247 if (cpu.equals("x86")) {
22248 access = new Win32X86JavaThreadPDAccess();
22249 } else if (cpu.equals("amd64")) {
22250 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java jdk21u-jdk-21.0.4-ga/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java
22251 --- jdk21u-jdk-21.0.4-ga.orig/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java 2024-07-09 10:07:16.000000000 +0200
22252 +++ jdk21u-jdk-21.0.4-ga/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java 2024-08-17 19:13:01.433247259 +0200
22253 @@ -28,10 +28,14 @@
22254 system. */
22256 public class PlatformInfo {
22257 - /* Returns "win32" if Windows; "linux" if Linux. */
22258 + /* Returns "solaris" if on Solaris; "win32" if Windows; "linux" if
22259 + Linux. Used to determine location of dbx and import module, or
22260 + possible debugger agent on win32. */
22261 public static String getOS() throws UnsupportedPlatformException {
22262 String os = System.getProperty("os.name");
22263 - if (os.equals("Linux")) {
22264 + if (os.equals("SunOS")) {
22265 + return "solaris";
22266 + } else if (os.equals("Linux")) {
22267 return "linux";
22268 } else if (os.equals("FreeBSD")) {
22269 return "bsd";
22270 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/jdk.hotspot.agent/share/native/libsaproc/ps_core_common.c jdk21u-jdk-21.0.4-ga/src/jdk.hotspot.agent/share/native/libsaproc/ps_core_common.c
22271 --- jdk21u-jdk-21.0.4-ga.orig/src/jdk.hotspot.agent/share/native/libsaproc/ps_core_common.c 2024-07-09 10:07:16.000000000 +0200
22272 +++ jdk21u-jdk-21.0.4-ga/src/jdk.hotspot.agent/share/native/libsaproc/ps_core_common.c 2024-08-17 19:13:01.433813532 +0200
22273 @@ -22,6 +22,8 @@
22277 +#include <jni.h> // just include something, or else solaris compiler will complain that this file is empty
22279 #if defined(LINUX) || defined(__APPLE__)
22280 #include <unistd.h>
22281 #include <fcntl.h>
22282 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/jdk.hotspot.agent/test/libproc/libproctest.sh jdk21u-jdk-21.0.4-ga/src/jdk.hotspot.agent/test/libproc/libproctest.sh
22283 --- jdk21u-jdk-21.0.4-ga.orig/src/jdk.hotspot.agent/test/libproc/libproctest.sh 2024-07-09 10:07:16.000000000 +0200
22284 +++ jdk21u-jdk-21.0.4-ga/src/jdk.hotspot.agent/test/libproc/libproctest.sh 2024-08-17 19:13:01.434275829 +0200
22285 @@ -59,8 +59,10 @@
22286 kill -9 $pid
22289 +OPTIONS="-Djava.library.path=$STARTDIR/../src/os/solaris/proc/`uname -p`:$STARTDIR/../solaris/`uname -p`"
22291 # run libproc client
22292 -$SA_JAVA -showversion -cp $STARTDIR/../../build/classes::$STARTDIR/../sa.jar:$STARTDIR LibprocClient x core.$pid
22293 +$SA_JAVA -showversion ${OPTIONS} -cp $STARTDIR/../../build/classes::$STARTDIR/../sa.jar:$STARTDIR LibprocClient x core.$pid
22295 # delete core
22296 rm -f core.$pid
22297 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/jdk.jdwp.agent/unix/native/libdt_socket/socket_md.c jdk21u-jdk-21.0.4-ga/src/jdk.jdwp.agent/unix/native/libdt_socket/socket_md.c
22298 --- jdk21u-jdk-21.0.4-ga.orig/src/jdk.jdwp.agent/unix/native/libdt_socket/socket_md.c 2024-07-09 10:07:16.000000000 +0200
22299 +++ jdk21u-jdk-21.0.4-ga/src/jdk.jdwp.agent/unix/native/libdt_socket/socket_md.c 2024-08-17 19:13:01.434902545 +0200
22300 @@ -33,8 +33,12 @@
22301 #include <errno.h>
22302 #include <string.h>
22303 #include <sys/time.h>
22304 +#ifdef __solaris__
22305 +#include <thread.h>
22306 +#else
22307 #include <pthread.h>
22308 #include <poll.h>
22309 +#endif
22311 #include "socket_md.h"
22312 #include "sysSocket.h"
22313 @@ -271,6 +275,35 @@
22314 return 0;
22317 +#ifdef __solaris__
22318 +int
22319 +dbgsysTlsAlloc() {
22320 + thread_key_t tk;
22321 + if (thr_keycreate(&tk, NULL)) {
22322 + perror("thr_keycreate");
22323 + exit(-1);
22325 + return (int)tk;
22328 +void
22329 +dbgsysTlsFree(int index) {
22330 + /* no-op */
22333 +void
22334 +dbgsysTlsPut(int index, void *value) {
22335 + thr_setspecific((thread_key_t)index, value) ;
22338 +void *
22339 +dbgsysTlsGet(int index) {
22340 + void* r = NULL;
22341 + thr_getspecific((thread_key_t)index, &r);
22342 + return r;
22345 +#else
22347 dbgsysTlsAlloc() {
22348 pthread_key_t key;
22349 @@ -296,6 +329,8 @@
22350 return pthread_getspecific((pthread_key_t)index);
22353 +#endif
22355 long
22356 dbgsysCurrentTimeMillis() {
22357 struct timeval t;
22358 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/jdk.management/solaris/native/libmanagement_ext/UnixOperatingSystem.c jdk21u-jdk-21.0.4-ga/src/jdk.management/solaris/native/libmanagement_ext/UnixOperatingSystem.c
22359 --- jdk21u-jdk-21.0.4-ga.orig/src/jdk.management/solaris/native/libmanagement_ext/UnixOperatingSystem.c 1970-01-01 01:00:00.000000000 +0100
22360 +++ jdk21u-jdk-21.0.4-ga/src/jdk.management/solaris/native/libmanagement_ext/UnixOperatingSystem.c 2024-08-17 19:13:01.475762943 +0200
22361 @@ -0,0 +1,254 @@
22363 + * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
22364 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
22366 + * This code is free software; you can redistribute it and/or modify it
22367 + * under the terms of the GNU General Public License version 2 only, as
22368 + * published by the Free Software Foundation. Oracle designates this
22369 + * particular file as subject to the "Classpath" exception as provided
22370 + * by Oracle in the LICENSE file that accompanied this code.
22372 + * This code is distributed in the hope that it will be useful, but WITHOUT
22373 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
22374 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22375 + * version 2 for more details (a copy is included in the LICENSE file that
22376 + * accompanied this code).
22378 + * You should have received a copy of the GNU General Public License version
22379 + * 2 along with this work; if not, write to the Free Software Foundation,
22380 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
22382 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22383 + * or visit www.oracle.com if you need additional information or have any
22384 + * questions.
22385 + */
22387 +#include <fcntl.h>
22388 +#include <kstat.h>
22389 +#include <procfs.h>
22390 +#include <unistd.h>
22391 +#include <stdlib.h>
22392 +#include <stdio.h>
22393 +#include <string.h>
22394 +#include <sys/sysinfo.h>
22395 +#include <sys/lwp.h>
22396 +#include <pthread.h>
22397 +#include <utmpx.h>
22398 +#include <dlfcn.h>
22399 +#include <sys/loadavg.h>
22400 +#include <jni.h>
22401 +#include "jvm.h"
22402 +#include "com_sun_management_internal_OperatingSystemImpl.h"
22404 +typedef struct {
22405 + kstat_t *kstat;
22406 + uint64_t last_idle;
22407 + uint64_t last_total;
22408 + double last_ratio;
22409 +} cpuload_t;
22411 +static cpuload_t *cpu_loads = NULL;
22412 +static unsigned int num_cpus;
22413 +static kstat_ctl_t *kstat_ctrl = NULL;
22415 +static void map_cpu_kstat_counters() {
22416 + kstat_t *kstat;
22417 + int i;
22419 + // Get number of CPU(s)
22420 + if ((num_cpus = sysconf(_SC_NPROCESSORS_ONLN)) == -1) {
22421 + num_cpus = 1;
22424 + // Data structure for saving CPU load
22425 + if ((cpu_loads = calloc(num_cpus,sizeof(cpuload_t))) == NULL) {
22426 + return;
22429 + // Get kstat cpu_stat counters for every CPU
22430 + // (loop over kstat to find our cpu_stat(s)
22431 + i = 0;
22432 + for (kstat = kstat_ctrl->kc_chain; kstat != NULL; kstat = kstat->ks_next) {
22433 + if (strncmp(kstat->ks_module, "cpu_stat", 8) == 0) {
22435 + if (kstat_read(kstat_ctrl, kstat, NULL) == -1) {
22436 + // Failed to initialize kstat for this CPU so ignore it
22437 + continue;
22440 + if (i == num_cpus) {
22441 + // Found more cpu_stats than reported CPUs
22442 + break;
22445 + cpu_loads[i++].kstat = kstat;
22450 +static int init_cpu_kstat_counters() {
22451 + static int initialized = 0;
22453 + // Concurrence in this method is prevented by the lock in
22454 + // the calling method get_cpu_load();
22455 + if(!initialized) {
22456 + if ((kstat_ctrl = kstat_open()) != NULL) {
22457 + map_cpu_kstat_counters();
22458 + initialized = 1;
22461 + return initialized ? 0 : -1;
22464 +static void update_cpu_kstat_counters() {
22465 + if(kstat_chain_update(kstat_ctrl) != 0) {
22466 + free(cpu_loads);
22467 + map_cpu_kstat_counters();
22471 +int read_cpustat(cpuload_t *load, cpu_stat_t *cpu_stat) {
22472 + if (load->kstat == NULL) {
22473 + // no handle.
22474 + return -1;
22476 + if (kstat_read(kstat_ctrl, load->kstat, cpu_stat) == -1) {
22477 + // disabling for now, a kstat chain update is likely to happen next time
22478 + load->kstat = NULL;
22479 + return -1;
22481 + return 0;
22484 +double get_single_cpu_load(unsigned int n) {
22485 + cpuload_t *load;
22486 + cpu_stat_t cpu_stat;
22487 + uint_t *usage;
22488 + uint64_t c_idle;
22489 + uint64_t c_total;
22490 + uint64_t d_idle;
22491 + uint64_t d_total;
22492 + int i;
22494 + if (n >= num_cpus) {
22495 + return -1.0;
22498 + load = &cpu_loads[n];
22499 + if (read_cpustat(load, &cpu_stat) < 0) {
22500 + return -1.0;
22503 + usage = cpu_stat.cpu_sysinfo.cpu;
22504 + c_idle = usage[CPU_IDLE];
22506 + for (c_total = 0, i = 0; i < CPU_STATES; i++) {
22507 + c_total += usage[i];
22510 + // Calculate diff against previous snapshot
22511 + d_idle = c_idle - load->last_idle;
22512 + d_total = c_total - load->last_total;
22514 + /** update if weve moved */
22515 + if (d_total > 0) {
22516 + // Save current values for next time around
22517 + load->last_idle = c_idle;
22518 + load->last_total = c_total;
22519 + load->last_ratio = (double) (d_total - d_idle) / d_total;
22522 + return load->last_ratio;
22525 +int get_info(const char *path, void *info, size_t s, off_t o) {
22526 + int fd;
22527 + int ret = 0;
22528 + if ((fd = open(path, O_RDONLY)) < 0) {
22529 + return -1;
22531 + if (pread(fd, info, s, o) != s) {
22532 + ret = -1;
22534 + close(fd);
22535 + return ret;
22538 +#define MIN(a, b) ((a < b) ? a : b)
22540 +static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
22542 +/**
22543 + * Return the cpu load (0-1) for proc number 'which' (or average all if which == -1)
22544 + */
22545 +double get_cpu_load(int which) {
22546 + double load =.0;
22548 + pthread_mutex_lock(&lock);
22549 + if(init_cpu_kstat_counters()==0) {
22551 + update_cpu_kstat_counters();
22553 + if (which == -1) {
22554 + unsigned int i;
22555 + double t;
22557 + for (t = .0, i = 0; i < num_cpus; i++) {
22558 + t += get_single_cpu_load(i);
22561 + // Cap total systemload to 1.0
22562 + load = MIN((t / num_cpus), 1.0);
22563 + } else {
22564 + load = MIN(get_single_cpu_load(which), 1.0);
22566 + } else {
22567 + load = -1.0;
22569 + pthread_mutex_unlock(&lock);
22571 + return load;
22574 +/**
22575 + * Return the cpu load (0-1) for the current process (i.e the JVM)
22576 + * or -1.0 if the get_info() call failed
22577 + */
22578 +double get_process_load(void) {
22579 + psinfo_t info;
22581 + // Get the percentage of "recent cpu usage" from all the lwp:s in the JVM:s
22582 + // process. This is returned as a value between 0.0 and 1.0 multiplied by 0x8000.
22583 + if (get_info("/proc/self/psinfo",&info.pr_pctcpu, sizeof(info.pr_pctcpu), offsetof(psinfo_t, pr_pctcpu)) == 0) {
22584 + return (double) info.pr_pctcpu / 0x8000;
22586 + return -1.0;
22589 +JNIEXPORT jdouble JNICALL
22590 +Java_com_sun_management_internal_OperatingSystemImpl_getCpuLoad0
22591 +(JNIEnv *env, jobject dummy)
22593 + return get_cpu_load(-1);
22596 +JNIEXPORT jdouble JNICALL
22597 +Java_com_sun_management_internal_OperatingSystemImpl_getProcessCpuLoad0
22598 +(JNIEnv *env, jobject dummy)
22600 + return get_process_load();
22603 +JNIEXPORT jdouble JNICALL
22604 +Java_com_sun_management_internal_OperatingSystemImpl_getSingleCpuLoad0
22605 +(JNIEnv *env, jobject mbean, jint cpu_number)
22607 + return -1.0;
22610 +JNIEXPORT jint JNICALL
22611 +Java_com_sun_management_internal_OperatingSystemImpl_getHostConfiguredCpuCount0
22612 +(JNIEnv *env, jobject mbean)
22614 + return -1;
22616 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/jdk.management/unix/native/libmanagement_ext/OperatingSystemImpl.c jdk21u-jdk-21.0.4-ga/src/jdk.management/unix/native/libmanagement_ext/OperatingSystemImpl.c
22617 --- jdk21u-jdk-21.0.4-ga.orig/src/jdk.management/unix/native/libmanagement_ext/OperatingSystemImpl.c 2024-07-09 10:07:16.000000000 +0200
22618 +++ jdk21u-jdk-21.0.4-ga/src/jdk.management/unix/native/libmanagement_ext/OperatingSystemImpl.c 2024-08-17 19:13:01.435601571 +0200
22619 @@ -85,7 +85,63 @@
22620 // true = get available swap in bytes
22621 // false = get total swap in bytes
22622 static jlong get_total_or_available_swap_space_size(JNIEnv* env, jboolean available) {
22623 -#if defined(__linux__)
22624 +#ifdef __solaris__
22625 + long total, avail;
22626 + int nswap, i, count;
22627 + swaptbl_t *stbl;
22628 + char *strtab;
22630 + // First get the number of swap resource entries
22631 + if ((nswap = swapctl(SC_GETNSWP, NULL)) == -1) {
22632 + throw_internal_error(env, "swapctl failed to get nswap");
22633 + return -1;
22635 + if (nswap == 0) {
22636 + return 0;
22639 + // Allocate storage for resource entries
22640 + stbl = (swaptbl_t*) malloc(nswap * sizeof(swapent_t) +
22641 + sizeof(struct swaptable));
22642 + if (stbl == NULL) {
22643 + JNU_ThrowOutOfMemoryError(env, 0);
22644 + return -1;
22647 + // Allocate storage for the table
22648 + strtab = (char*) malloc((nswap + 1) * MAXPATHLEN);
22649 + if (strtab == NULL) {
22650 + free(stbl);
22651 + JNU_ThrowOutOfMemoryError(env, 0);
22652 + return -1;
22655 + for (i = 0; i < (nswap + 1); i++) {
22656 + stbl->swt_ent[i].ste_path = strtab + (i * MAXPATHLEN);
22658 + stbl->swt_n = nswap + 1;
22660 + // Get the entries
22661 + if ((count = swapctl(SC_LIST, stbl)) < 0) {
22662 + free(stbl);
22663 + free(strtab);
22664 + throw_internal_error(env, "swapctl failed to get swap list");
22665 + return -1;
22668 + // Sum the entries to get total and free swap
22669 + total = 0;
22670 + avail = 0;
22671 + for (i = 0; i < count; i++) {
22672 + total += stbl->swt_ent[i].ste_pages;
22673 + avail += stbl->swt_ent[i].ste_free;
22676 + free(stbl);
22677 + free(strtab);
22678 + return available ? ((jlong)avail * page_size) :
22679 + ((jlong)total * page_size);
22680 +#elif defined(__linux__)
22681 int ret;
22682 jlong total = 0, avail = 0;
22684 @@ -134,7 +190,37 @@
22685 Java_com_sun_management_internal_OperatingSystemImpl_getCommittedVirtualMemorySize0
22686 (JNIEnv *env, jobject mbean)
22688 -#if defined(__APPLE__)
22689 +#ifdef __solaris__
22690 + psinfo_t psinfo;
22691 + ssize_t result;
22692 + size_t remaining;
22693 + char* addr;
22694 + int fd;
22696 + fd = open64("/proc/self/psinfo", O_RDONLY, 0);
22697 + if (fd < 0) {
22698 + throw_internal_error(env, "Unable to open /proc/self/psinfo");
22699 + return -1;
22702 + addr = (char *)&psinfo;
22703 + for (remaining = sizeof(psinfo_t); remaining > 0;) {
22704 + result = read(fd, addr, remaining);
22705 + if (result < 0) {
22706 + if (errno != EINTR) {
22707 + close(fd);
22708 + throw_internal_error(env, "Unable to read /proc/self/psinfo");
22709 + return -1;
22711 + } else {
22712 + remaining -= result;
22713 + addr += result;
22717 + close(fd);
22718 + return (jlong) psinfo.pr_size * 1024;
22719 +#elif defined(__APPLE__)
22720 struct task_basic_info t_info;
22721 mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;
22723 @@ -190,7 +276,7 @@
22724 * BSDNOTE: FreeBSD implements _SC_CLK_TCK since FreeBSD 5, so
22725 * add a magic to handle it
22727 -#if defined(_SC_CLK_TCK)
22728 +#if defined(__solaris__) || defined(_SC_CLK_TCK)
22729 clk_tck = (jlong) sysconf(_SC_CLK_TCK);
22730 #elif defined(__linux__) || defined(_ALLBSD_SOURCE)
22731 clk_tck = 100;
22732 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpNet.java jdk21u-jdk-21.0.4-ga/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpNet.java
22733 --- jdk21u-jdk-21.0.4-ga.orig/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpNet.java 2024-07-09 10:07:16.000000000 +0200
22734 +++ jdk21u-jdk-21.0.4-ga/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpNet.java 2024-08-17 19:13:01.436176349 +0200
22735 @@ -44,6 +44,12 @@
22736 /* -- Miscellaneous SCTP utilities -- */
22738 private static boolean IPv4MappedAddresses() {
22739 + if (true) {
22740 + /* FIXME - nonportable hack */
22741 + /* Solaris supports IPv4Mapped Addresses with bindx */
22742 + return true;
22743 + } /* else { //other OS/implementations */
22745 /* lksctp/linux requires Ipv4 addresses */
22746 return false;
22748 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/jdk.sctp/unix/native/libsctp/Sctp.h jdk21u-jdk-21.0.4-ga/src/jdk.sctp/unix/native/libsctp/Sctp.h
22749 --- jdk21u-jdk-21.0.4-ga.orig/src/jdk.sctp/unix/native/libsctp/Sctp.h 2024-07-09 10:07:16.000000000 +0200
22750 +++ jdk21u-jdk-21.0.4-ga/src/jdk.sctp/unix/native/libsctp/Sctp.h 2024-08-17 19:13:01.436753194 +0200
22751 @@ -26,6 +26,48 @@
22752 #ifndef SUN_NIO_CH_SCTP_H
22753 #define SUN_NIO_CH_SCTP_H
22755 +#ifdef __solaris__
22757 +#define _XPG4_2
22758 +#define __EXTENSIONS__
22759 +#include <sys/socket.h>
22760 +#include <netinet/sctp.h>
22761 +#include "jni.h"
22763 +/* Current Solaris headers don't comply with draft rfc */
22764 +#ifndef SCTP_EOF
22765 +#define SCTP_EOF MSG_EOF
22766 +#endif
22768 +#ifndef SCTP_UNORDERED
22769 +#define SCTP_UNORDERED MSG_UNORDERED
22770 +#endif
22772 +/* The current version of the socket API extension shipped with Solaris does
22773 + * not define the following options that the Java API (optionally) supports */
22774 +#ifndef SCTP_EXPLICIT_EOR
22775 +#define SCTP_EXPLICIT_EOR -1
22776 +#endif
22777 +#ifndef SCTP_FRAGMENT_INTERLEAVE
22778 +#define SCTP_FRAGMENT_INTERLEAVE -1
22779 +#endif
22780 +#ifndef SCTP_SET_PEER_PRIMARY_ADDR
22781 +#define SCTP_SET_PEER_PRIMARY_ADDR -1
22782 +#endif
22784 +/* Function types to support dynamic linking of socket API extension functions
22785 + * for SCTP. This is so that there is no linkage depandancy during build or
22786 + * runtime for libsctp.*/
22787 +typedef int sctp_getladdrs_func(int sock, sctp_assoc_t id, void **addrs);
22788 +typedef int sctp_freeladdrs_func(void* addrs);
22789 +typedef int sctp_getpaddrs_func(int sock, sctp_assoc_t id, void **addrs);
22790 +typedef int sctp_freepaddrs_func(void *addrs);
22791 +typedef int sctp_bindx_func(int sock, void *addrs, int addrcnt, int flags);
22792 +typedef int sctp_peeloff_func(int sock, sctp_assoc_t id);
22796 +#else /* __linux__ */
22797 #include <stdint.h>
22798 #include <linux/types.h>
22799 #include <sys/socket.h>
22800 @@ -278,6 +320,8 @@
22801 typedef int sctp_peeloff_func(int sock, sctp_assoc_t id);
22804 +#endif /* __linux__ */
22806 extern sctp_getladdrs_func* nio_sctp_getladdrs;
22807 extern sctp_freeladdrs_func* nio_sctp_freeladdrs;
22808 extern sctp_getpaddrs_func* nio_sctp_getpaddrs;
22809 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/jdk.sctp/unix/native/libsctp/SctpChannelImpl.c jdk21u-jdk-21.0.4-ga/src/jdk.sctp/unix/native/libsctp/SctpChannelImpl.c
22810 --- jdk21u-jdk-21.0.4-ga.orig/src/jdk.sctp/unix/native/libsctp/SctpChannelImpl.c 2024-07-09 10:07:16.000000000 +0200
22811 +++ jdk21u-jdk-21.0.4-ga/src/jdk.sctp/unix/native/libsctp/SctpChannelImpl.c 2024-08-17 19:13:01.437262559 +0200
22812 @@ -331,11 +331,10 @@
22813 break;
22814 case SCTP_ADDR_MADE_PRIM :
22815 event = sun_nio_ch_sctp_PeerAddrChange_SCTP_ADDR_MADE_PRIM;
22816 +#ifdef __linux__ /* Solaris currently doesn't support SCTP_ADDR_CONFIRMED */
22817 break;
22818 -#ifdef __linux__
22819 case SCTP_ADDR_CONFIRMED :
22820 event = sun_nio_ch_sctp_PeerAddrChange_SCTP_ADDR_CONFIRMED;
22821 - break;
22822 #endif /* __linux__ */
22825 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/jdk.sctp/unix/native/libsctp/SctpNet.c jdk21u-jdk-21.0.4-ga/src/jdk.sctp/unix/native/libsctp/SctpNet.c
22826 --- jdk21u-jdk-21.0.4-ga.orig/src/jdk.sctp/unix/native/libsctp/SctpNet.c 2024-07-09 10:07:16.000000000 +0200
22827 +++ jdk21u-jdk-21.0.4-ga/src/jdk.sctp/unix/native/libsctp/SctpNet.c 2024-08-17 19:13:01.437813542 +0200
22828 @@ -371,7 +371,11 @@
22829 int i, addrCount;
22830 jobjectArray isaa;
22832 +#ifdef __solaris__
22833 + if ((addrCount = nio_sctp_getladdrs(fd, 0, (void **)&addr_buf)) == -1) {
22834 +#else /* __linux__ */
22835 if ((addrCount = nio_sctp_getladdrs(fd, 0, (struct sockaddr **)&addr_buf)) == -1) {
22836 +#endif
22837 sctpHandleSocketError(env, errno);
22838 return NULL;
22840 @@ -416,7 +420,11 @@
22841 int i, addrCount;
22842 jobjectArray isaa;
22844 +#if defined(__solaris__)
22845 + if ((addrCount = nio_sctp_getpaddrs(fd, id, (void **)&addr_buf)) == -1) {
22846 +#else /* __linux__ */
22847 if ((addrCount = nio_sctp_getpaddrs(fd, id, (struct sockaddr **)&addr_buf)) == -1) {
22848 +#endif
22849 sctpHandleSocketError(env, errno);
22850 return NULL;
22852 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/jdk.security.auth/share/classes/com/sun/security/auth/module/Krb5LoginModule.java jdk21u-jdk-21.0.4-ga/src/jdk.security.auth/share/classes/com/sun/security/auth/module/Krb5LoginModule.java
22853 --- jdk21u-jdk-21.0.4-ga.orig/src/jdk.security.auth/share/classes/com/sun/security/auth/module/Krb5LoginModule.java 2024-07-09 10:07:16.000000000 +0200
22854 +++ jdk21u-jdk-21.0.4-ga/src/jdk.security.auth/share/classes/com/sun/security/auth/module/Krb5LoginModule.java 2024-08-17 19:13:01.438636225 +0200
22855 @@ -104,7 +104,7 @@
22856 * to false if you do not want this module to use the ticket cache.
22857 * (Default is False).
22858 * This module will search for the ticket
22859 - * cache in the following locations: On Linux
22860 + * cache in the following locations: On Solaris and Linux
22861 * it will look for the ticket cache in /tmp/krb5cc_{@code uid}
22862 * where the uid is numeric user identifier. If the ticket cache is
22863 * not available in the above location, or if we are on a
22864 diff -Nru jdk21u-jdk-21.0.4-ga.orig/src/jdk.security.auth/unix/native/libjaas/Unix.c jdk21u-jdk-21.0.4-ga/src/jdk.security.auth/unix/native/libjaas/Unix.c
22865 --- jdk21u-jdk-21.0.4-ga.orig/src/jdk.security.auth/unix/native/libjaas/Unix.c 2024-07-09 10:07:16.000000000 +0200
22866 +++ jdk21u-jdk-21.0.4-ga/src/jdk.security.auth/unix/native/libjaas/Unix.c 2024-08-17 19:13:01.439123973 +0200
22867 @@ -32,6 +32,10 @@
22868 #include <stdlib.h>
22869 #include <string.h>
22871 +/* For POSIX-compliant getpwuid_r on Solaris */
22872 +#if defined(__solaris__)
22873 +#define _POSIX_PTHREAD_SEMANTICS
22874 +#endif
22875 #include <pwd.h>