component(developer/golang-123): Add Component
[oi-userland.git] / components / runtime / openjdk-23 / patches / 1_java-solaris-sparc.patch
blob89d988320eed9bf6e6be45a7121c44ec8e99dda0
1 diff -Nru jdk23u-jdk-23-36.orig/bin/unshuffle_list.txt jdk23u-jdk-23-36/bin/unshuffle_list.txt
2 --- jdk23u-jdk-23-36.orig/bin/unshuffle_list.txt 2024-08-07 00:08:22.000000000 +0200
3 +++ jdk23u-jdk-23-36/bin/unshuffle_list.txt 2024-08-17 19:50:33.065828247 +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 jdk23u-jdk-23-36.orig/make/autoconf/basic_tools.m4 jdk23u-jdk-23-36/make/autoconf/basic_tools.m4
29 --- jdk23u-jdk-23-36.orig/make/autoconf/basic_tools.m4 2024-08-07 00:08:22.000000000 +0200
30 +++ jdk23u-jdk-23-36/make/autoconf/basic_tools.m4 2024-08-17 19:50:33.067428426 +0200
31 @@ -290,6 +290,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 jdk23u-jdk-23-36.orig/make/autoconf/build-aux/config.guess jdk23u-jdk-23-36/make/autoconf/build-aux/config.guess
41 --- jdk23u-jdk-23-36.orig/make/autoconf/build-aux/config.guess 2024-08-07 00:08:22.000000000 +0200
42 +++ jdk23u-jdk-23-36/make/autoconf/build-aux/config.guess 2024-08-17 19:50:33.067806944 +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 jdk23u-jdk-23-36.orig/make/autoconf/build-performance.m4 jdk23u-jdk-23-36/make/autoconf/build-performance.m4
59 --- jdk23u-jdk-23-36.orig/make/autoconf/build-performance.m4 2024-08-07 00:08:22.000000000 +0200
60 +++ jdk23u-jdk-23-36/make/autoconf/build-performance.m4 2024-08-17 19:50:33.068235276 +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 jdk23u-jdk-23-36.orig/make/autoconf/flags-cflags.m4 jdk23u-jdk-23-36/make/autoconf/flags-cflags.m4
81 --- jdk23u-jdk-23-36.orig/make/autoconf/flags-cflags.m4 2024-08-07 00:08:22.000000000 +0200
82 +++ jdk23u-jdk-23-36/make/autoconf/flags-cflags.m4 2024-08-17 19:50:33.068816422 +0200
83 @@ -455,6 +455,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_FILE_OFFSET_BITS=64"
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 jdk23u-jdk-23-36.orig/make/autoconf/jdk-options.m4 jdk23u-jdk-23-36/make/autoconf/jdk-options.m4
94 --- jdk23u-jdk-23-36.orig/make/autoconf/jdk-options.m4 2024-08-07 00:08:22.000000000 +0200
95 +++ jdk23u-jdk-23-36/make/autoconf/jdk-options.m4 2024-08-17 19:50:33.069333188 +0200
96 @@ -281,7 +281,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 @@ -294,7 +294,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 jdk23u-jdk-23-36.orig/make/autoconf/libraries.m4 jdk23u-jdk-23-36/make/autoconf/libraries.m4
115 --- jdk23u-jdk-23-36.orig/make/autoconf/libraries.m4 2024-08-07 00:08:22.000000000 +0200
116 +++ jdk23u-jdk-23-36/make/autoconf/libraries.m4 2024-08-17 19:50:33.069745901 +0200
117 @@ -133,13 +133,15 @@
118 BASIC_JVM_LIBS="$LIBM"
120 # Dynamic loading library
121 - if test "x$OPENJDK_TARGET_OS" = xlinux || test "x$OPENJDK_TARGET_OS" = xaix; then
122 + if test "x$OPENJDK_TARGET_OS" = xlinux || test "x$OPENJDK_TARGET_OS" = xsolaris || test "x$OPENJDK_TARGET_OS" = xaix; then
123 BASIC_JVM_LIBS="$BASIC_JVM_LIBS $LIBDL"
126 # Threading library
127 if test "x$OPENJDK_TARGET_OS" = xlinux || test "x$OPENJDK_TARGET_OS" = xaix; then
128 BASIC_JVM_LIBS="$BASIC_JVM_LIBS -lpthread"
129 + elif test "x$OPENJDK_TARGET_OS" = xsolaris; then
130 + BASIC_JVM_LIBS="$BASIC_JVM_LIBS -lthread"
133 # librt for legacy clock_gettime
134 @@ -156,6 +158,12 @@
135 BASIC_JVM_LIBS="$BASIC_JVM_LIBS -lperfstat"
138 + if test "x$OPENJDK_TARGET_OS" = xsolaris; then
139 + BASIC_JVM_LIBS="$BASIC_JVM_LIBS -lsocket -lsched -ldoor -lnsl \
140 + -lrt -lkstat"
141 + BASIC_JVM_LIBS="$BASIC_JVM_LIBS $LIBCXX_JVM"
142 + fi
144 if test "x$OPENJDK_TARGET_OS" = xwindows; then
145 BASIC_JVM_LIBS="$BASIC_JVM_LIBS kernel32.lib user32.lib gdi32.lib winspool.lib \
146 comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib powrprof.lib uuid.lib \
147 diff -Nru jdk23u-jdk-23-36.orig/make/autoconf/platform.m4 jdk23u-jdk-23-36/make/autoconf/platform.m4
148 --- jdk23u-jdk-23-36.orig/make/autoconf/platform.m4 2024-08-07 00:08:22.000000000 +0200
149 +++ jdk23u-jdk-23-36/make/autoconf/platform.m4 2024-08-17 19:50:33.070288328 +0200
150 @@ -202,6 +202,10 @@
151 VAR_OS=linux
152 VAR_OS_TYPE=unix
154 + *solaris*)
155 + VAR_OS=solaris
156 + VAR_OS_TYPE=unix
157 + ;;
158 *darwin*)
159 VAR_OS=macosx
160 VAR_OS_TYPE=unix
161 @@ -472,6 +476,17 @@
163 AC_SUBST(OPENJDK_$1_CPU_LEGACY_LIB)
165 + # OPENJDK_$1_CPU_ISADIR is normally empty. On 64-bit Solaris systems, it is set to
166 + # /amd64 or /sparcv9. This string is appended to some library paths, like this:
167 + # /usr/lib${OPENJDK_$1_CPU_ISADIR}/libexample.so
168 + OPENJDK_$1_CPU_ISADIR=""
169 + if test "x$OPENJDK_$1_OS" = xsolaris; then
170 + if test "x$OPENJDK_$1_CPU" = xx86_64; then
171 + OPENJDK_$1_CPU_ISADIR="/amd64"
172 + fi
173 + fi
174 + AC_SUBST(OPENJDK_$1_CPU_ISADIR)
176 # Setup OPENJDK_$1_CPU_OSARCH, which is used to set the os.arch Java system property
177 OPENJDK_$1_CPU_OSARCH="$OPENJDK_$1_CPU"
178 if test "x$OPENJDK_$1_OS" = xlinux && test "x$OPENJDK_$1_CPU" = xx86; then
179 @@ -603,6 +618,9 @@
181 AC_DEFUN([PLATFORM_SET_RELEASE_FILE_OS_VALUES],
183 + if test "x$OPENJDK_TARGET_OS" = "xsolaris"; then
184 + RELEASE_FILE_OS_NAME=SunOS
185 + fi
186 if test "x$OPENJDK_TARGET_OS" = "xlinux"; then
187 RELEASE_FILE_OS_NAME=Linux
189 diff -Nru jdk23u-jdk-23-36.orig/make/autoconf/toolchain.m4 jdk23u-jdk-23-36/make/autoconf/toolchain.m4
190 --- jdk23u-jdk-23-36.orig/make/autoconf/toolchain.m4 2024-08-07 00:08:22.000000000 +0200
191 +++ jdk23u-jdk-23-36/make/autoconf/toolchain.m4 2024-08-17 19:50:33.070809743 +0200
192 @@ -39,6 +39,7 @@
194 # These toolchains are valid on different platforms
195 VALID_TOOLCHAINS_linux="gcc clang"
196 +VALID_TOOLCHAINS_solaris="gcc"
197 VALID_TOOLCHAINS_macosx="clang"
198 VALID_TOOLCHAINS_aix="clang"
199 VALID_TOOLCHAINS_windows="microsoft"
200 diff -Nru jdk23u-jdk-23-36.orig/make/common/FileUtils.gmk jdk23u-jdk-23-36/make/common/FileUtils.gmk
201 --- jdk23u-jdk-23-36.orig/make/common/FileUtils.gmk 2024-08-07 00:08:22.000000000 +0200
202 +++ jdk23u-jdk-23-36/make/common/FileUtils.gmk 2024-08-17 19:50:33.071258192 +0200
203 @@ -114,7 +114,33 @@
204 ################################################################################
205 # All install-file and related macros automatically call DecodeSpace when needed.
207 -ifeq ($(call isTargetOs, macosx), true)
208 +ifeq ($(call isTargetOs, solaris), true)
209 + # On Solaris, if the target is a symlink and exists, cp won't overwrite.
210 + # Cp has to operate in recursive mode to allow for -P flag, to preserve soft links. If the
211 + # name of the target file differs from the source file, rename after copy.
212 + # If the source and target parent directories are the same, recursive copy doesn't work
213 + # so we fall back on regular copy, which isn't preserving symlinks.
214 + define install-file
215 + $(call MakeTargetDir)
216 + $(RM) '$(call DecodeSpace, $@)'
217 + if [ '$(call DecodeSpace, $(dir $(call EncodeSpace, $@)))' != \
218 + '$(call DecodeSpace, $(dir $(call EncodeSpace, $<)))' ]; then \
219 + $(CP) -f -r -P '$(call DecodeSpace, $<)' \
220 + '$(call DecodeSpace, $(dir $(call EncodeSpace, $@)))'; \
221 + if [ '$(call DecodeSpace, $(notdir $(call EncodeSpace, $@)))' != \
222 + '$(call DecodeSpace, $(notdir $(call EncodeSpace, $(<))))' ]; then \
223 + $(MV) '$(call DecodeSpace, $(dir $(call EncodeSpace, $@))/$(notdir $(call EncodeSpace, $<)))' \
224 + '$(call DecodeSpace, $@)'; \
225 + fi; \
226 + else \
227 + if [ -L '$(call DecodeSpace, $<)' ]; then \
228 + $(ECHO) "Source file is a symlink and target is in the same directory: $< $@" ; \
229 + exit 1; \
230 + fi; \
231 + $(CP) -f '$(call DecodeSpace, $<)' '$(call DecodeSpace, $@)'; \
232 + fi
233 + endef
234 +else ifeq ($(call isTargetOs, macosx), true)
235 # On mac, extended attributes sometimes creep into the source files, which may later
236 # cause the creation of ._* files which confuses testing. Clear these with xattr if
237 # set. Some files get their write permissions removed after being copied to the
238 diff -Nru jdk23u-jdk-23-36.orig/make/common/modules/LauncherCommon.gmk jdk23u-jdk-23-36/make/common/modules/LauncherCommon.gmk
239 --- jdk23u-jdk-23-36.orig/make/common/modules/LauncherCommon.gmk 2024-08-07 00:08:22.000000000 +0200
240 +++ jdk23u-jdk-23-36/make/common/modules/LauncherCommon.gmk 2024-08-17 19:50:33.071749855 +0200
241 @@ -133,17 +133,20 @@
242 -DLAUNCHER_NAME='"$$(LAUNCHER_NAME)"' \
243 -DPROGNAME='"$1"' \
244 $$($1_CFLAGS), \
245 + CFLAGS_solaris := -fPIC, \
246 CFLAGS_windows := $$($1_CFLAGS_windows), \
247 EXTRA_HEADER_DIRS := java.base:libjvm, \
248 DISABLED_WARNINGS_gcc := unused-function, \
249 LDFLAGS := $$($1_LDFLAGS), \
250 LDFLAGS_linux := $$(call SET_EXECUTABLE_ORIGIN,/../lib), \
251 LDFLAGS_macosx := $$(call SET_EXECUTABLE_ORIGIN,/../lib), \
252 + LDFLAGS_solaris := $$(call SET_EXECUTABLE_ORIGIN,/../lib), \
253 JDK_LIBS := java.base:libjli, \
254 JDK_LIBS_windows := java.base:libjava, \
255 LIBS := $$($1_LIBS), \
256 LIBS_unix := $(LIBZ_LIBS), \
257 LIBS_linux := $(LIBDL) -lpthread, \
258 + LIBS_solaris := $(LIBDL) -lthread, \
259 LIBS_macosx := \
260 -framework ApplicationServices \
261 -framework Cocoa \
262 diff -Nru jdk23u-jdk-23-36.orig/make/hotspot/gensrc/GensrcAdlc.gmk jdk23u-jdk-23-36/make/hotspot/gensrc/GensrcAdlc.gmk
263 --- jdk23u-jdk-23-36.orig/make/hotspot/gensrc/GensrcAdlc.gmk 2024-08-07 00:08:22.000000000 +0200
264 +++ jdk23u-jdk-23-36/make/hotspot/gensrc/GensrcAdlc.gmk 2024-08-17 19:50:33.072236780 +0200
265 @@ -36,6 +36,9 @@
266 # NOTE: No optimization or debug flags set here
267 ifeq ($(call isBuildOs, linux), true)
268 ADLC_CFLAGS := -fno-exceptions -DLINUX
269 + else ifeq ($(call isBuildOs, solaris), true)
270 + ADLC_LDFLAGS := -m64
271 + ADLC_CFLAGS := -m64 -fpermissive
272 else ifeq ($(call isBuildOs, aix), true)
273 ifeq ($(TOOLCHAIN_TYPE), clang)
274 ADLC_LDFLAGS += -m64
275 @@ -101,6 +104,8 @@
276 # ADLC flags depending on target OS
277 ifeq ($(call isTargetOs, linux), true)
278 ADLCFLAGS += -DLINUX=1 -D_GNU_SOURCE=1
279 + else ifeq ($(call isTargetOs, solaris), true)
280 + ADLCFLAGS += -DSOLARIS=1
281 else ifeq ($(call isTargetOs, aix), true)
282 ADLCFLAGS += -DAIX=1
283 else ifeq ($(call isTargetOs, macosx), true)
284 diff -Nru jdk23u-jdk-23-36.orig/make/hotspot/gensrc/GensrcDtrace.gmk jdk23u-jdk-23-36/make/hotspot/gensrc/GensrcDtrace.gmk
285 --- jdk23u-jdk-23-36.orig/make/hotspot/gensrc/GensrcDtrace.gmk 2024-08-07 00:08:22.000000000 +0200
286 +++ jdk23u-jdk-23-36/make/hotspot/gensrc/GensrcDtrace.gmk 2024-08-17 19:50:33.072638650 +0200
287 @@ -28,7 +28,10 @@
289 ifeq ($(call check-jvm-feature, dtrace), true)
291 - ifeq ($(call isTargetOs, macosx), true)
292 + ifeq ($(call isTargetOs, solaris), true)
293 + DTRACE_FLAGS := -64
294 + DTRACE_CPP_FLAGS := -D_LP64 -x c
295 + else ifeq ($(call isTargetOs, macosx), true)
296 DTRACE_CPP_FLAGS := -D_LP64 -x c
297 else ifeq ($(call isTargetOs, linux), true)
298 DTRACE_CPP_FLAGS := -x c
299 @@ -51,4 +54,59 @@
300 TARGETS += $(patsubst $(DTRACE_SOURCE_DIR)/%.d, \
301 $(DTRACE_GENSRC_DIR)/%.h, $(wildcard $(DTRACE_SOURCE_DIR)/*.d))
303 + ifeq ($(call isTargetOs, solaris), true)
304 + ############################################################################
305 + # First we need to generate the dtraceGenOffsets tool. When run, this will
306 + # produce two header files and a C++ file. Note that generateJvmOffsets.cpp
307 + # is using the same JVM_CFLAGS as libjvm.so.
309 + # Include support files that will setup JVM compiler flags.
310 + include lib/JvmFeatures.gmk
311 + include lib/JvmFlags.gmk
313 + # We cannot compile until the JVMTI and JFR gensrc has finished.
314 + # JFR_FILES is defined in GensrcJfr.gmk.
315 + JVMTI_H := $(JVM_VARIANT_OUTPUTDIR)/gensrc/jvmtifiles/jvmti.h
317 + $(eval $(call SetupNativeCompilation, BUILD_DTRACE_GEN_OFFSETS, \
318 + NAME := dtraceGenOffsets, \
319 + TYPE := EXECUTABLE, \
320 + SRC := $(TOPDIR)/make/hotspot/src/native/dtrace, \
321 + TOOLCHAIN := $(TOOLCHAIN_BUILD), \
322 + LDFLAGS := -m64, \
323 + CFLAGS := -m64 $(JVM_CFLAGS), \
324 + EXTRA_DEPS := $(JVMTI_H) $(JFR_FILES), \
325 + OBJECT_DIR := $(JVM_VARIANT_OUTPUTDIR)/tools/dtrace-gen-offsets/objs, \
326 + OUTPUT_DIR := $(JVM_VARIANT_OUTPUTDIR)/tools/dtrace-gen-offsets, \
327 + ))
329 + DTRACE_GEN_OFFSETS_TOOL := $(BUILD_DTRACE_GEN_OFFSETS_TARGET)
331 + # Argument 1: Output filename
332 + # Argument 2: dtrace-gen-offset tool command line option
333 + define SetupDtraceOffsetsGeneration
334 + $$(eval $$(call SetupExecute, dtrace_offset_$$(strip $2), \
335 + INFO := Generating dtrace $2 file, \
336 + DEPS := $$(BUILD_DTRACE_GEN_OFFSETS), \
337 + OUTPUT_FILE := $1, \
338 + COMMAND := ( $$(DTRACE_GEN_OFFSETS_TOOL) -$$(strip $2) > $1 ), \
339 + ))
341 + TARGETS += $$(dtrace_offset_$$(strip $2)_TARGET)
342 + endef
344 + JVM_OFFSETS_H := $(DTRACE_GENSRC_DIR)/JvmOffsets.h
345 + JVM_OFFSETS_CPP := $(DTRACE_GENSRC_DIR)/JvmOffsets.cpp
346 + JVM_OFFSETS_INDEX_H := $(DTRACE_GENSRC_DIR)/JvmOffsetsIndex.h
348 + ############################################################################
349 + # Run the dtrace-gen-offset tool to generate these three files.
350 + # The generated JvmOffsets.cpp is compiled with the rest of libjvm.
351 + # The header files are used by libjvm_db and jhelper.d, respectively.
353 + $(eval $(call SetupDtraceOffsetsGeneration, $(JVM_OFFSETS_H), header))
354 + $(eval $(call SetupDtraceOffsetsGeneration, $(JVM_OFFSETS_INDEX_H), index))
355 + $(eval $(call SetupDtraceOffsetsGeneration, $(JVM_OFFSETS_CPP), table))
356 + endif
358 endif
359 diff -Nru jdk23u-jdk-23-36.orig/make/hotspot/lib/CompileDtraceLibraries.gmk jdk23u-jdk-23-36/make/hotspot/lib/CompileDtraceLibraries.gmk
360 --- jdk23u-jdk-23-36.orig/make/hotspot/lib/CompileDtraceLibraries.gmk 1970-01-01 01:00:00.000000000 +0100
361 +++ jdk23u-jdk-23-36/make/hotspot/lib/CompileDtraceLibraries.gmk 2024-08-17 19:50:33.138898340 +0200
362 @@ -0,0 +1,62 @@
364 +# Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
365 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
367 +# This code is free software; you can redistribute it and/or modify it
368 +# under the terms of the GNU General Public License version 2 only, as
369 +# published by the Free Software Foundation. Oracle designates this
370 +# particular file as subject to the "Classpath" exception as provided
371 +# by Oracle in the LICENSE file that accompanied this code.
373 +# This code is distributed in the hope that it will be useful, but WITHOUT
374 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
375 +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
376 +# version 2 for more details (a copy is included in the LICENSE file that
377 +# accompanied this code).
379 +# You should have received a copy of the GNU General Public License version
380 +# 2 along with this work; if not, write to the Free Software Foundation,
381 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
383 +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
384 +# or visit www.oracle.com if you need additional information or have any
385 +# questions.
388 +ifeq ($(call check-jvm-feature, dtrace), true)
389 + ifeq ($(call isTargetOs, solaris), true)
390 + JNI_INCLUDE_FLAGS := \
391 + -I$(SUPPORT_OUTPUTDIR)/modules_include/java.base \
392 + -I$(SUPPORT_OUTPUTDIR)/modules_include/java.base/$(OPENJDK_TARGET_OS_INCLUDE_SUBDIR) \
395 + ############################################################################
396 + # Build the stand-alone dtrace libraries.
398 + LIBJVM_DTRACE_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/libjvm_dtrace
399 + $(eval $(call SetupNativeCompilation, BUILD_LIBJVM_DTRACE, \
400 + NAME := jvm_dtrace, \
401 + OUTPUT_DIR := $(JVM_LIB_OUTPUTDIR), \
402 + SRC := $(TOPDIR)/src/java.base/solaris/native/libjvm_dtrace, \
403 + CFLAGS := $(JNI_INCLUDE_FLAGS) -m64 -G -mt -KPIC -xldscope=hidden, \
404 + LDFLAGS := -m64 -mt -xnolib $(SHARED_LIBRARY_FLAGS), \
405 + LIBS := $(LIBDL) -lthread -ldoor, \
406 + OBJECT_DIR := $(LIBJVM_DTRACE_OUTPUTDIR)/objs, \
407 + ))
409 + # Note that libjvm_db.c has tests for COMPILER2, but this was never set by
410 + # the old build.
411 + LIBJVM_DB_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/libjvm_db
412 + $(eval $(call SetupNativeCompilation, BUILD_LIBJVM_DB, \
413 + NAME := jvm_db, \
414 + OUTPUT_DIR := $(JVM_LIB_OUTPUTDIR), \
415 + SRC := $(TOPDIR)/src/java.base/solaris/native/libjvm_db, \
416 + CFLAGS := -I$(DTRACE_GENSRC_DIR) $(JNI_INCLUDE_FLAGS) -m64 -G -mt -KPIC -xldscope=hidden, \
417 + LDFLAGS := -m64 -mt -xnolib $(SHARED_LIBRARY_FLAGS), \
418 + OBJECT_DIR := $(LIBJVM_DB_OUTPUTDIR)/objs, \
419 + ))
421 + TARGETS += $(BUILD_LIBJVM_DTRACE) $(BUILD_LIBJVM_DB)
423 + endif
424 +endif
425 diff -Nru jdk23u-jdk-23-36.orig/make/hotspot/lib/CompileJvm.gmk jdk23u-jdk-23-36/make/hotspot/lib/CompileJvm.gmk
426 --- jdk23u-jdk-23-36.orig/make/hotspot/lib/CompileJvm.gmk 2024-08-07 00:08:22.000000000 +0200
427 +++ jdk23u-jdk-23-36/make/hotspot/lib/CompileJvm.gmk 2024-08-17 19:50:33.073111422 +0200
428 @@ -31,6 +31,9 @@
429 include lib/JvmOverrideFiles.gmk
430 include lib/JvmFlags.gmk
432 +# Include support files that will setup DTRACE_EXTRA_OBJECT_FILES.
433 +include lib/JvmDtraceObjects.gmk
435 ################################################################################
436 # Setup compilation of the main Hotspot native library (libjvm).
438 @@ -171,6 +174,7 @@
439 EXCLUDES := $(JVM_EXCLUDES), \
440 EXCLUDE_FILES := $(JVM_EXCLUDE_FILES), \
441 EXCLUDE_PATTERNS := $(JVM_EXCLUDE_PATTERNS), \
442 + EXTRA_OBJECT_FILES := $(DTRACE_EXTRA_OBJECT_FILES), \
443 DEFAULT_CFLAGS := false, \
444 CFLAGS := $(JVM_CFLAGS), \
445 abstract_vm_version.cpp_CXXFLAGS := $(CFLAGS_VM_VERSION), \
446 diff -Nru jdk23u-jdk-23-36.orig/make/hotspot/lib/CompileLibraries.gmk jdk23u-jdk-23-36/make/hotspot/lib/CompileLibraries.gmk
447 --- jdk23u-jdk-23-36.orig/make/hotspot/lib/CompileLibraries.gmk 2024-08-07 00:08:22.000000000 +0200
448 +++ jdk23u-jdk-23-36/make/hotspot/lib/CompileLibraries.gmk 2024-08-17 19:50:33.073434154 +0200
449 @@ -32,6 +32,7 @@
450 include HotspotCommon.gmk
452 include lib/CompileJvm.gmk
453 +include lib/CompileDtraceLibraries.gmk
455 ifneq ($(GTEST_FRAMEWORK_SRC), )
456 ifneq ($(CREATING_BUILDJDK), true)
457 diff -Nru jdk23u-jdk-23-36.orig/make/hotspot/lib/JvmDtraceObjects.gmk jdk23u-jdk-23-36/make/hotspot/lib/JvmDtraceObjects.gmk
458 --- jdk23u-jdk-23-36.orig/make/hotspot/lib/JvmDtraceObjects.gmk 1970-01-01 01:00:00.000000000 +0100
459 +++ jdk23u-jdk-23-36/make/hotspot/lib/JvmDtraceObjects.gmk 2024-08-17 19:50:33.139178264 +0200
460 @@ -0,0 +1,122 @@
462 +# Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
463 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
465 +# This code is free software; you can redistribute it and/or modify it
466 +# under the terms of the GNU General Public License version 2 only, as
467 +# published by the Free Software Foundation. Oracle designates this
468 +# particular file as subject to the "Classpath" exception as provided
469 +# by Oracle in the LICENSE file that accompanied this code.
471 +# This code is distributed in the hope that it will be useful, but WITHOUT
472 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
473 +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
474 +# version 2 for more details (a copy is included in the LICENSE file that
475 +# accompanied this code).
477 +# You should have received a copy of the GNU General Public License version
478 +# 2 along with this work; if not, write to the Free Software Foundation,
479 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
481 +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
482 +# or visit www.oracle.com if you need additional information or have any
483 +# questions.
486 +ifeq ($(call check-jvm-feature, dtrace), true)
487 + ifeq ($(call isTargetOs, solaris), true)
489 + ############################################################################
490 + # Integrate with libjvm. Here we generate two object files which are
491 + # linked with libjvm.so. This step is complicated from a dependency
492 + # perspective. We add these two files to the linking of libjvm using
493 + # EXTRA_OBJECT_FILES, but they need to be created outside the call to
494 + # SetupNativeCompilation. Also, one of the files is dependent on compiled
495 + # object files from the libjvm compilation, so this generation must happen
496 + # as a part of the libjvm compilation.
498 + DTRACE_OBJ := $(JVM_OUTPUTDIR)/objs/dtrace.o
499 + DTRACE_JHELPER_OBJ := $(JVM_OUTPUTDIR)/objs/dtrace_jhelper.o
501 + DTRACE_EXTRA_OBJECT_FILES := $(DTRACE_OBJ) $(DTRACE_JHELPER_OBJ)
503 + ############################################################################
504 + # Generate DTRACE_OBJ which is linked with libjvm.so. It depends on a set of
505 + # object files from the compilation.
507 + # Concatenate all *.d files into a single file
508 + DTRACE_SOURCE_FILES := $(addprefix $(TOPDIR)/src/hotspot/os/posix/dtrace/, \
509 + hotspot_jni.d \
510 + hotspot.d \
511 + hs_private.d \
514 + # *.d in the objs dir is used for generated make dependency files, so use
515 + # *.dt for dtrace files to avoid clashes.
516 + $(JVM_OUTPUTDIR)/objs/dtrace.dt: $(DTRACE_SOURCE_FILES)
517 + $(call LogInfo, Generating $(@F))
518 + $(call MakeDir, $(@D))
519 + $(CAT) $^ > $@
521 + DTRACE_INSTRUMENTED_OBJS := $(addprefix $(JVM_OUTPUTDIR)/objs/, \
522 + ciEnv.o \
523 + classLoadingService.o \
524 + compileBroker.o \
525 + gcVMOperations.o \
526 + hashtable.o \
527 + instanceKlass.o \
528 + java.o \
529 + jni.o \
530 + jvm.o \
531 + memoryManager.o \
532 + nmethod.o \
533 + objectMonitor.o \
534 + runtimeService.o \
535 + sharedRuntime.o \
536 + synchronizer.o \
537 + thread.o \
538 + unsafe.o \
539 + vmThread.o \
542 + ifeq ($(call check-jvm-feature, parallelgc), true)
543 + DTRACE_INSTRUMENTED_OBJS += $(addprefix $(JVM_OUTPUTDIR)/objs/, \
544 + psVMOperations.o \
546 + endif
548 + DTRACE_FLAGS := -64 -G
549 + DTRACE_CPP_FLAGS := -D_LP64
551 + # Make sure we run our selected compiler for preprocessing instead of letting
552 + # the dtrace tool pick it on it's own.
553 + $(DTRACE_OBJ): $(JVM_OUTPUTDIR)/objs/dtrace.dt $(DTRACE_INSTRUMENTED_OBJS)
554 + $(call LogInfo, Generating $(@F) from $(<F) and object files)
555 + $(call MakeDir, $(DTRACE_SUPPORT_DIR))
556 + $(call ExecuteWithLog, $(DTRACE_SUPPORT_DIR)/$(@F).dt, \
557 + ($(CPP) $(DTRACE_CPP_FLAGS) $< > $(DTRACE_SUPPORT_DIR)/$(@F).dt))
558 + $(call ExecuteWithLog, $@, $(DTRACE) $(DTRACE_FLAGS) -xlazyload -o $@ \
559 + -s $(DTRACE_SUPPORT_DIR)/$(@F).dt $(sort $(DTRACE_INSTRUMENTED_OBJS)))
561 + ############################################################################
562 + # Generate DTRACE_JHELPER_OBJ which is linked with libjvm.so.
564 + JHELPER_DTRACE_SRC := $(TOPDIR)/src/hotspot/os/solaris/dtrace/jhelper.d
566 + # jhelper.d includes JvmOffsetsIndex.h which was created by the gensrc step.
567 + DTRACE_GENSRC_DIR := $(JVM_VARIANT_OUTPUTDIR)/gensrc/dtracefiles
568 + JVM_OFFSETS_INDEX_H := $(DTRACE_GENSRC_DIR)/JvmOffsetsIndex.h
570 + # Make sure we run our selected compiler for preprocessing instead of letting
571 + # the dtrace tool pick it on it's own.
572 + $(DTRACE_JHELPER_OBJ): $(JHELPER_DTRACE_SRC) $(JVM_OFFSETS_INDEX_H)
573 + $(call LogInfo, Running dtrace for $(<F))
574 + $(call MakeDir, $(DTRACE_SUPPORT_DIR))
575 + $(call ExecuteWithLog, $(DTRACE_SUPPORT_DIR)/$(@F).dt, \
576 + ($(CPP) $(DTRACE_CPP_FLAGS) -I$(DTRACE_GENSRC_DIR) $^ \
577 + > $(DTRACE_SUPPORT_DIR)/$(@F).dt))
578 + $(call ExecuteWithLog, $@, $(DTRACE) $(DTRACE_FLAGS) -o $@ \
579 + -s $(DTRACE_SUPPORT_DIR)/$(@F).dt)
581 + endif
582 +endif
583 diff -Nru jdk23u-jdk-23-36.orig/make/hotspot/src/native/dtrace/generateJvmOffsets.cpp jdk23u-jdk-23-36/make/hotspot/src/native/dtrace/generateJvmOffsets.cpp
584 --- jdk23u-jdk-23-36.orig/make/hotspot/src/native/dtrace/generateJvmOffsets.cpp 1970-01-01 01:00:00.000000000 +0100
585 +++ jdk23u-jdk-23-36/make/hotspot/src/native/dtrace/generateJvmOffsets.cpp 2024-08-17 19:50:33.139649857 +0200
586 @@ -0,0 +1,316 @@
588 + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
589 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
591 + * This code is free software; you can redistribute it and/or modify it
592 + * under the terms of the GNU General Public License version 2 only, as
593 + * published by the Free Software Foundation.
595 + * This code is distributed in the hope that it will be useful, but WITHOUT
596 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
597 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
598 + * version 2 for more details (a copy is included in the LICENSE file that
599 + * accompanied this code).
601 + * You should have received a copy of the GNU General Public License version
602 + * 2 along with this work; if not, write to the Free Software Foundation,
603 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
605 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
606 + * or visit www.oracle.com if you need additional information or have any
607 + * questions.
609 + */
612 + * This is to provide sanity check in jhelper.d which compares SCCS
613 + * versions of generateJvmOffsets.cpp used to create and extract
614 + * contents of __JvmOffsets[] table.
615 + * The __JvmOffsets[] table is located in generated JvmOffsets.cpp.
617 + * GENOFFS_SCCS_VER 34
618 + */
620 +#include <stdio.h>
621 +#include <strings.h>
623 +/* A workaround for private and protected fields */
624 +#define private public
625 +#define protected public
627 +#include <proc_service.h>
628 +#include "gc/shared/collectedHeap.hpp"
629 +#include "memory/heap.hpp"
630 +#include "oops/compressedOops.hpp"
631 +#include "runtime/vmStructs.hpp"
633 +typedef enum GEN_variant {
634 + GEN_OFFSET = 0,
635 + GEN_INDEX = 1,
636 + GEN_TABLE = 2
637 +} GEN_variant;
639 +#ifdef COMPILER1
640 +#ifdef ASSERT
643 + * To avoid the most part of potential link errors
644 + * we link this program with -z nodefs .
646 + * But for 'debug1' and 'fastdebug1' we still have to provide
647 + * a particular workaround for the following symbols below.
648 + * It will be good to find out a generic way in the future.
649 + */
651 +#pragma weak tty
653 +#if defined(i386) || defined(__i386) || defined(__amd64)
654 +#pragma weak noreg
655 +#endif /* i386 */
657 +LIR_Opr LIR_OprFact::illegalOpr = (LIR_Opr) 0;
659 +address StubRoutines::_call_stub_return_address = NULL;
661 +StubQueue* AbstractInterpreter::_code = NULL;
663 +#endif /* ASSERT */
664 +#endif /* COMPILER1 */
666 +#define GEN_OFFS_NAME(Type,Name,OutputType) \
667 + switch(gen_variant) { \
668 + case GEN_OFFSET: \
669 + printf("#define OFFSET_%-33s %ld\n", \
670 + #OutputType #Name, offset_of(Type, Name)); \
671 + break; \
672 + case GEN_INDEX: \
673 + printf("#define IDX_OFFSET_%-33s %d\n", \
674 + #OutputType #Name, index++); \
675 + break; \
676 + case GEN_TABLE: \
677 + printf("\tOFFSET_%s,\n", #OutputType #Name); \
678 + break; \
681 +#define GEN_OFFS(Type,Name) \
682 + GEN_OFFS_NAME(Type,Name,Type)
684 +#define GEN_SIZE(Type) \
685 + switch(gen_variant) { \
686 + case GEN_OFFSET: \
687 + printf("#define SIZE_%-35s %ld\n", \
688 + #Type, sizeof(Type)); \
689 + break; \
690 + case GEN_INDEX: \
691 + printf("#define IDX_SIZE_%-35s %d\n", \
692 + #Type, index++); \
693 + break; \
694 + case GEN_TABLE: \
695 + printf("\tSIZE_%s,\n", #Type); \
696 + break; \
699 +#define GEN_VALUE(String,Value) \
700 + switch(gen_variant) { \
701 + case GEN_OFFSET: \
702 + printf("#define %-40s %d\n", #String, Value); \
703 + break; \
704 + case GEN_INDEX: \
705 + printf("#define IDX_%-40s %d\n", #String, index++); \
706 + break; \
707 + case GEN_TABLE: \
708 + printf("\t" #String ",\n"); \
709 + break; \
712 +void gen_prologue(GEN_variant gen_variant) {
713 + const char *suffix = "Undefined-Suffix";
715 + switch(gen_variant) {
716 + case GEN_OFFSET: suffix = ".h"; break;
717 + case GEN_INDEX: suffix = "Index.h"; break;
718 + case GEN_TABLE: suffix = ".cpp"; break;
721 + printf("/*\n");
722 + printf(" * JvmOffsets%s !!!DO NOT EDIT!!! \n", suffix);
723 + printf(" * The generateJvmOffsets program generates this file!\n");
724 + printf(" */\n\n");
725 + switch(gen_variant) {
727 + case GEN_OFFSET:
728 + case GEN_INDEX:
729 + break;
731 + case GEN_TABLE:
732 + printf("#include \"JvmOffsets.h\"\n");
733 + printf("\n");
734 + printf("int __JvmOffsets[] = {\n");
735 + break;
739 +void gen_epilogue(GEN_variant gen_variant) {
740 + if (gen_variant != GEN_TABLE) {
741 + return;
743 + printf("};\n\n");
744 + return;
747 +int generateJvmOffsets(GEN_variant gen_variant) {
748 + int index = 0; /* It is used to generate JvmOffsetsIndex.h */
749 + int pointer_size = sizeof(void *);
750 + int data_model = (pointer_size == 4) ? PR_MODEL_ILP32 : PR_MODEL_LP64;
752 + gen_prologue(gen_variant);
754 + GEN_VALUE(DATA_MODEL, data_model);
755 + GEN_VALUE(POINTER_SIZE, pointer_size);
756 +#if COMPILER1_AND_COMPILER2
757 + GEN_VALUE(COMPILER, 3);
758 +#elif COMPILER1
759 + GEN_VALUE(COMPILER, 1);
760 +#elif COMPILER2
761 + GEN_VALUE(COMPILER, 2);
762 +#else
763 + GEN_VALUE(COMPILER, 0);
764 +#endif // COMPILER1 && COMPILER2
765 + printf("\n");
767 + GEN_OFFS(CollectedHeap, _reserved);
768 + GEN_OFFS(MemRegion, _start);
769 + GEN_OFFS(MemRegion, _word_size);
770 + GEN_SIZE(HeapWord);
771 + printf("\n");
773 + GEN_OFFS(VMStructEntry, typeName);
774 + GEN_OFFS(VMStructEntry, fieldName);
775 + GEN_OFFS(VMStructEntry, address);
776 + GEN_SIZE(VMStructEntry);
777 + printf("\n");
779 + GEN_VALUE(MAX_METHOD_CODE_SIZE, max_method_code_size);
780 +#if defined(i386) || defined(__i386) || defined(__amd64)
781 + GEN_VALUE(OFFSET_interpreter_frame_sender_sp, -1 * pointer_size);
782 + GEN_VALUE(OFFSET_interpreter_frame_method, -3 * pointer_size);
783 + GEN_VALUE(OFFSET_interpreter_frame_bcp_offset, -7 * pointer_size);
784 +#endif
786 + GEN_OFFS(Klass, _name);
787 + GEN_OFFS(ConstantPool, _pool_holder);
788 + printf("\n");
790 + GEN_VALUE(OFFSET_HeapBlockHeader_used, (int) offset_of(HeapBlock::Header, _used));
791 + GEN_OFFS(oopDesc, _metadata);
792 + printf("\n");
794 + GEN_VALUE(AccessFlags_NATIVE, JVM_ACC_NATIVE);
795 + GEN_VALUE(ConstMethod_has_linenumber_table, ConstMethod::_has_linenumber_table);
796 + GEN_OFFS(AccessFlags, _flags);
797 + GEN_OFFS(Symbol, _length);
798 + GEN_OFFS(Symbol, _body);
799 + printf("\n");
801 + GEN_OFFS(Method, _constMethod);
802 + GEN_OFFS(Method, _access_flags);
803 + printf("\n");
805 + GEN_OFFS(ConstMethod, _constants);
806 + GEN_OFFS(ConstMethod, _flags);
807 + GEN_OFFS(ConstMethod, _code_size);
808 + GEN_OFFS(ConstMethod, _name_index);
809 + GEN_OFFS(ConstMethod, _signature_index);
810 + printf("\n");
812 + GEN_OFFS(CodeHeap, _memory);
813 + GEN_OFFS(CodeHeap, _segmap);
814 + GEN_OFFS(CodeHeap, _log2_segment_size);
815 + printf("\n");
817 + GEN_OFFS(VirtualSpace, _low_boundary);
818 + GEN_OFFS(VirtualSpace, _high_boundary);
819 + GEN_OFFS(VirtualSpace, _low);
820 + GEN_OFFS(VirtualSpace, _high);
821 + printf("\n");
823 + /* We need to use different names here because of the template parameter */
824 + GEN_OFFS_NAME(GrowableArray<CodeHeap*>, _data, GrowableArray_CodeHeap);
825 + GEN_OFFS_NAME(GrowableArray<CodeHeap*>, _len, GrowableArray_CodeHeap);
826 + printf("\n");
828 + GEN_OFFS(CodeBlob, _name);
829 + GEN_OFFS(CodeBlob, _header_size);
830 + GEN_OFFS(CodeBlob, _content_begin);
831 + GEN_OFFS(CodeBlob, _code_begin);
832 + GEN_OFFS(CodeBlob, _code_end);
833 + GEN_OFFS(CodeBlob, _data_offset);
834 + GEN_OFFS(CodeBlob, _frame_size);
835 + printf("\n");
837 + GEN_OFFS(nmethod, _method);
838 + GEN_OFFS(nmethod, _dependencies_offset);
839 + GEN_OFFS(nmethod, _metadata_offset);
840 + GEN_OFFS(nmethod, _scopes_data_begin);
841 + GEN_OFFS(nmethod, _scopes_pcs_offset);
842 + GEN_OFFS(nmethod, _handler_table_offset);
843 + GEN_OFFS(nmethod, _deopt_handler_begin);
844 + GEN_OFFS(nmethod, _orig_pc_offset);
846 + GEN_OFFS(PcDesc, _pc_offset);
847 + GEN_OFFS(PcDesc, _scope_decode_offset);
849 + printf("\n");
851 + GEN_OFFS(NarrowPtrStruct, _base);
852 + GEN_OFFS(NarrowPtrStruct, _shift);
853 + printf("\n");
855 + GEN_VALUE(SIZE_HeapBlockHeader, (int) sizeof(HeapBlock::Header));
856 + GEN_SIZE(oopDesc);
857 + GEN_SIZE(ConstantPool);
858 + printf("\n");
860 + GEN_SIZE(PcDesc);
861 + GEN_SIZE(Method);
862 + GEN_SIZE(ConstMethod);
863 + GEN_SIZE(nmethod);
864 + GEN_SIZE(CodeBlob);
865 + GEN_SIZE(BufferBlob);
866 + GEN_SIZE(SingletonBlob);
867 + GEN_SIZE(RuntimeStub);
868 + GEN_SIZE(SafepointBlob);
870 + gen_epilogue(gen_variant);
871 + printf("\n");
873 + fflush(stdout);
874 + return 0;
877 +const char *HELP =
878 + "HELP: generateJvmOffsets {-header | -index | -table} \n";
880 +int main(int argc, const char *argv[]) {
881 + GEN_variant gen_var;
883 + if (argc != 2) {
884 + printf("%s", HELP);
885 + return 1;
888 + if (0 == strcmp(argv[1], "-header")) {
889 + gen_var = GEN_OFFSET;
891 + else if (0 == strcmp(argv[1], "-index")) {
892 + gen_var = GEN_INDEX;
894 + else if (0 == strcmp(argv[1], "-table")) {
895 + gen_var = GEN_TABLE;
897 + else {
898 + printf("%s", HELP);
899 + return 1;
901 + return generateJvmOffsets(gen_var);
903 diff -Nru jdk23u-jdk-23-36.orig/make/hotspot/symbols/symbols-solaris jdk23u-jdk-23-36/make/hotspot/symbols/symbols-solaris
904 --- jdk23u-jdk-23-36.orig/make/hotspot/symbols/symbols-solaris 1970-01-01 01:00:00.000000000 +0100
905 +++ jdk23u-jdk-23-36/make/hotspot/symbols/symbols-solaris 2024-08-17 19:50:33.139947718 +0200
906 @@ -0,0 +1,25 @@
908 +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
909 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
911 +# This code is free software; you can redistribute it and/or modify it
912 +# under the terms of the GNU General Public License version 2 only, as
913 +# published by the Free Software Foundation.
915 +# This code is distributed in the hope that it will be useful, but WITHOUT
916 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
917 +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
918 +# version 2 for more details (a copy is included in the LICENSE file that
919 +# accompanied this code).
921 +# You should have received a copy of the GNU General Public License version
922 +# 2 along with this work; if not, write to the Free Software Foundation,
923 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
925 +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
926 +# or visit www.oracle.com if you need additional information or have any
927 +# questions.
930 +JVM_handle_solaris_signal
931 +sysThreadAvailableStackWithSlack
932 diff -Nru jdk23u-jdk-23-36.orig/make/hotspot/symbols/symbols-solaris-dtrace-compiler1 jdk23u-jdk-23-36/make/hotspot/symbols/symbols-solaris-dtrace-compiler1
933 --- jdk23u-jdk-23-36.orig/make/hotspot/symbols/symbols-solaris-dtrace-compiler1 1970-01-01 01:00:00.000000000 +0100
934 +++ jdk23u-jdk-23-36/make/hotspot/symbols/symbols-solaris-dtrace-compiler1 2024-08-17 19:50:33.140179700 +0200
935 @@ -0,0 +1,34 @@
937 +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
938 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
940 +# This code is free software; you can redistribute it and/or modify it
941 +# under the terms of the GNU General Public License version 2 only, as
942 +# published by the Free Software Foundation.
944 +# This code is distributed in the hope that it will be useful, but WITHOUT
945 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
946 +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
947 +# version 2 for more details (a copy is included in the LICENSE file that
948 +# accompanied this code).
950 +# You should have received a copy of the GNU General Public License version
951 +# 2 along with this work; if not, write to the Free Software Foundation,
952 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
954 +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
955 +# or visit www.oracle.com if you need additional information or have any
956 +# questions.
959 +__1cGMethodG__vtbl_
960 +__1cHnmethodG__vtbl_
961 +__1cICodeBlobG__vtbl_
962 +__1cIUniverseO_collectedHeap_
963 +__1cJCodeCacheG_heaps_
964 +__1cKBufferBlobG__vtbl_
965 +__1cLRuntimeStubG__vtbl_
966 +__1cNSafepointBlobG__vtbl_
967 +__1cSDeoptimizationBlobG__vtbl_
969 +__JvmOffsets
970 diff -Nru jdk23u-jdk-23-36.orig/make/hotspot/symbols/symbols-solaris-dtrace-compiler2 jdk23u-jdk-23-36/make/hotspot/symbols/symbols-solaris-dtrace-compiler2
971 --- jdk23u-jdk-23-36.orig/make/hotspot/symbols/symbols-solaris-dtrace-compiler2 1970-01-01 01:00:00.000000000 +0100
972 +++ jdk23u-jdk-23-36/make/hotspot/symbols/symbols-solaris-dtrace-compiler2 2024-08-17 19:50:33.140407686 +0200
973 @@ -0,0 +1,36 @@
975 +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
976 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
978 +# This code is free software; you can redistribute it and/or modify it
979 +# under the terms of the GNU General Public License version 2 only, as
980 +# published by the Free Software Foundation.
982 +# This code is distributed in the hope that it will be useful, but WITHOUT
983 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
984 +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
985 +# version 2 for more details (a copy is included in the LICENSE file that
986 +# accompanied this code).
988 +# You should have received a copy of the GNU General Public License version
989 +# 2 along with this work; if not, write to the Free Software Foundation,
990 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
992 +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
993 +# or visit www.oracle.com if you need additional information or have any
994 +# questions.
997 +__1cGMethodG__vtbl_
998 +__1cHnmethodG__vtbl_
999 +__1cICodeBlobG__vtbl_
1000 +__1cIUniverseO_collectedHeap_
1001 +__1cJCodeCacheG_heaps_
1002 +__1cKBufferBlobG__vtbl_
1003 +__1cLRuntimeStubG__vtbl_
1004 +__1cNSafepointBlobG__vtbl_
1005 +__1cSDeoptimizationBlobG__vtbl_
1006 +__1cNExceptionBlobG__vtbl_
1007 +__1cQUncommonTrapBlobG__vtbl_
1009 +__JvmOffsets
1010 diff -Nru jdk23u-jdk-23-36.orig/make/ide/visualstudio/hotspot/CreateVSProject.gmk jdk23u-jdk-23-36/make/ide/visualstudio/hotspot/CreateVSProject.gmk
1011 --- jdk23u-jdk-23-36.orig/make/ide/visualstudio/hotspot/CreateVSProject.gmk 2024-08-07 00:08:22.000000000 +0200
1012 +++ jdk23u-jdk-23-36/make/ide/visualstudio/hotspot/CreateVSProject.gmk 2024-08-17 19:50:33.073911689 +0200
1013 @@ -76,6 +76,7 @@
1014 -ignorePath linux \
1015 -ignorePath posix \
1016 -ignorePath ppc \
1017 + -ignorePath solaris \
1018 -ignorePath x86_32 \
1019 -ignorePath zero \
1021 diff -Nru jdk23u-jdk-23-36.orig/make/modules/java.base/Copy.gmk jdk23u-jdk-23-36/make/modules/java.base/Copy.gmk
1022 --- jdk23u-jdk-23-36.orig/make/modules/java.base/Copy.gmk 2024-08-07 00:08:22.000000000 +0200
1023 +++ jdk23u-jdk-23-36/make/modules/java.base/Copy.gmk 2024-08-17 19:50:33.074387163 +0200
1024 @@ -190,7 +190,7 @@
1026 TARGETS += $(NET_PROPERTIES_DST)
1028 -ifeq ($(call isTargetOs, linux), true)
1029 +ifeq ($(call isTargetOs, solaris linux), true)
1030 $(eval $(call SetupCopyFiles, COPY_SDP_CONF, \
1031 FILES := $(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/conf/sdp/sdp.conf.template, \
1032 DEST := $(CONF_DST_DIR)/sdp, \
1033 diff -Nru jdk23u-jdk-23-36.orig/make/modules/java.base/gensrc/GensrcMisc.gmk jdk23u-jdk-23-36/make/modules/java.base/gensrc/GensrcMisc.gmk
1034 --- jdk23u-jdk-23-36.orig/make/modules/java.base/gensrc/GensrcMisc.gmk 2024-08-07 00:08:22.000000000 +0200
1035 +++ jdk23u-jdk-23-36/make/modules/java.base/gensrc/GensrcMisc.gmk 2024-08-17 19:50:33.075253447 +0200
1036 @@ -136,6 +136,21 @@
1038 endif
1040 +################################################################################
1042 +ifeq ($(call isTargetOs, solaris), true)
1044 + GENSRC_SC_FILE := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/fs/SolarisConstants.java
1046 + $(GENSRC_SC_FILE): \
1047 + $(TOPDIR)/src/java.base/solaris/classes/sun/nio/fs/SolarisConstants.java.template
1048 + $(generate-preproc-src)
1050 + TARGETS += $(GENSRC_SC_FILE)
1052 +endif
1054 +################################################################################
1055 # Create the javax/crypto/JceSecurity.class, using the build default.
1057 ifeq ($(UNLIMITED_CRYPTO), true)
1058 diff -Nru jdk23u-jdk-23-36.orig/make/modules/java.base/lib/CoreLibraries.gmk jdk23u-jdk-23-36/make/modules/java.base/lib/CoreLibraries.gmk
1059 --- jdk23u-jdk-23-36.orig/make/modules/java.base/lib/CoreLibraries.gmk 2024-08-07 00:08:22.000000000 +0200
1060 +++ jdk23u-jdk-23-36/make/modules/java.base/lib/CoreLibraries.gmk 2024-08-17 19:50:33.075792899 +0200
1061 @@ -28,7 +28,7 @@
1062 ################################################################################
1064 LIBVERIFY_OPTIMIZATION := HIGH
1065 -ifeq ($(call isTargetOs, linux)+$(COMPILE_WITH_DEBUG_SYMBOLS), true+true)
1066 +ifeq ($(call isTargetOs, solaris linux)+$(COMPILE_WITH_DEBUG_SYMBOLS), true+true)
1067 LIBVERIFY_OPTIMIZATION := LOW
1068 endif
1070 @@ -60,6 +60,7 @@
1071 DISABLED_WARNINGS_gcc_ProcessImpl_md.c := unused-result, \
1072 JDK_LIBS := libjvm, \
1073 LIBS_linux := $(LIBDL), \
1074 + LIBS_solaris := -lsocket -lnsl -lscf $(LIBDL), \
1075 LIBS_aix := $(LIBDL) $(LIBM),\
1076 LIBS_macosx := \
1077 -framework CoreFoundation \
1078 @@ -171,6 +172,7 @@
1079 DISABLED_WARNINGS_clang := format-nonliteral deprecated-non-prototype, \
1080 LIBS_unix := $(LIBZ_LIBS), \
1081 LIBS_linux := $(LIBDL) -lpthread, \
1082 + LIBS_solaris := $(LIBDL), \
1083 LIBS_macosx := \
1084 -framework ApplicationServices \
1085 -framework Cocoa \
1086 diff -Nru jdk23u-jdk-23-36.orig/make/modules/java.base/Lib.gmk jdk23u-jdk-23-36/make/modules/java.base/Lib.gmk
1087 --- jdk23u-jdk-23-36.orig/make/modules/java.base/Lib.gmk 2024-08-07 00:08:22.000000000 +0200
1088 +++ jdk23u-jdk-23-36/make/modules/java.base/Lib.gmk 2024-08-17 19:50:33.074833359 +0200
1089 @@ -56,6 +56,7 @@
1090 -delayload:winhttp.dll, \
1091 JDK_LIBS := libjava libjvm, \
1092 LIBS_linux := $(LIBDL), \
1093 + LIBS_solaris := -lnsl -lsocket $(LIBDL), \
1094 LIBS_aix := $(LIBDL),\
1095 LIBS_windows := advapi32.lib delayimp.lib iphlpapi.lib secur32.lib \
1096 winhttp.lib ws2_32.lib, \
1097 @@ -77,8 +78,9 @@
1098 libnio/ch \
1099 libnio/fs \
1100 libjvm, \
1101 - JDK_LIBS := libjava libnet, \
1102 + JDK_LIBS := libjava libjvm libnet, \
1103 LIBS_linux := $(LIBDL) -lpthread, \
1104 + LIBS_solaris := -lsocket -lposix4 $(LIBDL) -lsendfile, \
1105 LIBS_aix := $(LIBDL), \
1106 LIBS_macosx := \
1107 -framework CoreFoundation \
1108 @@ -117,6 +119,7 @@
1109 OPTIMIZATION := LOW, \
1110 jsig.c_CFLAGS := -DHOTSPOT_VM_DISTRO='"$(HOTSPOT_VM_DISTRO)"', \
1111 LIBS_linux := $(LIBDL), \
1112 + LIBS_solaris := $(LIBDL), \
1113 LIBS_aix := $(LIBDL), \
1116 diff -Nru jdk23u-jdk-23-36.orig/make/modules/java.desktop/Gensrc.gmk jdk23u-jdk-23-36/make/modules/java.desktop/Gensrc.gmk
1117 --- jdk23u-jdk-23-36.orig/make/modules/java.desktop/Gensrc.gmk 2024-08-07 00:08:22.000000000 +0200
1118 +++ jdk23u-jdk-23-36/make/modules/java.desktop/Gensrc.gmk 2024-08-17 19:50:33.076199278 +0200
1119 @@ -32,7 +32,7 @@
1120 include gensrc/GensrcIcons.gmk
1121 endif
1123 -ifeq ($(call isTargetOs, linux aix), true)
1124 +ifeq ($(call isTargetOs, linux solaris aix), true)
1125 include gensrc/GensrcX11Wrappers.gmk
1126 endif
1128 diff -Nru jdk23u-jdk-23-36.orig/make/modules/java.desktop/lib/AwtLibraries.gmk jdk23u-jdk-23-36/make/modules/java.desktop/lib/AwtLibraries.gmk
1129 --- jdk23u-jdk-23-36.orig/make/modules/java.desktop/lib/AwtLibraries.gmk 2024-08-07 00:08:22.000000000 +0200
1130 +++ jdk23u-jdk-23-36/make/modules/java.desktop/lib/AwtLibraries.gmk 2024-08-17 19:50:33.077213672 +0200
1131 @@ -57,7 +57,7 @@
1133 endif
1135 -ifeq ($(call isTargetOs, linux macosx aix), true)
1136 +ifeq ($(call isTargetOs, solaris linux macosx aix), true)
1137 LIBAWT_EXCLUDE_FILES += awt_Font.c CUPSfuncs.c fontpath.c X11Color.c
1138 endif
1140 @@ -125,6 +125,7 @@
1141 JDK_LIBS := java.base:libjava java.base:libjvm, \
1142 LIBS_unix := $(LIBM), \
1143 LIBS_linux := $(LIBDL), \
1144 + LIBS_solaris := $(LIBDL), \
1145 LIBS_aix := $(LIBDL),\
1146 LIBS_macosx := \
1147 -framework ApplicationServices \
1148 @@ -180,8 +181,9 @@
1149 EXTRA_HEADER_DIRS := $(LIBAWT_HEADLESS_EXTRA_HEADER_DIRS), \
1150 DISABLED_WARNINGS_gcc_X11Renderer.c := unused-function, \
1151 DISABLED_WARNINGS_gcc_X11SurfaceData.c := unused-function, \
1152 - JDK_LIBS := libawt java.base:libjava, \
1153 + JDK_LIBS := libawt java.base:libjava java.base:libjvm, \
1154 LIBS_linux := $(LIBDL) $(LIBM), \
1155 + LIBS_solaris := $(LIBDL) $(LIBM) $(LIBCXX), \
1156 STATIC_LIB_EXCLUDE_OBJS := $(LIBAWT_HEADLESS_STATIC_EXCLUDE_OBJS), \
1159 @@ -269,7 +271,7 @@
1160 DISABLED_WARNINGS_clang_aix_sun_awt_X11_GtkFileDialogPeer.c := \
1161 parentheses, \
1162 DISABLED_WARNINGS_clang_aix_awt_InputMethod.c := sign-compare, \
1163 - JDK_LIBS := libawt java.base:libjava, \
1164 + JDK_LIBS := libawt java.base:libjava java.base:libjvm, \
1165 LIBS_unix := $(LIBDL) $(LIBM) $(X_LIBS) -lX11 -lXext -lXi -lXrender \
1166 -lXtst, \
1167 LIBS_linux := -lpthread, \
1168 @@ -386,7 +388,7 @@
1169 endif
1171 ifeq ($(call isTargetOsType, unix)+$(call isTargetOs, macosx), true+false)
1172 - LIBJAWT_JDK_LIBS_unix := libawt
1173 + LIBJAWT_JDK_LIBS_unix := libawt java.base:libjava java.base:libjvm
1174 ifeq ($(ENABLE_HEADLESS_ONLY), false)
1175 LIBJAWT_JDK_LIBS_unix += libawt_xawt
1176 else
1177 @@ -406,6 +408,7 @@
1178 LDFLAGS_windows := $(LDFLAGS_CXX_JDK), \
1179 LDFLAGS_macosx := -Wl$(COMMA)-rpath$(COMMA)@loader_path, \
1180 JDK_LIBS_unix := $(LIBJAWT_JDK_LIBS_unix), \
1181 + LIBS_solaris := $(X_LIBS) -lXrender, \
1182 JDK_LIBS_windows := libawt, \
1183 JDK_LIBS_macosx := libawt_lwawt, \
1184 LIBS_macosx := -framework Cocoa, \
1185 diff -Nru jdk23u-jdk-23-36.orig/make/modules/java.desktop/lib/ClientLibraries.gmk jdk23u-jdk-23-36/make/modules/java.desktop/lib/ClientLibraries.gmk
1186 --- jdk23u-jdk-23-36.orig/make/modules/java.desktop/lib/ClientLibraries.gmk 2024-08-07 00:08:22.000000000 +0200
1187 +++ jdk23u-jdk-23-36/make/modules/java.desktop/lib/ClientLibraries.gmk 2024-08-17 19:50:33.077793660 +0200
1188 @@ -87,7 +87,7 @@
1189 DISABLED_WARNINGS_gcc := format-nonliteral type-limits \
1190 stringop-truncation, \
1191 DISABLED_WARNINGS_clang := format-nonliteral, \
1192 - JDK_LIBS := libawt java.base:libjava, \
1193 + JDK_LIBS := libawt java.base:libjava java.base:libjvm, \
1194 LIBS_unix := $(LCMS_LIBS) $(LIBM), \
1197 @@ -121,7 +121,7 @@
1198 DISABLED_WARNINGS_gcc_imageioJPEG.c := clobbered array-bounds, \
1199 DISABLED_WARNINGS_gcc_jcmaster.c := implicit-fallthrough, \
1200 DISABLED_WARNINGS_gcc_jdphuff.c := shift-negative-value, \
1201 - JDK_LIBS := java.base:libjava, \
1202 + JDK_LIBS := java.base:libjava java.base:libjvm, \
1203 LIBS := $(LIBJPEG_LIBS), \
1206 @@ -242,6 +242,7 @@
1207 LIBS := $(GIFLIB_LIBS) $(LIBJPEG_LIBS) $(LIBZ_LIBS) $(PNG_LIBS), \
1208 LIBS_unix := $(LIBM) -lpthread, \
1209 LIBS_linux := $(LIBDL) $(X_LIBS) -lX11 -lXext, \
1210 + LIBS_solaris := $(LIBDL) $(X_LIBS) -lX11 -lXext, \
1211 LIBS_macosx := -liconv \
1212 -framework ApplicationServices \
1213 -framework Cocoa \
1214 @@ -289,7 +290,7 @@
1215 -DHAVE_SYSCONF -DHAVE_SYS_MMAN_H -DHAVE_UNISTD_H \
1216 -DHB_NO_PRAGMA_GCC_DIAGNOSTIC
1217 endif
1218 - ifeq ($(call isTargetOs, linux macosx), true)
1219 + ifeq ($(call isTargetOs, solaris linux macosx), true)
1220 HARFBUZZ_CFLAGS += -DHAVE_INTEL_ATOMIC_PRIMITIVES -DHB_NO_VISIBILITY
1221 endif
1223 diff -Nru jdk23u-jdk-23-36.orig/make/modules/java.desktop/Lib.gmk jdk23u-jdk-23-36/make/modules/java.desktop/Lib.gmk
1224 --- jdk23u-jdk-23-36.orig/make/modules/java.desktop/Lib.gmk 2024-08-07 00:08:22.000000000 +0200
1225 +++ jdk23u-jdk-23-36/make/modules/java.desktop/Lib.gmk 2024-08-17 19:50:33.076541450 +0200
1226 @@ -48,10 +48,15 @@
1227 -DX_PLATFORM=X_$(OPENJDK_TARGET_OS_UPPERCASE) \
1228 -DUSE_PORTS=TRUE \
1229 -DUSE_DAUDIO=TRUE \
1230 - -DUSE_PLATFORM_MIDI_OUT=TRUE \
1231 - -DUSE_PLATFORM_MIDI_IN=TRUE \
1234 + ifeq ($(call isTargetOs, solaris), false)
1235 + LIBJSOUND_CFLAGS += \
1236 + -DUSE_PLATFORM_MIDI_OUT=TRUE \
1237 + -DUSE_PLATFORM_MIDI_IN=TRUE \
1239 + endif
1241 LIBJSOUND_LINK_TYPE := C
1242 ifeq ($(call isTargetOs, macosx), true)
1243 LIBJSOUND_LINK_TYPE := C++
1244 diff -Nru jdk23u-jdk-23-36.orig/make/modules/java.instrument/Lib.gmk jdk23u-jdk-23-36/make/modules/java.instrument/Lib.gmk
1245 --- jdk23u-jdk-23-36.orig/make/modules/java.instrument/Lib.gmk 2024-08-07 00:08:22.000000000 +0200
1246 +++ jdk23u-jdk-23-36/make/modules/java.instrument/Lib.gmk 2024-08-17 19:50:33.078211096 +0200
1247 @@ -39,6 +39,7 @@
1248 JDK_LIBS := java.base:libjava java.base:libjli java.base:libjvm, \
1249 LIBS_unix := $(LIBZ_LIBS), \
1250 LIBS_linux := $(LIBDL), \
1251 + LIBS_solaris := $(LIBDL), \
1252 LIBS_aix := $(LIBDL) -liconv, \
1253 LIBS_macosx := -liconv \
1254 -framework ApplicationServices \
1255 diff -Nru jdk23u-jdk-23-36.orig/make/modules/java.management/Lib.gmk jdk23u-jdk-23-36/make/modules/java.management/Lib.gmk
1256 --- jdk23u-jdk-23-36.orig/make/modules/java.management/Lib.gmk 2024-08-07 00:08:22.000000000 +0200
1257 +++ jdk23u-jdk-23-36/make/modules/java.management/Lib.gmk 2024-08-17 19:50:33.078648231 +0200
1258 @@ -30,7 +30,7 @@
1259 ################################################################################
1261 LIBMANAGEMENT_OPTIMIZATION := HIGH
1262 -ifeq ($(call isTargetOs, linux)+$(COMPILE_WITH_DEBUG_SYMBOLS), true+true)
1263 +ifeq ($(call isTargetOs, solaris linux)+$(COMPILE_WITH_DEBUG_SYMBOLS), true+true)
1264 LIBMANAGEMENT_OPTIMIZATION := LOW
1265 endif
1267 @@ -38,6 +38,7 @@
1268 NAME := management, \
1269 OPTIMIZATION := $(LIBMANAGEMENT_OPTIMIZATION), \
1270 JDK_LIBS := java.base:libjava java.base:libjvm, \
1271 + LIBS_solaris := -lkstat, \
1272 LIBS_aix := -lperfstat,\
1273 LIBS_windows := advapi32.lib psapi.lib, \
1275 diff -Nru jdk23u-jdk-23-36.orig/make/modules/jdk.attach/Lib.gmk jdk23u-jdk-23-36/make/modules/jdk.attach/Lib.gmk
1276 --- jdk23u-jdk-23-36.orig/make/modules/jdk.attach/Lib.gmk 2024-08-07 00:08:22.000000000 +0200
1277 +++ jdk23u-jdk-23-36/make/modules/jdk.attach/Lib.gmk 2024-08-17 19:50:33.079051331 +0200
1278 @@ -41,7 +41,8 @@
1279 OPTIMIZATION := LOW, \
1280 CFLAGS := $(LIBATTACH_CFLAGS), \
1281 CFLAGS_windows := -Gy, \
1282 - JDK_LIBS := java.base:libjava, \
1283 + JDK_LIBS := java.base:libjava java.base:libjvm, \
1284 + LIBS_solaris := -ldoor, \
1285 LIBS_windows := advapi32.lib psapi.lib, \
1288 diff -Nru jdk23u-jdk-23-36.orig/make/modules/jdk.crypto.cryptoki/Copy.gmk jdk23u-jdk-23-36/make/modules/jdk.crypto.cryptoki/Copy.gmk
1289 --- jdk23u-jdk-23-36.orig/make/modules/jdk.crypto.cryptoki/Copy.gmk 1970-01-01 01:00:00.000000000 +0100
1290 +++ jdk23u-jdk-23-36/make/modules/jdk.crypto.cryptoki/Copy.gmk 2024-08-17 19:50:33.140692837 +0200
1291 @@ -0,0 +1,45 @@
1293 +# Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
1294 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1296 +# This code is free software; you can redistribute it and/or modify it
1297 +# under the terms of the GNU General Public License version 2 only, as
1298 +# published by the Free Software Foundation. Oracle designates this
1299 +# particular file as subject to the "Classpath" exception as provided
1300 +# by Oracle in the LICENSE file that accompanied this code.
1302 +# This code is distributed in the hope that it will be useful, but WITHOUT
1303 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1304 +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1305 +# version 2 for more details (a copy is included in the LICENSE file that
1306 +# accompanied this code).
1308 +# You should have received a copy of the GNU General Public License version
1309 +# 2 along with this work; if not, write to the Free Software Foundation,
1310 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1312 +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1313 +# or visit www.oracle.com if you need additional information or have any
1314 +# questions.
1317 +include CopyCommon.gmk
1319 +################################################################################
1321 +ifeq ($(call isTargetOs, solaris), true)
1323 + SUNPKCS11_CFG_SRC := \
1324 + $(TOPDIR)/src/jdk.crypto.cryptoki/solaris/conf/security/sunpkcs11-solaris.cfg
1325 + SUNPKCS11_CFG_DST := $(CONF_DST_DIR)/security/sunpkcs11-solaris.cfg
1327 + $(SUNPKCS11_CFG_DST): $(SUNPKCS11_CFG_SRC)
1328 + $(call install-file)
1330 + SECURITY_PKCS11_CONF_FILES += $(SUNPKCS11_CFG_DST)
1332 + TARGETS := $(SUNPKCS11_CFG_DST)
1334 +endif
1336 +################################################################################
1337 diff -Nru jdk23u-jdk-23-36.orig/make/modules/jdk.hotspot.agent/Lib.gmk jdk23u-jdk-23-36/make/modules/jdk.hotspot.agent/Lib.gmk
1338 --- jdk23u-jdk-23-36.orig/make/modules/jdk.hotspot.agent/Lib.gmk 2024-08-07 00:08:22.000000000 +0200
1339 +++ jdk23u-jdk-23-36/make/modules/jdk.hotspot.agent/Lib.gmk 2024-08-17 19:50:33.079431621 +0200
1340 @@ -67,8 +67,9 @@
1341 CFLAGS := $(LIBSAPROC_CFLAGS), \
1342 CXXFLAGS := $(LIBSAPROC_CFLAGS) $(LIBSAPROC_CXXFLAGS), \
1343 EXTRA_SRC := $(LIBSAPROC_EXTRA_SRC), \
1344 - JDK_LIBS := java.base:libjava, \
1345 + JDK_LIBS := java.base:libjava java.base:libjvm, \
1346 LIBS_linux := $(LIBDL), \
1347 + LIBS_solaris := -ldl -lstdc++ -lthread -lproc, \
1348 LIBS_macosx := \
1349 -framework CoreFoundation \
1350 -framework Foundation \
1351 diff -Nru jdk23u-jdk-23-36.orig/make/modules/jdk.jdwp.agent/Lib.gmk jdk23u-jdk-23-36/make/modules/jdk.jdwp.agent/Lib.gmk
1352 --- jdk23u-jdk-23-36.orig/make/modules/jdk.jdwp.agent/Lib.gmk 2024-08-07 00:08:22.000000000 +0200
1353 +++ jdk23u-jdk-23-36/make/modules/jdk.jdwp.agent/Lib.gmk 2024-08-17 19:50:33.079857876 +0200
1354 @@ -37,6 +37,7 @@
1355 include \
1356 libjdwp/export, \
1357 LIBS_linux := -lpthread, \
1358 + LIBS_solaris := -lnsl -lsocket, \
1359 LIBS_windows := iphlpapi.lib ws2_32.lib, \
1362 @@ -63,6 +64,7 @@
1363 java.base:libjava \
1364 java.base:libjvm, \
1365 LIBS_linux := $(LIBDL), \
1366 + LIBS_solaris := $(LIBDL), \
1367 LIBS_macosx := -liconv, \
1368 LIBS_aix := -liconv, \
1370 diff -Nru jdk23u-jdk-23-36.orig/make/modules/jdk.management/Lib.gmk jdk23u-jdk-23-36/make/modules/jdk.management/Lib.gmk
1371 --- jdk23u-jdk-23-36.orig/make/modules/jdk.management/Lib.gmk 2024-08-07 00:08:22.000000000 +0200
1372 +++ jdk23u-jdk-23-36/make/modules/jdk.management/Lib.gmk 2024-08-17 19:50:33.080304423 +0200
1373 @@ -37,7 +37,7 @@
1374 endif
1376 LIBMANAGEMENT_EXT_OPTIMIZATION := HIGH
1377 -ifeq ($(call isTargetOs, linux)+$(COMPILE_WITH_DEBUG_SYMBOLS), true+true)
1378 +ifeq ($(call isTargetOs, solaris linux)+$(COMPILE_WITH_DEBUG_SYMBOLS), true+true)
1379 LIBMANAGEMENT_EXT_OPTIMIZATION := LOW
1380 endif
1382 @@ -47,6 +47,7 @@
1383 DISABLED_WARNINGS_clang_UnixOperatingSystem.c := format-nonliteral, \
1384 CFLAGS := $(LIBMANAGEMENT_EXT_CFLAGS), \
1385 JDK_LIBS := java.base:libjava java.base:libjvm, \
1386 + LIBS_solaris := -lkstat, \
1387 LIBS_aix := -lperfstat,\
1388 LIBS_windows := advapi32.lib psapi.lib, \
1390 diff -Nru jdk23u-jdk-23-36.orig/make/modules/jdk.management.agent/Lib.gmk jdk23u-jdk-23-36/make/modules/jdk.management.agent/Lib.gmk
1391 --- jdk23u-jdk-23-36.orig/make/modules/jdk.management.agent/Lib.gmk 2024-08-07 00:08:22.000000000 +0200
1392 +++ jdk23u-jdk-23-36/make/modules/jdk.management.agent/Lib.gmk 2024-08-17 19:50:33.080743212 +0200
1393 @@ -32,7 +32,7 @@
1394 $(eval $(call SetupJdkLibrary, BUILD_LIBMANAGEMENT_AGENT, \
1395 NAME := management_agent, \
1396 OPTIMIZATION := LOW, \
1397 - JDK_LIBS := java.base:libjava, \
1398 + JDK_LIBS := java.base:libjava java.base:libjvm, \
1399 LIBS_windows := advapi32.lib, \
1402 diff -Nru jdk23u-jdk-23-36.orig/make/modules/jdk.net/Lib.gmk jdk23u-jdk-23-36/make/modules/jdk.net/Lib.gmk
1403 --- jdk23u-jdk-23-36.orig/make/modules/jdk.net/Lib.gmk 2024-08-07 00:08:22.000000000 +0200
1404 +++ jdk23u-jdk-23-36/make/modules/jdk.net/Lib.gmk 2024-08-17 19:50:33.081189061 +0200
1405 @@ -29,6 +29,8 @@
1406 ## Build libextnet
1407 ################################################################################
1409 +ifeq ($(call isTargetOs, solaris), false)
1411 $(eval $(call SetupJdkLibrary, BUILD_LIBEXTNET, \
1412 NAME := extnet, \
1413 OPTIMIZATION := LOW, \
1414 @@ -38,3 +40,5 @@
1417 TARGETS += $(BUILD_LIBEXTNET)
1419 +endif
1420 diff -Nru jdk23u-jdk-23-36.orig/make/modules/jdk.sctp/Lib.gmk jdk23u-jdk-23-36/make/modules/jdk.sctp/Lib.gmk
1421 --- jdk23u-jdk-23-36.orig/make/modules/jdk.sctp/Lib.gmk 2024-08-07 00:08:22.000000000 +0200
1422 +++ jdk23u-jdk-23-36/make/modules/jdk.sctp/Lib.gmk 2024-08-17 19:50:33.081594528 +0200
1423 @@ -40,6 +40,7 @@
1424 java.base:libnio/ch, \
1425 JDK_LIBS := java.base:libjava java.base:libnet, \
1426 LIBS_linux := $(LIBDL) -lpthread, \
1427 + LIBS_solaris := -lsocket, \
1430 TARGETS += $(BUILD_LIBSCTP)
1431 diff -Nru jdk23u-jdk-23-36.orig/make/RunTestsPrebuilt.gmk jdk23u-jdk-23-36/make/RunTestsPrebuilt.gmk
1432 --- jdk23u-jdk-23-36.orig/make/RunTestsPrebuilt.gmk 2024-08-07 00:08:22.000000000 +0200
1433 +++ jdk23u-jdk-23-36/make/RunTestsPrebuilt.gmk 2024-08-17 19:50:33.066487995 +0200
1434 @@ -168,6 +168,8 @@
1435 OPENJDK_TARGET_OS := linux
1436 else ifeq ($(UNAME_OS), Darwin)
1437 OPENJDK_TARGET_OS := macosx
1438 + else ifeq ($(UNAME_OS), SunOS)
1439 + OPENJDK_TARGET_OS := solaris
1440 else
1441 OPENJDK_TARGET_OS := $(UNAME_OS)
1442 endif
1443 @@ -180,15 +182,28 @@
1444 # Assume little endian unless otherwise specified
1445 OPENJDK_TARGET_CPU_ENDIAN := little
1447 -UNAME_CPU := $(shell $(UNAME) -m)
1448 -ifeq ($(UNAME_CPU), i686)
1449 - OPENJDK_TARGET_CPU := x86
1450 - OPENJDK_TARGET_CPU_BITS := 32
1451 -else
1452 - # Assume all others are 64-bit. We use the same CPU name as uname for
1453 - # at least x86_64 and aarch64.
1454 - OPENJDK_TARGET_CPU := $(UNAME_CPU)
1455 +ifeq ($(OPENJDK_TARGET_OS), solaris)
1456 + # On solaris, use uname -p
1457 + UNAME_CPU := $(shell $(UNAME) -p)
1458 + # Assume 64-bit platform
1459 OPENJDK_TARGET_CPU_BITS := 64
1460 + ifeq ($(UNAME_CPU), i386)
1461 + OPENJDK_TARGET_CPU := x86_64
1462 + else
1463 + OPENJDK_TARGET_CPU := $(UNAME_CPU)
1464 + endif
1465 +else
1466 + # ... all others use uname -m
1467 + UNAME_CPU := $(shell $(UNAME) -m)
1468 + ifeq ($(UNAME_CPU), i686)
1469 + OPENJDK_TARGET_CPU := x86
1470 + OPENJDK_TARGET_CPU_BITS := 32
1471 + else
1472 + # Assume all others are 64-bit. We use the same CPU name as uname for
1473 + # at least x86_64 and aarch64.
1474 + OPENJDK_TARGET_CPU := $(UNAME_CPU)
1475 + OPENJDK_TARGET_CPU_BITS := 64
1476 + endif
1477 endif
1479 OPENJDK_TARGET_CPU_ARCH := $(OPENJDK_TARGET_CPU)
1480 @@ -213,6 +228,11 @@
1481 else ifeq ($(OPENJDK_TARGET_OS), macosx)
1482 NUM_CORES := $(shell /usr/sbin/sysctl -n hw.ncpu)
1483 MEMORY_SIZE := $(shell $(EXPR) `/usr/sbin/sysctl -n hw.memsize` / 1024 / 1024)
1484 +else ifeq ($(OPENJDK_TARGET_OS), solaris)
1485 + NUM_CORES := $(shell /usr/sbin/psrinfo -v | $(GREP) -c on-line)
1486 + MEMORY_SIZE := $(shell \
1487 + /usr/sbin/prtconf 2> /dev/null | $(GREP) "^Memory [Ss]ize" | $(AWK) '{print $$3}' \
1489 else ifeq ($(OPENJDK_TARGET_OS), windows)
1490 NUM_CORES := $(NUMBER_OF_PROCESSORS)
1491 MEMORY_SIZE := $(shell \
1492 diff -Nru jdk23u-jdk-23-36.orig/make/RunTestsPrebuiltSpec.gmk jdk23u-jdk-23-36/make/RunTestsPrebuiltSpec.gmk
1493 --- jdk23u-jdk-23-36.orig/make/RunTestsPrebuiltSpec.gmk 2024-08-07 00:08:22.000000000 +0200
1494 +++ jdk23u-jdk-23-36/make/RunTestsPrebuiltSpec.gmk 2024-08-17 19:50:33.066865085 +0200
1495 @@ -173,6 +173,16 @@
1496 FILE := file
1497 ULIMIT := ulimit
1499 +# On Solaris gnu versions of some tools are required.
1500 +ifeq ($(OPENJDK_BUILD_OS), solaris)
1501 + AWK := gawk
1502 + GREP := ggrep
1503 + EGREP := ggrep -E
1504 + FGREP := grep -F
1505 + SED := gsed
1506 + TAR := gtar
1507 +endif
1509 ifeq ($(OPENJDK_BUILD_OS), windows)
1510 PATHTOOL := cygpath
1511 endif
1512 diff -Nru jdk23u-jdk-23-36.orig/make/scripts/compare.sh jdk23u-jdk-23-36/make/scripts/compare.sh
1513 --- jdk23u-jdk-23-36.orig/make/scripts/compare.sh 2024-08-07 00:08:22.000000000 +0200
1514 +++ jdk23u-jdk-23-36/make/scripts/compare.sh 2024-08-17 19:50:33.083299191 +0200
1515 @@ -75,7 +75,14 @@
1516 # Disassembly diff filters. These filters try to filter out ephemeral parts of the
1517 # disassembly, such as hard-coded addresses, to be able to catch "actual" differences.
1519 -if [ "$OPENJDK_TARGET_OS" = "windows" ]; then
1520 +if [ "$OPENJDK_TARGET_OS" = "solaris" ]; then
1521 + if [ "$OPENJDK_TARGET_CPU" = "x86_64" ]; then
1522 + # Random strings looking like this differ: <.XAKoKoPIac2W0OA.
1523 + DIS_DIFF_FILTER="$SED \
1524 + -e 's/<\.[A-Za-z0-9]\{\15}\./<.SYM./' \
1526 + fi
1527 +elif [ "$OPENJDK_TARGET_OS" = "windows" ]; then
1528 if [ "$OPENJDK_TARGET_CPU" = "x86" ]; then
1529 DIS_DIFF_FILTER="$SED -r \
1530 -e 's/^ [0-9A-F]{16}: //' \
1531 @@ -398,7 +405,14 @@
1534 CONTENTS_DIFF_FILE=$WORK_DIR/$ZIP_FILE.diff
1535 - $DIFF -rq $OTHER_UNZIPDIR $THIS_UNZIPDIR > $CONTENTS_DIFF_FILE
1536 + # On solaris, there is no -q option.
1537 + if [ "$OPENJDK_TARGET_OS" = "solaris" ]; then
1538 + $DIFF -r $OTHER_UNZIPDIR $THIS_UNZIPDIR \
1539 + | $GREP -v -e "^<" -e "^>" -e "^Common subdirectories:" \
1540 + > $CONTENTS_DIFF_FILE
1541 + else
1542 + $DIFF -rq $OTHER_UNZIPDIR $THIS_UNZIPDIR > $CONTENTS_DIFF_FILE
1543 + fi
1545 ONLY_OTHER=$($GREP "^Only in $OTHER_UNZIPDIR" $CONTENTS_DIFF_FILE)
1546 ONLY_THIS=$($GREP "^Only in $THIS_UNZIPDIR" $CONTENTS_DIFF_FILE)
1547 @@ -420,8 +434,14 @@
1550 if [ "$CMP_ZIPS_CONTENTS" = "true" ]; then
1551 - DIFFING_FILES=$($GREP -e "differ$" $CONTENTS_DIFF_FILE \
1552 - | $CUT -f 2 -d ' ' | $SED "s|$OTHER_UNZIPDIR/||g")
1553 + if [ "$OPENJDK_TARGET_OS" = "solaris" ]; then
1554 + DIFFING_FILES=$($GREP -e 'differ$' -e '^diff ' $CONTENTS_DIFF_FILE \
1555 + | $SED -e 's/^Files //g' -e 's/diff -r //g' | $CUT -f 1 -d ' ' \
1556 + | $SED "s|$OTHER_UNZIPDIR/||g")
1557 + else
1558 + DIFFING_FILES=$($GREP -e "differ$" $CONTENTS_DIFF_FILE \
1559 + | $CUT -f 2 -d ' ' | $SED "s|$OTHER_UNZIPDIR/||g")
1560 + fi
1562 # Separate executable/library files from other files in zip.
1563 DIFFING_TEXT_FILES=
1564 @@ -769,6 +789,10 @@
1565 # to filter out that extra information.
1566 $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
1567 $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
1568 + elif [ "$OPENJDK_TARGET_OS" = "solaris" ]; then
1569 + # Some symbols get seemingly random 15 character prefixes. Filter them out.
1570 + $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
1571 + $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
1572 elif [ "$OPENJDK_TARGET_OS" = "aix" ]; then
1573 $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
1574 $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
1575 diff -Nru jdk23u-jdk-23-36.orig/make/scripts/hide_important_warnings_from_javac.sh jdk23u-jdk-23-36/make/scripts/hide_important_warnings_from_javac.sh
1576 --- jdk23u-jdk-23-36.orig/make/scripts/hide_important_warnings_from_javac.sh 2024-08-07 00:08:22.000000000 +0200
1577 +++ jdk23u-jdk-23-36/make/scripts/hide_important_warnings_from_javac.sh 2024-08-17 19:50:33.083925827 +0200
1578 @@ -22,8 +22,13 @@
1579 # questions.
1582 -GREP=grep
1584 +if [ -x /usr/bin/ggrep ] ; then
1585 + # Gnu grep on Solaris
1586 + # (reference configure and build/solaris-i586-clientANDserver-release/spec.gmk
1587 + GREP=/usr/bin/ggrep
1588 +else
1589 + GREP=grep
1592 EXP="Note: Some input files use or override a deprecated API."
1593 EXP="${EXP}|Note: Recompile with -Xlint:deprecation for details."
1594 diff -Nru jdk23u-jdk-23-36.orig/make/test/JtregNativeHotspot.gmk jdk23u-jdk-23-36/make/test/JtregNativeHotspot.gmk
1595 --- jdk23u-jdk-23-36.orig/make/test/JtregNativeHotspot.gmk 2024-08-07 00:08:22.000000000 +0200
1596 +++ jdk23u-jdk-23-36/make/test/JtregNativeHotspot.gmk 2024-08-17 19:50:33.085386613 +0200
1597 @@ -867,6 +867,10 @@
1598 BUILD_HOTSPOT_JTREG_LIBRARIES_JDK_LIBS_libatExit := java.base:libjvm
1599 BUILD_HOTSPOT_JTREG_EXECUTABLES_JDK_LIBS_exedaemonDestroy := java.base:libjvm
1601 +ifeq ($(call isTargetOs, solaris), true)
1602 + BUILD_HOTSPOT_JTREG_EXCLUDE += libterminatedThread.c
1603 +endif
1605 ifeq ($(call isTargetOs, windows), true)
1606 BUILD_HOTSPOT_JTREG_EXECUTABLES_CFLAGS_exeFPRegs := -MT
1607 BUILD_HOTSPOT_JTREG_EXCLUDE += exesigtest.c libterminatedThread.c libTestJNI.c libCompleteExit.c libMonitorWithDeadObjectTest.c libTestPsig.c exeGetCreatedJavaVMs.c
1608 diff -Nru jdk23u-jdk-23-36.orig/make/test/JtregNativeJdk.gmk jdk23u-jdk-23-36/make/test/JtregNativeJdk.gmk
1609 --- jdk23u-jdk-23-36.orig/make/test/JtregNativeJdk.gmk 2024-08-07 00:08:22.000000000 +0200
1610 +++ jdk23u-jdk-23-36/make/test/JtregNativeJdk.gmk 2024-08-17 19:50:33.086298583 +0200
1611 @@ -59,10 +59,10 @@
1612 BUILD_JDK_JTREG_EXECUTABLES_JDK_LIBS_exeCallerAccessTest := java.base:libjvm
1613 BUILD_JDK_JTREG_EXECUTABLES_JDK_LIBS_exeNullCallerTest := java.base:libjvm
1615 -BUILD_JDK_JTREG_LIBRARIES_JDK_LIBS_libstringPlatformChars := java.base:libjava
1616 +BUILD_JDK_JTREG_LIBRARIES_JDK_LIBS_libstringPlatformChars := java.base:libjava java.base:libjvm
1617 BUILD_JDK_JTREG_LIBRARIES_JDK_LIBS_libTracePinnedThreads := java.base:libjvm
1618 -BUILD_JDK_JTREG_LIBRARIES_JDK_LIBS_libNewDirectByteBuffer := java.base:libjava
1619 -BUILD_JDK_JTREG_LIBRARIES_JDK_LIBS_libGetXSpace := java.base:libjava
1620 +BUILD_JDK_JTREG_LIBRARIES_JDK_LIBS_libNewDirectByteBuffer := java.base:libjava java.base:libjvm
1621 +BUILD_JDK_JTREG_LIBRARIES_JDK_LIBS_libGetXSpace := java.base:libjava java.base:libjvm
1623 # Platform specific setup
1624 ifeq ($(call isTargetOs, windows), true)
1625 @@ -74,7 +74,7 @@
1626 BUILD_JDK_JTREG_EXECUTABLES_LIBS_exerevokeall := advapi32.lib
1627 BUILD_JDK_JTREG_EXECUTABLES_CFLAGS_exeNullCallerTest := /EHsc
1628 else
1629 - BUILD_JDK_JTREG_LIBRARIES_JDK_LIBS_libDirectIO := java.base:libjava
1630 + BUILD_JDK_JTREG_LIBRARIES_JDK_LIBS_libDirectIO := java.base:libjava java.base:libjvm
1631 BUILD_JDK_JTREG_LIBRARIES_LDFLAGS_libNativeThread := -pthread
1633 # java.lang.foreign tests
1634 @@ -91,6 +91,9 @@
1635 ifeq ($(call isTargetOs, linux), true)
1636 BUILD_JDK_JTREG_LIBRARIES_JDK_LIBS_libInheritedChannel := java.base:libjava
1637 BUILD_JDK_JTREG_EXECUTABLES_LIBS_exelauncher := -ldl
1638 + else ifeq ($(call isTargetOs, solaris), true)
1639 + BUILD_JDK_JTREG_LIBRARIES_JDK_LIBS_libInheritedChannel := java.base:libjava java.base:libjvm
1640 + BUILD_JDK_JTREG_EXECUTABLES_LIBS_exelauncher := -lsocket -lnsl -lthread -ldl
1641 endif
1642 BUILD_JDK_JTREG_EXECUTABLES_LIBS_exeNullCallerTest := $(LIBCXX)
1643 endif
1644 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/cpu/x86/globalDefinitions_x86.hpp jdk23u-jdk-23-36/src/hotspot/cpu/x86/globalDefinitions_x86.hpp
1645 --- jdk23u-jdk-23-36.orig/src/hotspot/cpu/x86/globalDefinitions_x86.hpp 2024-08-07 00:08:22.000000000 +0200
1646 +++ jdk23u-jdk-23-36/src/hotspot/cpu/x86/globalDefinitions_x86.hpp 2024-08-17 19:50:33.087265798 +0200
1647 @@ -57,7 +57,7 @@
1648 #define INCLUDE_RTM_OPT 1
1649 #endif
1651 -#if defined(LINUX) || defined(__APPLE__)
1652 +#if defined(LINUX) || defined(SOLARIS) || defined(__APPLE__)
1653 #define SUPPORT_RESERVED_STACK_AREA
1654 #endif
1656 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/os/posix/include/jvm_md.h jdk23u-jdk-23-36/src/hotspot/os/posix/include/jvm_md.h
1657 --- jdk23u-jdk-23-36.orig/src/hotspot/os/posix/include/jvm_md.h 2024-08-07 00:08:22.000000000 +0200
1658 +++ jdk23u-jdk-23-36/src/hotspot/os/posix/include/jvm_md.h 2024-08-17 19:50:33.088186364 +0200
1659 @@ -54,7 +54,7 @@
1660 #endif
1661 #define JNI_LIB_NAME(NAME) JNI_LIB_PREFIX NAME JNI_LIB_SUFFIX
1663 -#if defined(AIX)
1664 +#if defined(AIX) || defined(SOLARIS)
1665 #define JVM_MAXPATHLEN MAXPATHLEN
1666 #else
1667 // Hack: MAXPATHLEN is 4095 on some Linux and 4096 on others. This may
1668 @@ -87,8 +87,14 @@
1669 #define JVM_SIGTERM SIGTERM
1671 #define BREAK_SIGNAL SIGQUIT /* Thread dumping support. */
1672 +#ifdef SOLARIS
1673 +#define ASYNC_SIGNAL SIGJVM2 /* Event-based suspend/resume support */
1674 +#endif // SOLARIS
1675 #define SHUTDOWN1_SIGNAL SIGHUP /* Shutdown Hooks support. */
1676 #define SHUTDOWN2_SIGNAL SIGINT
1677 #define SHUTDOWN3_SIGNAL SIGTERM
1679 +/* With 1.4.1 libjsig added versioning: used in os_solaris.cpp and jsig.c */
1680 +#define JSIG_VERSION_1_4_1 0x30140100
1682 #endif /* !_JAVASOFT_JVM_MD_H_ */
1683 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/os/posix/os_posix.cpp jdk23u-jdk-23-36/src/hotspot/os/posix/os_posix.cpp
1684 --- jdk23u-jdk-23-36.orig/src/hotspot/os/posix/os_posix.cpp 2024-08-07 00:08:22.000000000 +0200
1685 +++ jdk23u-jdk-23-36/src/hotspot/os/posix/os_posix.cpp 2024-08-17 19:50:33.089505807 +0200
1686 @@ -500,7 +500,7 @@
1687 st->print("%ld", sysconf(_SC_CHILD_MAX));
1689 print_rlimit(st, ", THREADS", RLIMIT_THREADS);
1690 -#else
1691 +#elif !defined(SOLARIS)
1692 print_rlimit(st, ", NPROC", RLIMIT_NPROC);
1693 #endif
1695 @@ -518,6 +518,12 @@
1696 print_rlimit(st, ", MEMLOCK", RLIMIT_MEMLOCK, true);
1697 #endif
1699 +#if defined(SOLARIS)
1700 + // maximum size of mapped address space of a process in bytes;
1701 + // if the limit is exceeded, mmap and brk fail
1702 + print_rlimit(st, ", VMEM", RLIMIT_VMEM, true);
1703 +#endif
1705 // MacOS; The maximum size (in bytes) to which a process's resident set size may grow.
1706 #if defined(__APPLE__)
1707 print_rlimit(st, ", RSS", RLIMIT_RSS, true);
1708 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/os/posix/os_posix.inline.hpp jdk23u-jdk-23-36/src/hotspot/os/posix/os_posix.inline.hpp
1709 --- jdk23u-jdk-23-36.orig/src/hotspot/os/posix/os_posix.inline.hpp 2024-08-07 00:08:22.000000000 +0200
1710 +++ jdk23u-jdk-23-36/src/hotspot/os/posix/os_posix.inline.hpp 2024-08-17 19:50:33.090061484 +0200
1711 @@ -34,8 +34,10 @@
1712 #include <sys/socket.h>
1713 #include <netdb.h>
1715 +#ifndef SOLARIS
1716 // Aix does not have NUMA support but need these for compilation.
1717 inline bool os::numa_has_group_homing() { AIX_ONLY(ShouldNotReachHere();) return false; }
1718 +#endif // !SOLARIS
1720 // Platform Mutex/Monitor implementation
1722 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/os/posix/vmError_posix.cpp jdk23u-jdk-23-36/src/hotspot/os/posix/vmError_posix.cpp
1723 --- jdk23u-jdk-23-36.orig/src/hotspot/os/posix/vmError_posix.cpp 2024-08-07 00:08:22.000000000 +0200
1724 +++ jdk23u-jdk-23-36/src/hotspot/os/posix/vmError_posix.cpp 2024-08-17 19:50:33.090696523 +0200
1725 @@ -41,6 +41,9 @@
1726 #include <sys/syscall.h>
1727 #include <unistd.h>
1728 #endif
1729 +#ifdef SOLARIS
1730 +#include <thread.h>
1731 +#endif
1732 #ifdef AIX
1733 #include <unistd.h>
1734 #endif
1735 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/os/solaris/attachListener_solaris.cpp jdk23u-jdk-23-36/src/hotspot/os/solaris/attachListener_solaris.cpp
1736 --- jdk23u-jdk-23-36.orig/src/hotspot/os/solaris/attachListener_solaris.cpp 1970-01-01 01:00:00.000000000 +0100
1737 +++ jdk23u-jdk-23-36/src/hotspot/os/solaris/attachListener_solaris.cpp 2024-08-17 19:50:33.141265699 +0200
1738 @@ -0,0 +1,719 @@
1740 + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
1741 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1743 + * This code is free software; you can redistribute it and/or modify it
1744 + * under the terms of the GNU General Public License version 2 only, as
1745 + * published by the Free Software Foundation.
1747 + * This code is distributed in the hope that it will be useful, but WITHOUT
1748 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1749 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1750 + * version 2 for more details (a copy is included in the LICENSE file that
1751 + * accompanied this code).
1753 + * You should have received a copy of the GNU General Public License version
1754 + * 2 along with this work; if not, write to the Free Software Foundation,
1755 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1757 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1758 + * or visit www.oracle.com if you need additional information or have any
1759 + * questions.
1761 + */
1763 +#include "precompiled.hpp"
1764 +#include "logging/log.hpp"
1765 +#include "runtime/interfaceSupport.inline.hpp"
1766 +#include "runtime/os.inline.hpp"
1767 +#include "services/attachListener.hpp"
1768 +#include "services/dtraceAttacher.hpp"
1769 +#include "utilities/vmError.hpp"
1771 +#include <door.h>
1772 +#include <limits.h>
1773 +#include <string.h>
1774 +#include <signal.h>
1775 +#include <sys/types.h>
1776 +#include <sys/socket.h>
1777 +#include <sys/stat.h>
1779 +// stropts.h uses STR in stream ioctl defines
1780 +#undef STR
1781 +#include <stropts.h>
1782 +#undef STR
1783 +#define STR(a) #a
1785 +// The attach mechanism on Solaris is implemented using the Doors IPC
1786 +// mechanism. The first tool to attempt to attach causes the attach
1787 +// listener thread to startup. This thread creats a door that is
1788 +// associated with a function that enqueues an operation to the attach
1789 +// listener. The door is attached to a file in the file system so that
1790 +// client (tools) can locate it. To enqueue an operation to the VM the
1791 +// client calls through the door which invokes the enqueue function in
1792 +// this process. The credentials of the client are checked and if the
1793 +// effective uid matches this process then the operation is enqueued.
1794 +// When an operation completes the attach listener is required to send the
1795 +// operation result and any result data to the client. In this implementation
1796 +// the result is returned via a UNIX domain socket. A pair of connected
1797 +// sockets (socketpair) is created in the enqueue function and the file
1798 +// descriptor for one of the sockets is returned to the client as the
1799 +// return from the door call. The other end is retained in this process.
1800 +// When the operation completes the result is sent to the client and
1801 +// the socket is closed.
1803 +// forward reference
1804 +class SolarisAttachOperation;
1806 +class SolarisAttachListener: AllStatic {
1807 + private:
1809 + // the path to which we attach the door file descriptor
1810 + static char _door_path[PATH_MAX+1];
1811 + static volatile bool _has_door_path;
1813 + // door descriptor returned by door_create
1814 + static int _door_descriptor;
1816 + static bool _atexit_registered;
1818 + // mutex to protect operation list
1819 + static pthread_mutex_t _mutex;
1821 + // semaphore to wakeup listener thread
1822 + static sema_t _wakeup;
1824 + static pthread_mutex_t* mutex() { return &_mutex; }
1825 + static sema_t* wakeup() { return &_wakeup; }
1827 + // enqueued operation list
1828 + static SolarisAttachOperation* _head;
1829 + static SolarisAttachOperation* _tail;
1831 + static SolarisAttachOperation* head() { return _head; }
1832 + static void set_head(SolarisAttachOperation* head) { _head = head; }
1834 + static SolarisAttachOperation* tail() { return _tail; }
1835 + static void set_tail(SolarisAttachOperation* tail) { _tail = tail; }
1837 + // create the door
1838 + static int create_door();
1840 + public:
1841 + enum {
1842 + ATTACH_PROTOCOL_VER = 1 // protocol version
1843 + };
1844 + enum {
1845 + ATTACH_ERROR_BADREQUEST = 100, // error codes
1846 + ATTACH_ERROR_BADVERSION = 101,
1847 + ATTACH_ERROR_RESOURCE = 102,
1848 + ATTACH_ERROR_INTERNAL = 103,
1849 + ATTACH_ERROR_DENIED = 104
1850 + };
1852 + static void set_door_path(char* path) {
1853 + if (path == NULL) {
1854 + _door_path[0] = '\0';
1855 + _has_door_path = false;
1856 + } else {
1857 + strncpy(_door_path, path, PATH_MAX);
1858 + _door_path[PATH_MAX] = '\0';
1859 + _has_door_path = true;
1863 + static void set_door_descriptor(int dd) { _door_descriptor = dd; }
1865 + // initialize the listener, returns 0 if okay
1866 + static int init();
1868 + static char* door_path() { return _door_path; }
1869 + static bool has_door_path() { return _has_door_path; }
1870 + static int door_descriptor() { return _door_descriptor; }
1872 + // enqueue an operation
1873 + static void enqueue(SolarisAttachOperation* op);
1875 + // dequeue an operation
1876 + static SolarisAttachOperation* dequeue();
1880 +// SolarisAttachOperation is an AttachOperation that additionally encapsulates
1881 +// a socket connection to the requesting client/tool. SolarisAttachOperation
1882 +// can additionally be held in a linked list.
1884 +class SolarisAttachOperation: public AttachOperation {
1885 + private:
1886 + friend class SolarisAttachListener;
1888 + // connection to client
1889 + int _socket;
1891 + // linked list support
1892 + SolarisAttachOperation* _next;
1894 + SolarisAttachOperation* next() { return _next; }
1895 + void set_next(SolarisAttachOperation* next) { _next = next; }
1897 + public:
1898 + void complete(jint res, bufferedStream* st);
1900 + void set_socket(int s) { _socket = s; }
1901 + int socket() const { return _socket; }
1903 + SolarisAttachOperation(char* name) : AttachOperation(name) {
1904 + set_socket(-1);
1905 + set_next(NULL);
1909 +// statics
1910 +char SolarisAttachListener::_door_path[PATH_MAX+1];
1911 +volatile bool SolarisAttachListener::_has_door_path;
1912 +int SolarisAttachListener::_door_descriptor = -1;
1913 +bool SolarisAttachListener::_atexit_registered = false;
1914 +pthread_mutex_t SolarisAttachListener::_mutex;
1915 +sema_t SolarisAttachListener::_wakeup;
1916 +SolarisAttachOperation* SolarisAttachListener::_head = NULL;
1917 +SolarisAttachOperation* SolarisAttachListener::_tail = NULL;
1919 +// Supporting class to help split a buffer into individual components
1920 +class ArgumentIterator : public StackObj {
1921 + private:
1922 + char* _pos;
1923 + char* _end;
1924 + public:
1925 + ArgumentIterator(char* arg_buffer, size_t arg_size) {
1926 + _pos = arg_buffer;
1927 + _end = _pos + arg_size - 1;
1929 + char* next() {
1930 + if (*_pos == '\0') {
1931 + // advance the iterator if possible (null arguments)
1932 + if (_pos < _end) {
1933 + _pos += 1;
1935 + return NULL;
1937 + char* res = _pos;
1938 + char* next_pos = strchr(_pos, '\0');
1939 + if (next_pos < _end) {
1940 + next_pos++;
1942 + _pos = next_pos;
1943 + return res;
1947 +// Calls from the door function to check that the client credentials
1948 +// match this process. Returns 0 if credentials okay, otherwise -1.
1949 +static int check_credentials() {
1950 + ucred_t *cred_info = NULL;
1951 + int ret = -1; // deny by default
1953 + // get client credentials
1954 + if (door_ucred(&cred_info) == -1) {
1955 + return -1; // unable to get them, deny
1958 + // get euid/egid from ucred_free
1959 + uid_t ucred_euid = ucred_geteuid(cred_info);
1960 + gid_t ucred_egid = ucred_getegid(cred_info);
1962 + // check that the effective uid/gid matches
1963 + if (os::Posix::matches_effective_uid_and_gid_or_root(ucred_euid, ucred_egid)) {
1964 + ret = 0; // allow
1967 + ucred_free(cred_info);
1968 + return ret;
1972 +// Parses the argument buffer to create an AttachOperation that we should
1973 +// enqueue to the attach listener.
1974 +// The buffer is expected to be formatted as follows:
1975 +// <ver>0<cmd>0<arg>0<arg>0<arg>0
1976 +// where <ver> is the version number (must be "1"), <cmd> is the command
1977 +// name ("load, "datadump", ...) and <arg> is an argument.
1979 +static SolarisAttachOperation* create_operation(char* argp, size_t arg_size, int* err) {
1980 + // assume bad request until parsed
1981 + *err = SolarisAttachListener::ATTACH_ERROR_BADREQUEST;
1983 + if (arg_size < 2 || argp[arg_size-1] != '\0') {
1984 + return NULL; // no ver or not null terminated
1987 + // Use supporting class to iterate over the buffer
1988 + ArgumentIterator args(argp, arg_size);
1990 + // First check the protocol version
1991 + char* ver = args.next();
1992 + if (ver == NULL) {
1993 + return NULL;
1995 + if (atoi(ver) != SolarisAttachListener::ATTACH_PROTOCOL_VER) {
1996 + *err = SolarisAttachListener::ATTACH_ERROR_BADVERSION;
1997 + return NULL;
2000 + // Get command name and create the operation
2001 + char* name = args.next();
2002 + if (name == NULL || strlen(name) > AttachOperation::name_length_max) {
2003 + return NULL;
2005 + SolarisAttachOperation* op = new SolarisAttachOperation(name);
2007 + // Iterate over the arguments
2008 + for (int i=0; i<AttachOperation::arg_count_max; i++) {
2009 + char* arg = args.next();
2010 + if (arg == NULL) {
2011 + op->set_arg(i, NULL);
2012 + } else {
2013 + if (strlen(arg) > AttachOperation::arg_length_max) {
2014 + delete op;
2015 + return NULL;
2017 + op->set_arg(i, arg);
2021 + // return operation
2022 + *err = 0;
2023 + return op;
2026 +// This is door function which the client executes via a door_call.
2027 +extern "C" {
2028 + static void enqueue_proc(void* cookie, char* argp, size_t arg_size,
2029 + door_desc_t* dt, uint_t n_desc)
2031 + int return_fd = -1;
2032 + SolarisAttachOperation* op = NULL;
2034 + // wait up to 10 seconds for listener to be up and running
2035 + jint res = 0;
2036 + int sleep_count = 0;
2037 + while (!AttachListener::is_initialized()) {
2038 + sleep(1); // 1 second
2039 + sleep_count++;
2040 + if (sleep_count > 10) { // try for 10 seconds
2041 + debug_only(warning("door_call when not enabled"));
2042 + res = (jint)SolarisAttachListener::ATTACH_ERROR_INTERNAL;
2043 + break;
2047 + // check client credentials
2048 + if (res == 0) {
2049 + if (check_credentials() != 0) {
2050 + res = (jint)SolarisAttachListener::ATTACH_ERROR_DENIED;
2054 + // if we are stopped at ShowMessageBoxOnError then maybe we can
2055 + // load a diagnostic library
2056 + if (res == 0 && VMError::is_error_reported()) {
2057 + if (ShowMessageBoxOnError) {
2058 + // TBD - support loading of diagnostic library here
2061 + // can't enqueue operation after fatal error
2062 + res = (jint)SolarisAttachListener::ATTACH_ERROR_RESOURCE;
2065 + // create the operation
2066 + if (res == 0) {
2067 + int err;
2068 + op = create_operation(argp, arg_size, &err);
2069 + res = (op == NULL) ? (jint)err : 0;
2072 + // create a pair of connected sockets. Store the file descriptor
2073 + // for one end in the operation and enqueue the operation. The
2074 + // file descriptor for the other end wil be returned to the client.
2075 + if (res == 0) {
2076 + int s[2];
2077 + if (socketpair(PF_UNIX, SOCK_STREAM, 0, s) < 0) {
2078 + delete op;
2079 + res = (jint)SolarisAttachListener::ATTACH_ERROR_RESOURCE;
2080 + } else {
2081 + op->set_socket(s[0]);
2082 + return_fd = s[1];
2083 + SolarisAttachListener::enqueue(op);
2087 + // Return 0 (success) + file descriptor, or non-0 (error)
2088 + if (res == 0) {
2089 + door_desc_t desc;
2090 + // DOOR_RELEASE flag makes sure fd is closed after passing it to
2091 + // the client. See door_return(3DOOR) man page.
2092 + desc.d_attributes = DOOR_DESCRIPTOR | DOOR_RELEASE;
2093 + desc.d_data.d_desc.d_descriptor = return_fd;
2094 + door_return((char*)&res, sizeof(res), &desc, 1);
2095 + } else {
2096 + door_return((char*)&res, sizeof(res), NULL, 0);
2101 +// atexit hook to detach the door and remove the file
2102 +extern "C" {
2103 + static void listener_cleanup() {
2104 + int dd = SolarisAttachListener::door_descriptor();
2105 + if (dd >= 0) {
2106 + SolarisAttachListener::set_door_descriptor(-1);
2107 + ::close(dd);
2109 + if (SolarisAttachListener::has_door_path()) {
2110 + char* path = SolarisAttachListener::door_path();
2111 + ::fdetach(path);
2112 + ::unlink(path);
2113 + SolarisAttachListener::set_door_path(NULL);
2118 +// Create the door
2119 +int SolarisAttachListener::create_door() {
2120 + char door_path[PATH_MAX];
2121 + char initial_path[PATH_MAX];
2122 + int fd, res;
2124 + // register function to cleanup
2125 + if (!_atexit_registered) {
2126 + _atexit_registered = true;
2127 + ::atexit(listener_cleanup);
2130 + // create the door descriptor
2131 + int dd = ::door_create(enqueue_proc, NULL, 0);
2132 + if (dd < 0) {
2133 + return -1;
2136 + int n = snprintf(door_path, PATH_MAX, "%s/.java_pid%d",
2137 + os::get_temp_directory(), os::current_process_id());
2138 + if (n < (int)PATH_MAX) {
2139 + snprintf(initial_path, PATH_MAX, "%s.tmp", door_path);
2141 + if (n >= (int)PATH_MAX) {
2142 + return -1;
2144 + RESTARTABLE(::creat(initial_path, S_IRUSR | S_IWUSR), fd);
2145 + if (fd == -1) {
2146 + log_debug(attach)("attempt to create door file %s failed (%d)", initial_path, errno);
2147 + ::door_revoke(dd);
2148 + return -1;
2150 + assert(fd >= 0, "bad file descriptor");
2151 + ::close(fd);
2153 + // attach the door descriptor to the file
2154 + if ((res = ::fattach(dd, initial_path)) == -1) {
2155 + // if busy then detach and try again
2156 + if (errno == EBUSY) {
2157 + ::fdetach(initial_path);
2158 + res = ::fattach(dd, initial_path);
2160 + if (res == -1) {
2161 + log_debug(attach)("unable to create door - fattach failed (%d)", errno);
2162 + ::door_revoke(dd);
2163 + dd = -1;
2167 + // rename file so that clients can attach
2168 + if (dd >= 0) {
2169 + if (::rename(initial_path, door_path) == -1) {
2170 + ::close(dd);
2171 + ::fdetach(initial_path);
2172 + log_debug(attach)("unable to create door - rename %s to %s failed (%d)", initial_path, door_path, errno);
2173 + dd = -1;
2176 + if (dd >= 0) {
2177 + set_door_descriptor(dd);
2178 + set_door_path(door_path);
2179 + log_trace(attach)("door file %s created succesfully", door_path);
2180 + } else {
2181 + // unable to create door, attach it to file, or rename file into place
2182 + ::unlink(initial_path);
2183 + return -1;
2186 + return 0;
2189 +// Initialization - create the door, locks, and other initialization
2190 +int SolarisAttachListener::init() {
2191 + if (create_door()) {
2192 + return -1;
2195 + int status = pthread_mutex_init(&_mutex, NULL);
2196 + assert_status(status==0, status, "mutex_init");
2198 + status = ::sema_init(&_wakeup, 0, NULL, NULL);
2199 + assert_status(status==0, status, "sema_init");
2201 + set_head(NULL);
2202 + set_tail(NULL);
2204 + return 0;
2207 +// Dequeue an operation
2208 +SolarisAttachOperation* SolarisAttachListener::dequeue() {
2209 + for (;;) {
2210 + int res;
2212 + // wait for somebody to enqueue something
2213 + while ((res = ::sema_wait(wakeup())) == EINTR)
2215 + if (res) {
2216 + warning("sema_wait failed: %s", os::strerror(res));
2217 + return NULL;
2220 + // lock the list
2221 + res = pthread_mutex_lock(mutex());
2222 + assert(res == 0, "mutex_lock failed");
2224 + // remove the head of the list
2225 + SolarisAttachOperation* op = head();
2226 + if (op != NULL) {
2227 + set_head(op->next());
2228 + if (head() == NULL) {
2229 + set_tail(NULL);
2233 + // unlock
2234 + pthread_mutex_unlock(mutex());
2236 + // if we got an operation when return it.
2237 + if (op != NULL) {
2238 + return op;
2243 +// Enqueue an operation
2244 +void SolarisAttachListener::enqueue(SolarisAttachOperation* op) {
2245 + // lock list
2246 + int res = pthread_mutex_lock(mutex());
2247 + assert(res == 0, "mutex_lock failed");
2249 + // enqueue at tail
2250 + op->set_next(NULL);
2251 + if (head() == NULL) {
2252 + set_head(op);
2253 + } else {
2254 + tail()->set_next(op);
2256 + set_tail(op);
2258 + // wakeup the attach listener
2259 + RESTARTABLE(::sema_post(wakeup()), res);
2260 + assert(res == 0, "sema_post failed");
2262 + // unlock
2263 + pthread_mutex_unlock(mutex());
2267 +// support function - writes the (entire) buffer to a socket
2268 +static int write_fully(int s, char* buf, int len) {
2269 + do {
2270 + int n = ::write(s, buf, len);
2271 + if (n == -1) {
2272 + if (errno != EINTR) return -1;
2273 + } else {
2274 + buf += n;
2275 + len -= n;
2278 + while (len > 0);
2279 + return 0;
2282 +// Complete an operation by sending the operation result and any result
2283 +// output to the client. At this time the socket is in blocking mode so
2284 +// potentially we can block if there is a lot of data and the client is
2285 +// non-responsive. For most operations this is a non-issue because the
2286 +// default send buffer is sufficient to buffer everything. In the future
2287 +// if there are operations that involves a very big reply then it the
2288 +// socket could be made non-blocking and a timeout could be used.
2290 +void SolarisAttachOperation::complete(jint res, bufferedStream* st) {
2291 + if (this->socket() >= 0) {
2292 + JavaThread* thread = JavaThread::current();
2293 + ThreadBlockInVM tbivm(thread);
2295 + // write operation result
2296 + char msg[32];
2297 + sprintf(msg, "%d\n", res);
2298 + int rc = write_fully(this->socket(), msg, strlen(msg));
2300 + // write any result data
2301 + if (rc == 0) {
2302 + write_fully(this->socket(), (char*) st->base(), st->size());
2303 + ::shutdown(this->socket(), 2);
2306 + // done
2307 + ::close(this->socket());
2309 + delete this;
2313 +// AttachListener functions
2315 +AttachOperation* AttachListener::dequeue() {
2316 + JavaThread* thread = JavaThread::current();
2317 + ThreadBlockInVM tbivm(thread);
2319 + AttachOperation* op = SolarisAttachListener::dequeue();
2321 + return op;
2325 +// Performs initialization at vm startup
2326 +// For Solaris we remove any stale .java_pid file which could cause
2327 +// an attaching process to think we are ready to receive a door_call
2328 +// before we are properly initialized
2330 +void AttachListener::vm_start() {
2331 + char fn[PATH_MAX+1];
2332 + struct stat64 st;
2333 + int ret;
2335 + int n = snprintf(fn, sizeof(fn), "%s/.java_pid%d",
2336 + os::get_temp_directory(), os::current_process_id());
2337 + assert(n < sizeof(fn), "java_pid file name buffer overflow");
2339 + RESTARTABLE(::stat64(fn, &st), ret);
2340 + if (ret == 0) {
2341 + ret = ::unlink(fn);
2342 + if (ret == -1) {
2343 + log_debug(attach)("Failed to remove stale attach pid file at %s", fn);
2348 +int AttachListener::pd_init() {
2349 + JavaThread* thread = JavaThread::current();
2350 + ThreadBlockInVM tbivm(thread);
2352 + int ret_code = SolarisAttachListener::init();
2354 + return ret_code;
2357 +bool AttachListener::check_socket_file() {
2358 + int ret;
2359 + struct stat64 st;
2360 + ret = stat64(SolarisAttachListener::door_path(), &st);
2361 + if (ret == -1) { // need to restart attach listener.
2362 + log_debug(attach)("Door file %s does not exist - Restart Attach Listener",
2363 + SolarisAttachListener::door_path());
2365 + listener_cleanup();
2367 + // wait to terminate current attach listener instance...
2368 + while (AttachListener::transit_state(AL_INITIALIZING,
2369 + AL_NOT_INITIALIZED) != AL_NOT_INITIALIZED) {
2370 + os::naked_yield();
2372 + return is_init_trigger();
2374 + return false;
2377 +// Attach Listener is started lazily except in the case when
2378 +// +ReduseSignalUsage is used
2379 +bool AttachListener::init_at_startup() {
2380 + if (ReduceSignalUsage) {
2381 + return true;
2382 + } else {
2383 + return false;
2387 +// If the file .attach_pid<pid> exists in the working directory
2388 +// or /tmp then this is the trigger to start the attach mechanism
2389 +bool AttachListener::is_init_trigger() {
2390 + if (init_at_startup() || is_initialized()) {
2391 + return false; // initialized at startup or already initialized
2393 + char fn[PATH_MAX + 1];
2394 + int ret;
2395 + struct stat64 st;
2396 + sprintf(fn, ".attach_pid%d", os::current_process_id());
2397 + RESTARTABLE(::stat64(fn, &st), ret);
2398 + if (ret == -1) {
2399 + log_trace(attach)("Failed to find attach file: %s, trying alternate", fn);
2400 + snprintf(fn, sizeof(fn), "%s/.attach_pid%d",
2401 + os::get_temp_directory(), os::current_process_id());
2402 + RESTARTABLE(::stat64(fn, &st), ret);
2403 + if (ret == -1) {
2404 + log_debug(attach)("Failed to find attach file: %s", fn);
2407 + if (ret == 0) {
2408 + // simple check to avoid starting the attach mechanism when
2409 + // a bogus non-root user creates the file
2410 + if (os::Posix::matches_effective_uid_or_root(st.st_uid)) {
2411 + init();
2412 + log_trace(attach)("Attach triggered by %s", fn);
2413 + return true;
2414 + } else {
2415 + log_debug(attach)("File %s has wrong user id %d (vs %d). Attach is not triggered", fn, st.st_uid, geteuid());
2418 + return false;
2421 +// if VM aborts then remove listener
2422 +void AttachListener::abort() {
2423 + listener_cleanup();
2426 +void AttachListener::pd_data_dump() {
2427 + os::signal_notify(SIGQUIT);
2430 +static jint enable_dprobes(AttachOperation* op, outputStream* out) {
2431 + const char* probe = op->arg(0);
2432 + if (probe == NULL || probe[0] == '\0') {
2433 + out->print_cr("No probe specified");
2434 + return JNI_ERR;
2435 + } else {
2436 + char *end;
2437 + long val = strtol(probe, &end, 10);
2438 + if (end == probe || val < 0 || val > INT_MAX) {
2439 + out->print_cr("invalid probe type");
2440 + return JNI_ERR;
2441 + } else {
2442 + int probe_typess = (int) val;
2443 + DTrace::enable_dprobes(probe_typess);
2444 + return JNI_OK;
2449 +// platform specific operations table
2450 +static AttachOperationFunctionInfo funcs[] = {
2451 + { "enabledprobes", enable_dprobes },
2452 + { NULL, NULL }
2455 +void AttachListener::pd_detachall() {
2456 + DTrace::detach_all_clients();
2458 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/os/solaris/c1_globals_solaris.hpp jdk23u-jdk-23-36/src/hotspot/os/solaris/c1_globals_solaris.hpp
2459 --- jdk23u-jdk-23-36.orig/src/hotspot/os/solaris/c1_globals_solaris.hpp 1970-01-01 01:00:00.000000000 +0100
2460 +++ jdk23u-jdk-23-36/src/hotspot/os/solaris/c1_globals_solaris.hpp 2024-08-17 19:50:33.141524608 +0200
2461 @@ -0,0 +1,36 @@
2463 + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
2464 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
2466 + * This code is free software; you can redistribute it and/or modify it
2467 + * under the terms of the GNU General Public License version 2 only, as
2468 + * published by the Free Software Foundation.
2470 + * This code is distributed in the hope that it will be useful, but WITHOUT
2471 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
2472 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
2473 + * version 2 for more details (a copy is included in the LICENSE file that
2474 + * accompanied this code).
2476 + * You should have received a copy of the GNU General Public License version
2477 + * 2 along with this work; if not, write to the Free Software Foundation,
2478 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2480 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2481 + * or visit www.oracle.com if you need additional information or have any
2482 + * questions.
2484 + */
2486 +#ifndef OS_SOLARIS_C1_GLOBALS_SOLARIS_HPP
2487 +#define OS_SOLARIS_C1_GLOBALS_SOLARIS_HPP
2489 +#include "utilities/globalDefinitions.hpp"
2490 +#include "utilities/macros.hpp"
2493 +// Sets the default values for operating system dependent flags used by the
2494 +// client compiler. (see c1_globals.hpp)
2497 +#endif // OS_SOLARIS_C1_GLOBALS_SOLARIS_HPP
2498 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/os/solaris/c2_globals_solaris.hpp jdk23u-jdk-23-36/src/hotspot/os/solaris/c2_globals_solaris.hpp
2499 --- jdk23u-jdk-23-36.orig/src/hotspot/os/solaris/c2_globals_solaris.hpp 1970-01-01 01:00:00.000000000 +0100
2500 +++ jdk23u-jdk-23-36/src/hotspot/os/solaris/c2_globals_solaris.hpp 2024-08-17 19:50:33.141795200 +0200
2501 @@ -0,0 +1,36 @@
2503 + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
2504 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
2506 + * This code is free software; you can redistribute it and/or modify it
2507 + * under the terms of the GNU General Public License version 2 only, as
2508 + * published by the Free Software Foundation.
2510 + * This code is distributed in the hope that it will be useful, but WITHOUT
2511 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
2512 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
2513 + * version 2 for more details (a copy is included in the LICENSE file that
2514 + * accompanied this code).
2516 + * You should have received a copy of the GNU General Public License version
2517 + * 2 along with this work; if not, write to the Free Software Foundation,
2518 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2520 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2521 + * or visit www.oracle.com if you need additional information or have any
2522 + * questions.
2524 + */
2526 +#ifndef OS_SOLARIS_C2_GLOBALS_SOLARIS_HPP
2527 +#define OS_SOLARIS_C2_GLOBALS_SOLARIS_HPP
2529 +#include "utilities/globalDefinitions.hpp"
2530 +#include "utilities/macros.hpp"
2533 +// Sets the default values for operating system dependent flags used by the
2534 +// server compiler. (see c2_globals.hpp)
2537 +#endif // OS_SOLARIS_C2_GLOBALS_SOLARIS_HPP
2538 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/os/solaris/decoder_solaris.cpp jdk23u-jdk-23-36/src/hotspot/os/solaris/decoder_solaris.cpp
2539 --- jdk23u-jdk-23-36.orig/src/hotspot/os/solaris/decoder_solaris.cpp 1970-01-01 01:00:00.000000000 +0100
2540 +++ jdk23u-jdk-23-36/src/hotspot/os/solaris/decoder_solaris.cpp 2024-08-17 19:50:33.142031385 +0200
2541 @@ -0,0 +1,32 @@
2543 + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
2544 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
2546 + * This code is free software; you can redistribute it and/or modify it
2547 + * under the terms of the GNU General Public License version 2 only, as
2548 + * published by the Free Software Foundation.
2550 + * This code is distributed in the hope that it will be useful, but WITHOUT
2551 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
2552 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
2553 + * version 2 for more details (a copy is included in the LICENSE file that
2554 + * accompanied this code).
2556 + * You should have received a copy of the GNU General Public License version
2557 + * 2 along with this work; if not, write to the Free Software Foundation,
2558 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2560 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2561 + * or visit www.oracle.com if you need additional information or have any
2562 + * questions.
2564 + */
2566 +#include "utilities/decoder_elf.hpp"
2568 +#include <demangle.h>
2570 +bool ElfDecoder::demangle(const char* symbol, char *buf, int buflen) {
2571 + return !cplus_demangle(symbol, buf, (size_t)buflen);
2574 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/os/solaris/dtrace/jhelper.d jdk23u-jdk-23-36/src/hotspot/os/solaris/dtrace/jhelper.d
2575 --- jdk23u-jdk-23-36.orig/src/hotspot/os/solaris/dtrace/jhelper.d 1970-01-01 01:00:00.000000000 +0100
2576 +++ jdk23u-jdk-23-36/src/hotspot/os/solaris/dtrace/jhelper.d 2024-08-17 19:50:33.142535941 +0200
2577 @@ -0,0 +1,540 @@
2579 + * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
2580 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
2582 + * This code is free software; you can redistribute it and/or modify it
2583 + * under the terms of the GNU General Public License version 2 only, as
2584 + * published by the Free Software Foundation.
2586 + * This code is distributed in the hope that it will be useful, but WITHOUT
2587 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
2588 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
2589 + * version 2 for more details (a copy is included in the LICENSE file that
2590 + * accompanied this code).
2592 + * You should have received a copy of the GNU General Public License version
2593 + * 2 along with this work; if not, write to the Free Software Foundation,
2594 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2596 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2597 + * or visit www.oracle.com if you need additional information or have any
2598 + * questions.
2600 + */
2602 +/* This file is auto-generated */
2603 +#include "JvmOffsetsIndex.h"
2605 +#define DEBUG
2607 +#ifdef DEBUG
2608 +#define MARK_LINE this->line = __LINE__
2609 +#else
2610 +#define MARK_LINE
2611 +#endif
2613 +#ifdef _LP64
2614 +#define STACK_BIAS 0x7ff
2615 +#define pointer uint64_t
2616 +#else
2617 +#define STACK_BIAS 0
2618 +#define pointer uint32_t
2619 +#endif
2621 +extern pointer __JvmOffsets;
2623 +/* GrowableArray<CodeHeaps*>* */
2624 +extern pointer __1cJCodeCacheG_heaps_;
2626 +extern pointer __1cIUniverseO_collectedHeap_;
2628 +extern pointer __1cHnmethodG__vtbl_;
2629 +extern pointer __1cGMethodG__vtbl_;
2630 +extern pointer __1cKBufferBlobG__vtbl_;
2632 +#define copyin_ptr(ADDR) *(pointer*) copyin((pointer) (ADDR), sizeof(pointer))
2633 +#define copyin_uchar(ADDR) *(uchar_t*) copyin((pointer) (ADDR), sizeof(uchar_t))
2634 +#define copyin_uint16(ADDR) *(uint16_t*) copyin((pointer) (ADDR), sizeof(uint16_t))
2635 +#define copyin_uint32(ADDR) *(uint32_t*) copyin((pointer) (ADDR), sizeof(uint32_t))
2636 +#define copyin_int32(ADDR) *(int32_t*) copyin((pointer) (ADDR), sizeof(int32_t))
2637 +#define copyin_uint8(ADDR) *(uint8_t*) copyin((pointer) (ADDR), sizeof(uint8_t))
2639 +#define copyin_offset(JVM_CONST) JVM_CONST = \
2640 + copyin_int32(JvmOffsetsPtr + IDX_##JVM_CONST * sizeof(int32_t))
2642 +int init_done;
2644 +dtrace:helper:ustack:
2646 + MARK_LINE;
2647 + this->done = 0;
2648 + /*
2649 + * TBD:
2650 + * Here we initialize init_done, otherwise jhelper does not work.
2651 + * Therefore, copyin_offset() statements work multiple times now.
2652 + * There is a hope we could avoid it in the future, and so,
2653 + * this initialization can be removed.
2654 + */
2655 + init_done = 0;
2656 + this->error = (char *) NULL;
2657 + this->result = (char *) NULL;
2658 + this->isMethod = 0;
2659 + this->codecache = 0;
2660 + this->klass = (pointer) NULL;
2661 + this->vtbl = (pointer) NULL;
2662 + this->suffix = '\0';
2665 +dtrace:helper:ustack:
2667 + MARK_LINE;
2668 + /* Initialization of JvmOffsets constants */
2669 + JvmOffsetsPtr = (pointer) &``__JvmOffsets;
2672 +dtrace:helper:ustack:
2673 +/!init_done && !this->done/
2675 + MARK_LINE;
2677 + copyin_offset(POINTER_SIZE);
2678 + copyin_offset(COMPILER);
2679 + copyin_offset(OFFSET_CollectedHeap_reserved);
2680 + copyin_offset(OFFSET_MemRegion_start);
2681 + copyin_offset(OFFSET_MemRegion_word_size);
2682 + copyin_offset(SIZE_HeapWord);
2684 + copyin_offset(OFFSET_interpreter_frame_method);
2685 + copyin_offset(OFFSET_Klass_name);
2686 + copyin_offset(OFFSET_ConstantPool_pool_holder);
2688 + copyin_offset(OFFSET_HeapBlockHeader_used);
2689 + copyin_offset(OFFSET_oopDesc_metadata);
2691 + copyin_offset(OFFSET_Symbol_length);
2692 + copyin_offset(OFFSET_Symbol_body);
2694 + copyin_offset(OFFSET_Method_constMethod);
2695 + copyin_offset(OFFSET_ConstMethod_constants);
2696 + copyin_offset(OFFSET_ConstMethod_name_index);
2697 + copyin_offset(OFFSET_ConstMethod_signature_index);
2699 + copyin_offset(OFFSET_CodeHeap_memory);
2700 + copyin_offset(OFFSET_CodeHeap_segmap);
2701 + copyin_offset(OFFSET_CodeHeap_log2_segment_size);
2703 + copyin_offset(OFFSET_GrowableArray_CodeHeap_data);
2704 + copyin_offset(OFFSET_GrowableArray_CodeHeap_len);
2706 + copyin_offset(OFFSET_VirtualSpace_low);
2707 + copyin_offset(OFFSET_VirtualSpace_high);
2709 + copyin_offset(OFFSET_CodeBlob_name);
2711 + copyin_offset(OFFSET_nmethod_method);
2712 + copyin_offset(SIZE_HeapBlockHeader);
2713 + copyin_offset(SIZE_oopDesc);
2714 + copyin_offset(SIZE_ConstantPool);
2716 + copyin_offset(OFFSET_NarrowPtrStruct_base);
2717 + copyin_offset(OFFSET_NarrowPtrStruct_shift);
2719 + /*
2720 + * The PC to translate is in arg0.
2721 + */
2722 + this->pc = arg0;
2724 +#if defined(__i386) || defined(__amd64)
2725 + this->methodPtr = copyin_ptr(arg1 + OFFSET_interpreter_frame_method);
2726 +#else
2727 +#error "Don't know architecture"
2728 +#endif
2730 + /* Read address of GrowableArray<CodeHeaps*> */
2731 + // this->code_heaps_address = copyin_ptr(&``__1cJCodeCacheG_heaps_);
2732 + this->code_heaps_address = * ( uint64_t * ) copyin ( ( uint64_t ) ( &``__1cJCodeCacheG_heaps_ ) , sizeof ( uint64_t ) );
2734 + /* Read address of _data array field in GrowableArray */
2735 + this->code_heaps_array_address = copyin_ptr(this->code_heaps_address + OFFSET_GrowableArray_CodeHeap_data);
2736 + this->number_of_heaps = copyin_uint32(this->code_heaps_address + OFFSET_GrowableArray_CodeHeap_len);
2738 + this->Method_vtbl = (pointer) &``__1cGMethodG__vtbl_;
2740 + /*
2741 + * Get Java heap bounds
2742 + */
2743 + // this->Universe_collectedHeap = copyin_ptr(&``__1cIUniverseO_collectedHeap_);
2744 + this->Universe_collectedHeap = * ( uint64_t * ) copyin ( ( uint64_t ) ( &``__1cIUniverseO_collectedHeap_ ) , sizeof ( uint64_t ) );
2746 + this->heap_start = copyin_ptr(this->Universe_collectedHeap +
2747 + OFFSET_CollectedHeap_reserved +
2748 + OFFSET_MemRegion_start);
2749 + this->heap_size = SIZE_HeapWord *
2750 + copyin_ptr(this->Universe_collectedHeap +
2751 + OFFSET_CollectedHeap_reserved +
2752 + OFFSET_MemRegion_word_size
2753 + );
2754 + this->heap_end = this->heap_start + this->heap_size;
2758 + * IMPORTANT: At the moment the ustack helper supports up to 5 code heaps in
2759 + * the code cache. If more code heaps are added the following probes have to
2760 + * be extended. This is done by simply adding a probe to get the heap bounds
2761 + * and another probe to set the code heap address of the newly created heap.
2762 + */
2765 + * ----- BEGIN: Get bounds of code heaps -----
2766 + */
2767 +dtrace:helper:ustack:
2768 +/init_done < 1 && this->number_of_heaps >= 1 && !this->done/
2770 + MARK_LINE;
2771 + /* CodeHeap 1 */
2772 + init_done = 1;
2773 + this->code_heap1_address = copyin_ptr(this->code_heaps_array_address);
2774 + this->code_heap1_low = copyin_ptr(this->code_heap1_address +
2775 + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low);
2776 + this->code_heap1_high = copyin_ptr(this->code_heap1_address +
2777 + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_high);
2780 +dtrace:helper:ustack:
2781 +/init_done < 2 && this->number_of_heaps >= 2 && !this->done/
2783 + MARK_LINE;
2784 + /* CodeHeap 2 */
2785 + init_done = 2;
2786 + this->code_heaps_array_address = this->code_heaps_array_address + POINTER_SIZE;
2787 + this->code_heap2_address = copyin_ptr(this->code_heaps_array_address);
2788 + this->code_heap2_low = copyin_ptr(this->code_heap2_address +
2789 + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low);
2790 + this->code_heap2_high = copyin_ptr(this->code_heap2_address +
2791 + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_high);
2794 +dtrace:helper:ustack:
2795 +/init_done < 3 && this->number_of_heaps >= 3 && !this->done/
2797 + /* CodeHeap 3 */
2798 + init_done = 3;
2799 + this->code_heaps_array_address = this->code_heaps_array_address + POINTER_SIZE;
2800 + this->code_heap3_address = copyin_ptr(this->code_heaps_array_address);
2801 + this->code_heap3_low = copyin_ptr(this->code_heap3_address +
2802 + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low);
2803 + this->code_heap3_high = copyin_ptr(this->code_heap3_address +
2804 + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_high);
2807 +dtrace:helper:ustack:
2808 +/init_done < 4 && this->number_of_heaps >= 4 && !this->done/
2810 + /* CodeHeap 4 */
2811 + init_done = 4;
2812 + this->code_heaps_array_address = this->code_heaps_array_address + POINTER_SIZE;
2813 + this->code_heap4_address = copyin_ptr(this->code_heaps_array_address);
2814 + this->code_heap4_low = copyin_ptr(this->code_heap4_address +
2815 + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low);
2816 + this->code_heap4_high = copyin_ptr(this->code_heap4_address +
2817 + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_high);
2820 +dtrace:helper:ustack:
2821 +/init_done < 5 && this->number_of_heaps >= 5 && !this->done/
2823 + /* CodeHeap 5 */
2824 + init_done = 5;
2825 + this->code_heaps_array_address = this->code_heaps_array_address + POINTER_SIZE;
2826 + this->code_heap5_address = copyin_ptr(this->code_heaps_array_address);
2827 + this->code_heap5_low = copyin_ptr(this->code_heap5_address +
2828 + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low);
2829 + this->code_heap5_high = copyin_ptr(this->code_heap5_address +
2830 + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_high);
2833 + * ----- END: Get bounds of code heaps -----
2834 + */
2837 + * ----- BEGIN: Get address of the code heap pc points to -----
2838 + */
2839 +dtrace:helper:ustack:
2840 +/!this->done && this->number_of_heaps >= 1 && this->code_heap1_low <= this->pc && this->pc < this->code_heap1_high/
2842 + MARK_LINE;
2843 + this->codecache = 1;
2844 + this->code_heap_address = this->code_heap1_address;
2847 +dtrace:helper:ustack:
2848 +/!this->done && this->number_of_heaps >= 2 && this->code_heap2_low <= this->pc && this->pc < this->code_heap2_high/
2850 + MARK_LINE;
2851 + this->codecache = 1;
2852 + this->code_heap_address = this->code_heap2_address;
2855 +dtrace:helper:ustack:
2856 +/!this->done && this->number_of_heaps >= 3 && this->code_heap3_low <= this->pc && this->pc < this->code_heap3_high/
2858 + MARK_LINE;
2859 + this->codecache = 1;
2860 + this->code_heap_address = this->code_heap3_address;
2863 +dtrace:helper:ustack:
2864 +/!this->done && this->number_of_heaps >= 4 && this->code_heap4_low <= this->pc && this->pc < this->code_heap4_high/
2866 + MARK_LINE;
2867 + this->codecache = 1;
2868 + this->code_heap_address = this->code_heap4_address;
2871 +dtrace:helper:ustack:
2872 +/!this->done && this->number_of_heaps >= 5 && this->code_heap5_low <= this->pc && this->pc < this->code_heap5_high/
2874 + MARK_LINE;
2875 + this->codecache = 1;
2876 + this->code_heap_address = this->code_heap5_address;
2879 + * ----- END: Get address of the code heap pc points to -----
2880 + */
2882 +dtrace:helper:ustack:
2883 +/!this->done && this->codecache/
2885 + MARK_LINE;
2886 + /*
2887 + * Get code heap configuration
2888 + */
2889 + this->code_heap_low = copyin_ptr(this->code_heap_address +
2890 + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low);
2891 + this->code_heap_segmap_low = copyin_ptr(this->code_heap_address +
2892 + OFFSET_CodeHeap_segmap + OFFSET_VirtualSpace_low);
2893 + this->code_heap_log2_segment_size = copyin_uint32(
2894 + this->code_heap_address + OFFSET_CodeHeap_log2_segment_size);
2896 + /*
2897 + * Find start
2898 + */
2899 + this->segment = (this->pc - this->code_heap_low) >>
2900 + this->code_heap_log2_segment_size;
2901 + this->block = this->code_heap_segmap_low;
2902 + this->tag = copyin_uchar(this->block + this->segment);
2905 +dtrace:helper:ustack:
2906 +/!this->done && this->codecache && this->tag > 0/
2908 + MARK_LINE;
2909 + this->tag = copyin_uchar(this->block + this->segment);
2910 + this->segment = this->segment - this->tag;
2913 +dtrace:helper:ustack:
2914 +/!this->done && this->codecache && this->tag > 0/
2916 + MARK_LINE;
2917 + this->tag = copyin_uchar(this->block + this->segment);
2918 + this->segment = this->segment - this->tag;
2921 +dtrace:helper:ustack:
2922 +/!this->done && this->codecache && this->tag > 0/
2924 + MARK_LINE;
2925 + this->tag = copyin_uchar(this->block + this->segment);
2926 + this->segment = this->segment - this->tag;
2929 +dtrace:helper:ustack:
2930 +/!this->done && this->codecache && this->tag > 0/
2932 + MARK_LINE;
2933 + this->tag = copyin_uchar(this->block + this->segment);
2934 + this->segment = this->segment - this->tag;
2937 +dtrace:helper:ustack:
2938 +/!this->done && this->codecache && this->tag > 0/
2940 + MARK_LINE;
2941 + this->tag = copyin_uchar(this->block + this->segment);
2942 + this->segment = this->segment - this->tag;
2945 +dtrace:helper:ustack:
2946 +/!this->done && this->codecache && this->tag > 0/
2948 + MARK_LINE;
2949 + this->error = "<couldn't find start>";
2950 + this->done = 1;
2953 +dtrace:helper:ustack:
2954 +/!this->done && this->codecache/
2956 + MARK_LINE;
2957 + this->block = this->code_heap_low +
2958 + (this->segment << this->code_heap_log2_segment_size);
2959 + this->used = copyin_uint32(this->block + OFFSET_HeapBlockHeader_used);
2962 +dtrace:helper:ustack:
2963 +/!this->done && this->codecache && !this->used/
2965 + MARK_LINE;
2966 + this->error = "<block not in use>";
2967 + this->done = 1;
2970 +dtrace:helper:ustack:
2971 +/!this->done && this->codecache/
2973 + MARK_LINE;
2974 + this->start = this->block + SIZE_HeapBlockHeader;
2975 + this->vtbl = copyin_ptr(this->start);
2977 + this->nmethod_vtbl = (pointer) &``__1cHnmethodG__vtbl_;
2978 + this->BufferBlob_vtbl = (pointer) &``__1cKBufferBlobG__vtbl_;
2981 +dtrace:helper:ustack:
2982 +/!this->done && this->vtbl == this->nmethod_vtbl/
2984 + MARK_LINE;
2985 + this->methodPtr = copyin_ptr(this->start + OFFSET_nmethod_method);
2986 + this->suffix = '*';
2987 + this->isMethod = 1;
2990 +dtrace:helper:ustack:
2991 +/!this->done && this->vtbl == this->BufferBlob_vtbl/
2993 + MARK_LINE;
2994 + this->name = copyin_ptr(this->start + OFFSET_CodeBlob_name);
2998 +dtrace:helper:ustack:
2999 +/!this->done && this->vtbl == this->BufferBlob_vtbl && this->methodPtr != 0/
3001 + MARK_LINE;
3002 + this->klass = copyin_ptr(this->methodPtr);
3003 + this->isMethod = this->klass == this->Method_vtbl;
3004 + this->done = !this->isMethod;
3007 +dtrace:helper:ustack:
3008 +/!this->done && !this->isMethod/
3010 + MARK_LINE;
3011 + this->name = copyin_ptr(this->start + OFFSET_CodeBlob_name);
3012 + this->result = this->name != 0 ? copyinstr(this->name) : "<CodeBlob>";
3013 + this->done = 1;
3016 +dtrace:helper:ustack:
3017 +/!this->done && this->isMethod/
3019 + MARK_LINE;
3020 + this->constMethod = copyin_ptr(this->methodPtr +
3021 + OFFSET_Method_constMethod);
3023 + this->nameIndex = copyin_uint16(this->constMethod +
3024 + OFFSET_ConstMethod_name_index);
3026 + this->signatureIndex = copyin_uint16(this->constMethod +
3027 + OFFSET_ConstMethod_signature_index);
3029 + this->constantPool = copyin_ptr(this->constMethod +
3030 + OFFSET_ConstMethod_constants);
3032 + this->nameSymbol = copyin_ptr(this->constantPool +
3033 + this->nameIndex * sizeof (pointer) + SIZE_ConstantPool);
3034 + /* The symbol is a CPSlot and has lower bit set to indicate metadata */
3035 + this->nameSymbol &= (~1); /* remove metadata lsb */
3037 + this->nameSymbolLength = copyin_uint16(this->nameSymbol +
3038 + OFFSET_Symbol_length);
3040 + this->signatureSymbol = copyin_ptr(this->constantPool +
3041 + this->signatureIndex * sizeof (pointer) + SIZE_ConstantPool);
3042 + this->signatureSymbol &= (~1); /* remove metadata lsb */
3044 + this->signatureSymbolLength = copyin_uint16(this->signatureSymbol +
3045 + OFFSET_Symbol_length);
3047 + this->klassPtr = copyin_ptr(this->constantPool +
3048 + OFFSET_ConstantPool_pool_holder);
3050 + this->klassSymbol = copyin_ptr(this->klassPtr +
3051 + OFFSET_Klass_name);
3053 + this->klassSymbolLength = copyin_uint16(this->klassSymbol +
3054 + OFFSET_Symbol_length);
3056 + /*
3057 + * Enough for three strings, plus the '.', plus the trailing '\0'.
3058 + */
3059 + this->result = (char *) alloca(this->klassSymbolLength +
3060 + this->nameSymbolLength +
3061 + this->signatureSymbolLength + 2 + 1);
3063 + copyinto(this->klassSymbol + OFFSET_Symbol_body,
3064 + this->klassSymbolLength, this->result);
3066 + /*
3067 + * Add the '.' between the class and the name.
3068 + */
3069 + this->result[this->klassSymbolLength] = '.';
3071 + copyinto(this->nameSymbol + OFFSET_Symbol_body,
3072 + this->nameSymbolLength,
3073 + this->result + this->klassSymbolLength + 1);
3075 + copyinto(this->signatureSymbol + OFFSET_Symbol_body,
3076 + this->signatureSymbolLength,
3077 + this->result + this->klassSymbolLength +
3078 + this->nameSymbolLength + 1);
3080 + /*
3081 + * Now we need to add a trailing '\0' and possibly a tag character.
3082 + */
3083 + this->result[this->klassSymbolLength + 1 +
3084 + this->nameSymbolLength +
3085 + this->signatureSymbolLength] = this->suffix;
3086 + this->result[this->klassSymbolLength + 2 +
3087 + this->nameSymbolLength +
3088 + this->signatureSymbolLength] = '\0';
3090 + this->done = 1;
3093 +dtrace:helper:ustack:
3094 +/this->done && this->error == (char *) NULL/
3096 + this->result;
3099 +dtrace:helper:ustack:
3100 +/this->done && this->error != (char *) NULL/
3102 + this->error;
3105 +dtrace:helper:ustack:
3106 +/!this->done && this->codecache/
3108 + this->done = 1;
3109 + "error";
3113 +dtrace:helper:ustack:
3114 +/!this->done/
3116 + NULL;
3118 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/os/solaris/globals_solaris.hpp jdk23u-jdk-23-36/src/hotspot/os/solaris/globals_solaris.hpp
3119 --- jdk23u-jdk-23-36.orig/src/hotspot/os/solaris/globals_solaris.hpp 1970-01-01 01:00:00.000000000 +0100
3120 +++ jdk23u-jdk-23-36/src/hotspot/os/solaris/globals_solaris.hpp 2024-08-17 19:50:33.142834368 +0200
3121 @@ -0,0 +1,48 @@
3123 + * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved.
3124 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3126 + * This code is free software; you can redistribute it and/or modify it
3127 + * under the terms of the GNU General Public License version 2 only, as
3128 + * published by the Free Software Foundation.
3130 + * This code is distributed in the hope that it will be useful, but WITHOUT
3131 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
3132 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
3133 + * version 2 for more details (a copy is included in the LICENSE file that
3134 + * accompanied this code).
3136 + * You should have received a copy of the GNU General Public License version
3137 + * 2 along with this work; if not, write to the Free Software Foundation,
3138 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
3140 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
3141 + * or visit www.oracle.com if you need additional information or have any
3142 + * questions.
3144 + */
3146 +#ifndef OS_SOLARIS_GLOBALS_SOLARIS_HPP
3147 +#define OS_SOLARIS_GLOBALS_SOLARIS_HPP
3150 +// Defines Solaris specific flags. They are not available on other platforms.
3152 +#define RUNTIME_OS_FLAGS(develop, \
3153 + develop_pd, \
3154 + product, \
3155 + product_pd, \
3156 + range, \
3157 + constraint)
3160 +// Defines Solaris-specific default values. The flags are available on all
3161 +// platforms, but they may have different default values on other platforms.
3163 +define_pd_global(size_t, PreTouchParallelChunkSize, 1 * G);
3164 +define_pd_global(bool, UseLargePages, true);
3165 +define_pd_global(bool, UseLargePagesIndividualAllocation, false);
3166 +define_pd_global(bool, UseOSErrorReporting, false);
3167 +define_pd_global(bool, UseThreadPriorities, false);
3169 +#endif // OS_SOLARIS_GLOBALS_SOLARIS_HPP
3170 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/os/solaris/os_perf_solaris.cpp jdk23u-jdk-23-36/src/hotspot/os/solaris/os_perf_solaris.cpp
3171 --- jdk23u-jdk-23-36.orig/src/hotspot/os/solaris/os_perf_solaris.cpp 1970-01-01 01:00:00.000000000 +0100
3172 +++ jdk23u-jdk-23-36/src/hotspot/os/solaris/os_perf_solaris.cpp 2024-08-17 19:50:33.143890419 +0200
3173 @@ -0,0 +1,808 @@
3175 + * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
3176 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3178 + * This code is free software; you can redistribute it and/or modify it
3179 + * under the terms of the GNU General Public License version 2 only, as
3180 + * published by the Free Software Foundation.
3182 + * This code is distributed in the hope that it will be useful, but WITHOUT
3183 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
3184 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
3185 + * version 2 for more details (a copy is included in the LICENSE file that
3186 + * accompanied this code).
3188 + * You should have received a copy of the GNU General Public License version
3189 + * 2 along with this work; if not, write to the Free Software Foundation,
3190 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
3192 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
3193 + * or visit www.oracle.com if you need additional information or have any
3194 + * questions.
3196 + */
3198 +#include "precompiled.hpp"
3199 +#include "jvm.h"
3200 +#include "memory/allocation.inline.hpp"
3201 +#include "runtime/os.hpp"
3202 +#include "runtime/os_perf.hpp"
3203 +#include "runtime/vm_version.hpp"
3204 +#include "os_solaris.inline.hpp"
3205 +#include "utilities/globalDefinitions.hpp"
3206 +#include "utilities/macros.hpp"
3208 +#include <sys/types.h>
3209 +#include <procfs.h>
3210 +#include <dirent.h>
3211 +#include <errno.h>
3212 +#include <stdio.h>
3213 +#include <stdlib.h>
3214 +#include <strings.h>
3215 +#include <unistd.h>
3216 +#include <fcntl.h>
3217 +#include <kstat.h>
3218 +#include <unistd.h>
3219 +#include <string.h>
3220 +#include <sys/sysinfo.h>
3221 +#include <sys/lwp.h>
3222 +#include <pthread.h>
3223 +#include <time.h>
3224 +#include <utmpx.h>
3225 +#include <dlfcn.h>
3226 +#include <sys/loadavg.h>
3227 +#include <limits.h>
3229 +static const double NANOS_PER_SEC = 1000000000.0;
3231 +struct CPUPerfTicks {
3232 + kstat_t* kstat;
3233 + uint64_t last_idle;
3234 + uint64_t last_total;
3235 + double last_ratio;
3238 +struct CPUPerfCounters {
3239 + int nProcs;
3240 + CPUPerfTicks* jvmTicks;
3241 + kstat_ctl_t* kstat_ctrl;
3244 +static int get_info(const char* path, void* info, size_t s, off_t o) {
3245 + assert(path != NULL, "path is NULL!");
3246 + assert(info != NULL, "info is NULL!");
3248 + int fd = -1;
3250 + if ((fd = os::open(path, O_RDONLY, 0)) < 0) {
3251 + return OS_ERR;
3253 + if (pread(fd, info, s, o) != s) {
3254 + close(fd);
3255 + return OS_ERR;
3257 + close(fd);
3258 + return OS_OK;
3261 +static int get_psinfo2(void* info, size_t s, off_t o) {
3262 + return get_info("/proc/self/psinfo", info, s, o);
3265 +static int get_psinfo(psinfo_t* info) {
3266 + return get_psinfo2(info, sizeof(*info), 0);
3269 +static int read_cpustat(kstat_ctl_t* kstat_ctrl, CPUPerfTicks* load, cpu_stat_t* cpu_stat) {
3270 + assert(kstat_ctrl != NULL, "kstat_ctrl pointer is NULL!");
3271 + assert(load != NULL, "load pointer is NULL!");
3272 + assert(cpu_stat != NULL, "cpu_stat pointer is NULL!");
3274 + if (load->kstat == NULL) {
3275 + // no handle.
3276 + return OS_ERR;
3278 + if (kstat_read(kstat_ctrl, load->kstat, cpu_stat) == OS_ERR) {
3279 + // disable handle for this CPU
3280 + load->kstat = NULL;
3281 + return OS_ERR;
3283 + return OS_OK;
3286 +static double get_cpu_load(int which_logical_cpu, CPUPerfCounters* counters) {
3287 + assert(counters != NULL, "counters pointer is NULL!");
3289 + cpu_stat_t cpu_stat = {0};
3291 + if (which_logical_cpu >= counters->nProcs) {
3292 + return .0;
3295 + CPUPerfTicks load = counters->jvmTicks[which_logical_cpu];
3296 + if (read_cpustat(counters->kstat_ctrl, &load, &cpu_stat) != OS_OK) {
3297 + return .0;
3300 + uint_t* usage = cpu_stat.cpu_sysinfo.cpu;
3301 + if (usage == NULL) {
3302 + return .0;
3305 + uint64_t c_idle = usage[CPU_IDLE];
3306 + uint64_t c_total = 0;
3308 + for (int i = 0; i < CPU_STATES; i++) {
3309 + c_total += usage[i];
3312 + // Calculate diff against previous snapshot
3313 + uint64_t d_idle = c_idle - load.last_idle;
3314 + uint64_t d_total = c_total - load.last_total;
3316 + /** update if weve moved */
3317 + if (d_total > 0) {
3318 + // Save current values for next time around
3319 + load.last_idle = c_idle;
3320 + load.last_total = c_total;
3321 + load.last_ratio = (double) (d_total - d_idle) / d_total;
3324 + return load.last_ratio;
3327 +static int get_boot_time(uint64_t* time) {
3328 + assert(time != NULL, "time pointer is NULL!");
3329 + setutxent();
3330 + for(;;) {
3331 + struct utmpx* u;
3332 + if ((u = getutxent()) == NULL) {
3333 + break;
3335 + if (u->ut_type == BOOT_TIME) {
3336 + *time = u->ut_xtime;
3337 + endutxent();
3338 + return OS_OK;
3341 + endutxent();
3342 + return OS_ERR;
3345 +static int get_noof_context_switches(CPUPerfCounters* counters, uint64_t* switches) {
3346 + assert(switches != NULL, "switches pointer is NULL!");
3347 + assert(counters != NULL, "counter pointer is NULL!");
3348 + *switches = 0;
3349 + uint64_t s = 0;
3351 + // Collect data from all CPUs
3352 + for (int i = 0; i < counters->nProcs; i++) {
3353 + cpu_stat_t cpu_stat = {0};
3354 + CPUPerfTicks load = counters->jvmTicks[i];
3356 + if (read_cpustat(counters->kstat_ctrl, &load, &cpu_stat) == OS_OK) {
3357 + s += cpu_stat.cpu_sysinfo.pswitch;
3358 + } else {
3359 + //fail fast...
3360 + return OS_ERR;
3363 + *switches = s;
3364 + return OS_OK;
3367 +static int perf_context_switch_rate(CPUPerfCounters* counters, double* rate) {
3368 + assert(counters != NULL, "counters is NULL!");
3369 + assert(rate != NULL, "rate pointer is NULL!");
3370 + static pthread_mutex_t contextSwitchLock = PTHREAD_MUTEX_INITIALIZER;
3371 + static uint64_t lastTime = 0;
3372 + static uint64_t lastSwitches = 0;
3373 + static double lastRate = 0.0;
3375 + uint64_t lt = 0;
3376 + int res = 0;
3378 + if (lastTime == 0) {
3379 + uint64_t tmp;
3380 + if (get_boot_time(&tmp) < 0) {
3381 + return OS_ERR;
3383 + lt = tmp * 1000;
3386 + res = OS_OK;
3388 + pthread_mutex_lock(&contextSwitchLock);
3391 + uint64_t sw = 0;
3392 + clock_t t, d;
3394 + if (lastTime == 0) {
3395 + lastTime = lt;
3398 + t = clock();
3399 + d = t - lastTime;
3401 + if (d == 0) {
3402 + *rate = lastRate;
3403 + } else if (get_noof_context_switches(counters, &sw)== OS_OK) {
3404 + *rate = ((double)(sw - lastSwitches) / d) * 1000;
3405 + lastRate = *rate;
3406 + lastSwitches = sw;
3407 + lastTime = t;
3408 + } else {
3409 + *rate = 0.0;
3410 + res = OS_ERR;
3412 + if (*rate < 0.0) {
3413 + *rate = 0.0;
3414 + lastRate = 0.0;
3417 + pthread_mutex_unlock(&contextSwitchLock);
3418 + return res;
3423 +class CPUPerformanceInterface::CPUPerformance : public CHeapObj<mtInternal> {
3424 + friend class CPUPerformanceInterface;
3425 + private:
3426 + CPUPerfCounters _counters;
3427 + int cpu_load(int which_logical_cpu, double* cpu_load);
3428 + int context_switch_rate(double* rate);
3429 + int cpu_load_total_process(double* cpu_load);
3430 + int cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad);
3432 + CPUPerformance();
3433 + ~CPUPerformance();
3434 + bool initialize();
3437 +CPUPerformanceInterface::CPUPerformance::CPUPerformance() {
3438 + _counters.nProcs = 0;
3439 + _counters.jvmTicks = NULL;
3440 + _counters.kstat_ctrl = NULL;
3443 +bool CPUPerformanceInterface::CPUPerformance::initialize() {
3444 + // initialize kstat control structure,
3445 + _counters.kstat_ctrl = kstat_open();
3446 + assert(_counters.kstat_ctrl != NULL, "error initializing kstat control structure!");
3448 + if (NULL == _counters.kstat_ctrl) {
3449 + return false;
3452 + // Get number of CPU(s)
3453 + if ((_counters.nProcs = sysconf(_SC_NPROCESSORS_ONLN)) == OS_ERR) {
3454 + // ignore error?
3455 + _counters.nProcs = 1;
3458 + assert(_counters.nProcs > 0, "no CPUs detected in sysconf call!");
3459 + if (_counters.nProcs == 0) {
3460 + return false;
3463 + // Data structure(s) for saving CPU load (one per CPU)
3464 + size_t array_entry_count = _counters.nProcs;
3465 + _counters.jvmTicks = NEW_C_HEAP_ARRAY(CPUPerfTicks, array_entry_count, mtInternal);
3466 + memset(_counters.jvmTicks, 0, array_entry_count * sizeof(*_counters.jvmTicks));
3468 + // Get kstat cpu_stat counters for every CPU
3469 + // loop over kstat to find our cpu_stat(s)
3470 + int i = 0;
3471 + for (kstat_t* kstat = _counters.kstat_ctrl->kc_chain; kstat != NULL; kstat = kstat->ks_next) {
3472 + if (strncmp(kstat->ks_module, "cpu_stat", 8) == 0) {
3473 + if (kstat_read(_counters.kstat_ctrl, kstat, NULL) == OS_ERR) {
3474 + continue;
3476 + if (i == _counters.nProcs) {
3477 + // more cpu_stats than reported CPUs
3478 + break;
3480 + _counters.jvmTicks[i++].kstat = kstat;
3483 + return true;
3486 +CPUPerformanceInterface::CPUPerformance::~CPUPerformance() {
3487 + FREE_C_HEAP_ARRAY(char, _counters.jvmTicks);
3488 + if (_counters.kstat_ctrl != NULL) {
3489 + kstat_close(_counters.kstat_ctrl);
3493 +int CPUPerformanceInterface::CPUPerformance::cpu_load(int which_logical_cpu, double* cpu_load) {
3494 + assert(cpu_load != NULL, "cpu_load pointer is NULL!");
3495 + double t = .0;
3496 + if (-1 == which_logical_cpu) {
3497 + for (int i = 0; i < _counters.nProcs; i++) {
3498 + t += get_cpu_load(i, &_counters);
3500 + // Cap total systemload to 1.0
3501 + t = MIN2<double>((t / _counters.nProcs), 1.0);
3502 + } else {
3503 + t = MIN2<double>(get_cpu_load(which_logical_cpu, &_counters), 1.0);
3506 + *cpu_load = t;
3507 + return OS_OK;
3510 +int CPUPerformanceInterface::CPUPerformance::cpu_load_total_process(double* cpu_load) {
3511 + assert(cpu_load != NULL, "cpu_load pointer is NULL!");
3513 + psinfo_t info;
3515 + // Get the percentage of "recent cpu usage" from all the lwp:s in the JVM:s
3516 + // process. This is returned as a value between 0.0 and 1.0 multiplied by 0x8000.
3517 + if (get_psinfo2(&info.pr_pctcpu, sizeof(info.pr_pctcpu), offsetof(psinfo_t, pr_pctcpu)) != 0) {
3518 + *cpu_load = 0.0;
3519 + return OS_ERR;
3521 + *cpu_load = (double) info.pr_pctcpu / 0x8000;
3522 + return OS_OK;
3525 +int CPUPerformanceInterface::CPUPerformance::cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad) {
3526 + assert(pjvmUserLoad != NULL, "pjvmUserLoad not inited");
3527 + assert(pjvmKernelLoad != NULL, "pjvmKernelLoad not inited");
3528 + assert(psystemTotalLoad != NULL, "psystemTotalLoad not inited");
3530 + static uint64_t lastTime;
3531 + static uint64_t lastUser, lastKernel;
3532 + static double lastUserRes, lastKernelRes;
3534 + pstatus_t pss;
3535 + psinfo_t info;
3537 + *pjvmKernelLoad = *pjvmUserLoad = *psystemTotalLoad = 0;
3538 + if (get_info("/proc/self/status", &pss.pr_utime, sizeof(timestruc_t)*2, offsetof(pstatus_t, pr_utime)) != 0) {
3539 + return OS_ERR;
3542 + if (get_psinfo(&info) != 0) {
3543 + return OS_ERR;
3546 + // get the total time in user, kernel and total time
3547 + // check ratios for 'lately' and multiply the 'recent load'.
3548 + uint64_t time = (info.pr_time.tv_sec * NANOS_PER_SEC) + info.pr_time.tv_nsec;
3549 + uint64_t user = (pss.pr_utime.tv_sec * NANOS_PER_SEC) + pss.pr_utime.tv_nsec;
3550 + uint64_t kernel = (pss.pr_stime.tv_sec * NANOS_PER_SEC) + pss.pr_stime.tv_nsec;
3551 + uint64_t diff = time - lastTime;
3552 + double load = (double) info.pr_pctcpu / 0x8000;
3554 + if (diff > 0) {
3555 + lastUserRes = (load * (user - lastUser)) / diff;
3556 + lastKernelRes = (load * (kernel - lastKernel)) / diff;
3558 + // BUG9182835 - patch for clamping these values to sane ones.
3559 + lastUserRes = MIN2<double>(1, lastUserRes);
3560 + lastUserRes = MAX2<double>(0, lastUserRes);
3561 + lastKernelRes = MIN2<double>(1, lastKernelRes);
3562 + lastKernelRes = MAX2<double>(0, lastKernelRes);
3565 + double t = .0;
3566 + cpu_load(-1, &t);
3567 + // clamp at user+system and 1.0
3568 + if (lastUserRes + lastKernelRes > t) {
3569 + t = MIN2<double>(lastUserRes + lastKernelRes, 1.0);
3572 + *pjvmUserLoad = lastUserRes;
3573 + *pjvmKernelLoad = lastKernelRes;
3574 + *psystemTotalLoad = t;
3576 + lastTime = time;
3577 + lastUser = user;
3578 + lastKernel = kernel;
3580 + return OS_OK;
3583 +int CPUPerformanceInterface::CPUPerformance::context_switch_rate(double* rate) {
3584 + return perf_context_switch_rate(&_counters, rate);
3587 +CPUPerformanceInterface::CPUPerformanceInterface() {
3588 + _impl = NULL;
3591 +bool CPUPerformanceInterface::initialize() {
3592 + _impl = new CPUPerformanceInterface::CPUPerformance();
3593 + return _impl->initialize();
3596 +CPUPerformanceInterface::~CPUPerformanceInterface(void) {
3597 + if (_impl != NULL) {
3598 + delete _impl;
3602 +int CPUPerformanceInterface::cpu_load(int which_logical_cpu, double* cpu_load) const {
3603 + return _impl->cpu_load(which_logical_cpu, cpu_load);
3606 +int CPUPerformanceInterface::cpu_load_total_process(double* cpu_load) const {
3607 + return _impl->cpu_load_total_process(cpu_load);
3610 +int CPUPerformanceInterface::cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad) const {
3611 + return _impl->cpu_loads_process(pjvmUserLoad, pjvmKernelLoad, psystemTotalLoad);
3614 +int CPUPerformanceInterface::context_switch_rate(double* rate) const {
3615 + return _impl->context_switch_rate(rate);
3618 +class SystemProcessInterface::SystemProcesses : public CHeapObj<mtInternal> {
3619 + friend class SystemProcessInterface;
3620 + private:
3621 + class ProcessIterator : public CHeapObj<mtInternal> {
3622 + friend class SystemProcessInterface::SystemProcesses;
3623 + private:
3624 + DIR* _dir;
3625 + struct dirent* _entry;
3626 + bool _valid;
3628 + ProcessIterator();
3629 + ~ProcessIterator();
3630 + bool initialize();
3632 + bool is_valid() const { return _valid; }
3633 + bool is_valid_entry(struct dirent* const entry) const;
3634 + bool is_dir(const char* const name) const;
3635 + char* allocate_string(const char* const str) const;
3636 + int current(SystemProcess* const process_info);
3637 + int next_process();
3638 + };
3640 + ProcessIterator* _iterator;
3641 + SystemProcesses();
3642 + bool initialize();
3643 + ~SystemProcesses();
3645 + //information about system processes
3646 + int system_processes(SystemProcess** system_processes, int* no_of_sys_processes) const;
3649 +bool SystemProcessInterface::SystemProcesses::ProcessIterator::is_dir(const char* name) const {
3650 + struct stat64 mystat;
3651 + int ret_val = 0;
3653 + ret_val = ::stat64(name, &mystat);
3655 + if (ret_val < 0) {
3656 + return false;
3658 + ret_val = S_ISDIR(mystat.st_mode);
3659 + return ret_val > 0;
3662 +// if it has a numeric name, is a directory and has a 'psinfo' file in it
3663 +bool SystemProcessInterface::SystemProcesses::ProcessIterator::is_valid_entry(struct dirent* entry) const {
3664 + // ignore the "." and ".." directories
3665 + if ((strcmp(entry->d_name, ".") == 0) ||
3666 + (strcmp(entry->d_name, "..") == 0)) {
3667 + return false;
3670 + char buffer[PATH_MAX] = {0};
3671 + uint64_t size = 0;
3672 + bool result = false;
3673 + FILE *fp = NULL;
3675 + if (atoi(entry->d_name) != 0) {
3676 + jio_snprintf(buffer, PATH_MAX, "/proc/%s", entry->d_name);
3678 + if (is_dir(buffer)) {
3679 + memset(buffer, 0, PATH_MAX);
3680 + jio_snprintf(buffer, PATH_MAX, "/proc/%s/psinfo", entry->d_name);
3681 + if ((fp = fopen(buffer, "r")) != NULL) {
3682 + int nread = 0;
3683 + psinfo_t psinfo_data;
3684 + if ((nread = fread(&psinfo_data, 1, sizeof(psinfo_t), fp)) != -1) {
3685 + // only considering system process owned by root
3686 + if (psinfo_data.pr_uid == 0) {
3687 + result = true;
3694 + if (fp != NULL) {
3695 + fclose(fp);
3698 + return result;
3701 +char* SystemProcessInterface::SystemProcesses::ProcessIterator::allocate_string(const char* str) const {
3702 + if (str != NULL) {
3703 + return os::strdup_check_oom(str, mtInternal);
3705 + return NULL;
3708 +int SystemProcessInterface::SystemProcesses::ProcessIterator::current(SystemProcess* process_info) {
3709 + if (!is_valid()) {
3710 + return OS_ERR;
3713 + char psinfo_path[PATH_MAX] = {0};
3714 + jio_snprintf(psinfo_path, PATH_MAX, "/proc/%s/psinfo", _entry->d_name);
3716 + FILE *fp = NULL;
3717 + if ((fp = fopen(psinfo_path, "r")) == NULL) {
3718 + return OS_ERR;
3721 + int nread = 0;
3722 + psinfo_t psinfo_data;
3723 + if ((nread = fread(&psinfo_data, 1, sizeof(psinfo_t), fp)) == -1) {
3724 + fclose(fp);
3725 + return OS_ERR;
3728 + char *exe_path = NULL;
3729 + if ((psinfo_data.pr_fname != NULL) &&
3730 + (psinfo_data.pr_psargs != NULL)) {
3731 + char *path_substring = strstr(psinfo_data.pr_psargs, psinfo_data.pr_fname);
3732 + if (path_substring != NULL) {
3733 + int len = path_substring - psinfo_data.pr_psargs;
3734 + exe_path = NEW_C_HEAP_ARRAY(char, len+1, mtInternal);
3735 + jio_snprintf(exe_path, len, "%s", psinfo_data.pr_psargs);
3736 + exe_path[len] = '\0';
3740 + process_info->set_pid(atoi(_entry->d_name));
3741 + process_info->set_name(allocate_string(psinfo_data.pr_fname));
3742 + process_info->set_path(allocate_string(exe_path));
3743 + process_info->set_command_line(allocate_string(psinfo_data.pr_psargs));
3745 + if (exe_path != NULL) {
3746 + FREE_C_HEAP_ARRAY(char, exe_path);
3749 + if (fp != NULL) {
3750 + fclose(fp);
3753 + return OS_OK;
3756 +int SystemProcessInterface::SystemProcesses::ProcessIterator::next_process() {
3757 + if (!is_valid()) {
3758 + return OS_ERR;
3761 + do {
3762 + _entry = os::readdir(_dir);
3763 + if (_entry == NULL) {
3764 + // Error or reached end. Could use errno to distinguish those cases.
3765 + _valid = false;
3766 + return OS_ERR;
3768 + } while(!is_valid_entry(_entry));
3770 + _valid = true;
3771 + return OS_OK;
3774 +SystemProcessInterface::SystemProcesses::ProcessIterator::ProcessIterator() {
3775 + _dir = NULL;
3776 + _entry = NULL;
3777 + _valid = false;
3780 +bool SystemProcessInterface::SystemProcesses::ProcessIterator::initialize() {
3781 + _dir = os::opendir("/proc");
3782 + _entry = NULL;
3783 + _valid = true;
3784 + next_process();
3786 + return true;
3789 +SystemProcessInterface::SystemProcesses::ProcessIterator::~ProcessIterator() {
3790 + if (_dir != NULL) {
3791 + os::closedir(_dir);
3795 +SystemProcessInterface::SystemProcesses::SystemProcesses() {
3796 + _iterator = NULL;
3799 +bool SystemProcessInterface::SystemProcesses::initialize() {
3800 + _iterator = new SystemProcessInterface::SystemProcesses::ProcessIterator();
3801 + return _iterator->initialize();
3804 +SystemProcessInterface::SystemProcesses::~SystemProcesses() {
3805 + if (_iterator != NULL) {
3806 + delete _iterator;
3810 +int SystemProcessInterface::SystemProcesses::system_processes(SystemProcess** system_processes, int* no_of_sys_processes) const {
3811 + assert(system_processes != NULL, "system_processes pointer is NULL!");
3812 + assert(no_of_sys_processes != NULL, "system_processes counter pointer is NULL!");
3813 + assert(_iterator != NULL, "iterator is NULL!");
3815 + // initialize pointers
3816 + *no_of_sys_processes = 0;
3817 + *system_processes = NULL;
3819 + while (_iterator->is_valid()) {
3820 + SystemProcess* tmp = new SystemProcess();
3821 + _iterator->current(tmp);
3823 + //if already existing head
3824 + if (*system_processes != NULL) {
3825 + //move "first to second"
3826 + tmp->set_next(*system_processes);
3828 + // new head
3829 + *system_processes = tmp;
3830 + // increment
3831 + (*no_of_sys_processes)++;
3832 + // step forward
3833 + _iterator->next_process();
3835 + return OS_OK;
3838 +int SystemProcessInterface::system_processes(SystemProcess** system_procs, int* no_of_sys_processes) const {
3839 + return _impl->system_processes(system_procs, no_of_sys_processes);
3842 +SystemProcessInterface::SystemProcessInterface() {
3843 + _impl = NULL;
3846 +bool SystemProcessInterface::initialize() {
3847 + _impl = new SystemProcessInterface::SystemProcesses();
3848 + return _impl->initialize();
3852 +SystemProcessInterface::~SystemProcessInterface() {
3853 + if (_impl != NULL) {
3854 + delete _impl;
3858 +CPUInformationInterface::CPUInformationInterface() {
3859 + _cpu_info = NULL;
3862 +bool CPUInformationInterface::initialize() {
3863 + _cpu_info = new CPUInformation();
3864 + VM_Version::initialize_cpu_information();
3865 + _cpu_info->set_number_of_hardware_threads(VM_Version::number_of_threads());
3866 + _cpu_info->set_number_of_cores(VM_Version::number_of_cores());
3867 + _cpu_info->set_number_of_sockets(VM_Version::number_of_sockets());
3868 + _cpu_info->set_cpu_name(VM_Version::cpu_name());
3869 + _cpu_info->set_cpu_description(VM_Version::cpu_description());
3870 + return true;
3873 +CPUInformationInterface::~CPUInformationInterface() {
3874 + if (_cpu_info != NULL) {
3875 + if (_cpu_info->cpu_name() != NULL) {
3876 + const char* cpu_name = _cpu_info->cpu_name();
3877 + FREE_C_HEAP_ARRAY(char, cpu_name);
3878 + _cpu_info->set_cpu_name(NULL);
3880 + if (_cpu_info->cpu_description() != NULL) {
3881 + const char* cpu_desc = _cpu_info->cpu_description();
3882 + FREE_C_HEAP_ARRAY(char, cpu_desc);
3883 + _cpu_info->set_cpu_description(NULL);
3885 + delete _cpu_info;
3889 +int CPUInformationInterface::cpu_information(CPUInformation& cpu_info) {
3890 + if (_cpu_info == NULL) {
3891 + return OS_ERR;
3894 + cpu_info = *_cpu_info; // shallow copy assignment
3895 + return OS_OK;
3898 +class NetworkPerformanceInterface::NetworkPerformance : public CHeapObj<mtInternal> {
3899 + friend class NetworkPerformanceInterface;
3900 + private:
3901 + NetworkPerformance();
3902 + NONCOPYABLE(NetworkPerformance);
3903 + bool initialize();
3904 + ~NetworkPerformance();
3905 + int network_utilization(NetworkInterface** network_interfaces) const;
3908 +NetworkPerformanceInterface::NetworkPerformance::NetworkPerformance() {
3912 +bool NetworkPerformanceInterface::NetworkPerformance::initialize() {
3913 + return true;
3916 +NetworkPerformanceInterface::NetworkPerformance::~NetworkPerformance() {
3920 +int NetworkPerformanceInterface::NetworkPerformance::network_utilization(NetworkInterface** network_interfaces) const
3922 + kstat_ctl_t* ctl = kstat_open();
3923 + if (ctl == NULL) {
3924 + return OS_ERR;
3927 + NetworkInterface* ret = NULL;
3928 + for (kstat_t* k = ctl->kc_chain; k != NULL; k = k->ks_next) {
3929 + if (strcmp(k->ks_class, "net") != 0) {
3930 + continue;
3932 + if (strcmp(k->ks_module, "link") != 0) {
3933 + continue;
3936 + if (kstat_read(ctl, k, NULL) == -1) {
3937 + return OS_ERR;
3940 + uint64_t bytes_in = UINT64_MAX;
3941 + uint64_t bytes_out = UINT64_MAX;
3942 + for (unsigned int i = 0; i < k->ks_ndata; ++i) {
3943 + kstat_named_t* data = &reinterpret_cast<kstat_named_t*>(k->ks_data)[i];
3944 + if (strcmp(data->name, "rbytes64") == 0) {
3945 + bytes_in = data->value.ui64;
3947 + else if (strcmp(data->name, "obytes64") == 0) {
3948 + bytes_out = data->value.ui64;
3952 + if ((bytes_in != UINT64_MAX) && (bytes_out != UINT64_MAX)) {
3953 + NetworkInterface* cur = new NetworkInterface(k->ks_name, bytes_in, bytes_out, ret);
3954 + ret = cur;
3958 + kstat_close(ctl);
3959 + *network_interfaces = ret;
3961 + return OS_OK;
3964 +NetworkPerformanceInterface::NetworkPerformanceInterface() {
3965 + _impl = NULL;
3968 +NetworkPerformanceInterface::~NetworkPerformanceInterface() {
3969 + if (_impl != NULL) {
3970 + delete _impl;
3974 +bool NetworkPerformanceInterface::initialize() {
3975 + _impl = new NetworkPerformanceInterface::NetworkPerformance();
3976 + return _impl->initialize();
3979 +int NetworkPerformanceInterface::network_utilization(NetworkInterface** network_interfaces) const {
3980 + return _impl->network_utilization(network_interfaces);
3982 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/os/solaris/os_solaris.cpp jdk23u-jdk-23-36/src/hotspot/os/solaris/os_solaris.cpp
3983 --- jdk23u-jdk-23-36.orig/src/hotspot/os/solaris/os_solaris.cpp 1970-01-01 01:00:00.000000000 +0100
3984 +++ jdk23u-jdk-23-36/src/hotspot/os/solaris/os_solaris.cpp 2024-08-17 19:50:33.145500618 +0200
3985 @@ -0,0 +1,2938 @@
3987 + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
3988 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3990 + * This code is free software; you can redistribute it and/or modify it
3991 + * under the terms of the GNU General Public License version 2 only, as
3992 + * published by the Free Software Foundation.
3994 + * This code is distributed in the hope that it will be useful, but WITHOUT
3995 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
3996 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
3997 + * version 2 for more details (a copy is included in the LICENSE file that
3998 + * accompanied this code).
4000 + * You should have received a copy of the GNU General Public License version
4001 + * 2 along with this work; if not, write to the Free Software Foundation,
4002 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
4004 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
4005 + * or visit www.oracle.com if you need additional information or have any
4006 + * questions.
4008 + */
4010 +// no precompiled headers
4011 +#include "jvm.h"
4012 +#include "classfile/classLoader.hpp"
4013 +#include "classfile/systemDictionary.hpp"
4014 +#include "classfile/vmSymbols.hpp"
4015 +#include "code/vtableStubs.hpp"
4016 +#include "compiler/compileBroker.hpp"
4017 +#include "compiler/disassembler.hpp"
4018 +#include "interpreter/interpreter.hpp"
4019 +#include "jvmtifiles/jvmti.h"
4020 +#include "logging/log.hpp"
4021 +#include "logging/logStream.hpp"
4022 +#include "memory/allocation.inline.hpp"
4023 +#include "memory/universe.hpp"
4024 +#include "oops/oop.inline.hpp"
4025 +#include "os_solaris.inline.hpp"
4026 +#include "prims/jniFastGetField.hpp"
4027 +#include "prims/jvm_misc.hpp"
4028 +#include "runtime/arguments.hpp"
4029 +#include "runtime/atomic.hpp"
4030 +#include "runtime/globals.hpp"
4031 +#include "runtime/globals_extension.hpp"
4032 +#include "runtime/interfaceSupport.inline.hpp"
4033 +#include "runtime/java.hpp"
4034 +#include "runtime/javaCalls.hpp"
4035 +#include "runtime/javaThread.hpp"
4036 +#include "runtime/mutexLocker.hpp"
4037 +#include "runtime/objectMonitor.hpp"
4038 +#include "runtime/osInfo.hpp"
4039 +#include "runtime/orderAccess.hpp"
4040 +#include "runtime/osThread.hpp"
4041 +#include "runtime/park.hpp"
4042 +#include "runtime/perfMemory.hpp"
4043 +#include "runtime/sharedRuntime.hpp"
4044 +#include "runtime/statSampler.hpp"
4045 +#include "runtime/stubRoutines.hpp"
4046 +#include "runtime/threadCritical.hpp"
4047 +#include "runtime/threads.hpp"
4048 +#include "runtime/timer.hpp"
4049 +#include "runtime/vm_version.hpp"
4050 +#include "semaphore_posix.hpp"
4051 +#include "services/attachListener.hpp"
4052 +#include "nmt/memTracker.hpp"
4053 +#include "services/runtimeService.hpp"
4054 +#include "signals_posix.hpp"
4055 +#include "utilities/align.hpp"
4056 +#include "utilities/checkedCast.hpp"
4057 +#include "utilities/decoder.hpp"
4058 +#include "utilities/defaultStream.hpp"
4059 +#include "utilities/events.hpp"
4060 +#include "utilities/growableArray.hpp"
4061 +#include "utilities/macros.hpp"
4062 +#include "utilities/vmError.hpp"
4064 +// put OS-includes here
4065 +# include <dlfcn.h>
4066 +# include <errno.h>
4067 +# include <exception>
4068 +# include <link.h>
4069 +# include <poll.h>
4070 +# include <pthread.h>
4071 +# include <setjmp.h>
4072 +# include <signal.h>
4073 +# include <stdio.h>
4074 +# include <alloca.h>
4075 +# include <sys/filio.h>
4076 +# include <sys/ipc.h>
4077 +# include <sys/lwp.h>
4078 +# include <sys/machelf.h> // for elf Sym structure used by dladdr1
4079 +# include <sys/mman.h>
4080 +# include <sys/processor.h>
4081 +# include <sys/procset.h>
4082 +# include <sys/pset.h>
4083 +# include <sys/resource.h>
4084 +# include <sys/shm.h>
4085 +# include <sys/socket.h>
4086 +# include <sys/stat.h>
4087 +# include <sys/swap.h> // for swapctl
4088 +# include <sys/systeminfo.h>
4089 +# include <sys/time.h>
4090 +# include <sys/times.h>
4091 +# include <sys/types.h>
4092 +# include <sys/wait.h>
4093 +# include <sys/utsname.h>
4094 +# include <thread.h>
4095 +# include <unistd.h>
4096 +# include <sys/priocntl.h>
4097 +# include <sys/rtpriocntl.h>
4098 +# include <sys/tspriocntl.h>
4099 +# include <sys/iapriocntl.h>
4100 +# include <sys/fxpriocntl.h>
4101 +# include <sys/loadavg.h>
4102 +# include <string.h>
4103 +# include <stdio.h>
4104 +# include <vm/anon.h> // for swap anoninfo
4106 +# include <procfs.h>
4108 +#define MAX_PATH (2 * K)
4110 +// for timer info max values which include all bits
4111 +#define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF)
4113 +// Here are some liblgrp types from sys/lgrp_user.h to be able to
4114 +// compile on older systems without this header file.
4116 +#ifndef MADV_ACCESS_LWP
4117 + #define MADV_ACCESS_LWP 7 /* next LWP to access heavily */
4118 +#endif
4119 +#ifndef MADV_ACCESS_MANY
4120 + #define MADV_ACCESS_MANY 8 /* many processes to access heavily */
4121 +#endif
4123 +#ifndef LGRP_RSRC_CPU
4124 + #define LGRP_RSRC_CPU 0 /* CPU resources */
4125 +#endif
4126 +#ifndef LGRP_RSRC_MEM
4127 + #define LGRP_RSRC_MEM 1 /* memory resources */
4128 +#endif
4130 +// guarded in sys/mman.h
4131 +extern "C" {
4132 +extern int getpagesizes(size_t[], int);
4135 +// Values for ThreadPriorityPolicy == 1
4136 +int prio_policy1[CriticalPriority+1] = {
4137 + -99999, 0, 16, 32, 48, 64,
4138 + 80, 96, 112, 124, 127, 127 };
4140 +// System parameters used internally
4141 +static clock_t clock_tics_per_sec = 100;
4143 +// For diagnostics to print a message once. see run_periodic_checks
4144 +static bool check_addr0_done = false;
4146 +address os::Solaris::handler_start; // start pc of thr_sighndlrinfo
4147 +address os::Solaris::handler_end; // end pc of thr_sighndlrinfo
4149 +address os::Solaris::_main_stack_base = NULL; // 4352906 workaround
4151 +os::Solaris::pthread_setname_np_func_t os::Solaris::_pthread_setname_np = NULL;
4153 +// "default" initializers for missing libc APIs
4154 +extern "C" {
4155 + int memcntl(void *, size_t, int, void *, int, int);
4156 + int meminfo(const uint64_t *, int, const uint_t *, int, uint64_t *, uint_t *);
4159 +static inline size_t adjust_stack_size(address base, size_t size) {
4160 + if ((ssize_t)size < 0) {
4161 + // 4759953: Compensate for ridiculous stack size.
4162 + size = max_intx;
4164 + if (size > (size_t)base) {
4165 + // 4812466: Make sure size doesn't allow the stack to wrap the address space.
4166 + size = (size_t)base;
4168 + return size;
4171 +static inline stack_t get_stack_info() {
4172 + stack_t st;
4173 + int retval = thr_stksegment(&st);
4174 + st.ss_size = adjust_stack_size((address)st.ss_sp, st.ss_size);
4175 + assert(retval == 0, "incorrect return value from thr_stksegment");
4176 + assert((address)&st < (address)st.ss_sp, "Invalid stack base returned");
4177 + assert((address)&st > (address)st.ss_sp-st.ss_size, "Invalid stack size returned");
4178 + return st;
4181 +bool os::is_primordial_thread(void) {
4182 + int r = thr_main();
4183 + guarantee(r == 0 || r == 1, "CR6501650 or CR6493689");
4184 + return r == 1;
4187 +address os::Solaris::current_stack_base() {
4188 + bool _is_primordial_thread = os::is_primordial_thread();
4190 + // Workaround 4352906, avoid calls to thr_stksegment by
4191 + // thr_main after the first one (it looks like we trash
4192 + // some data, causing the value for ss_sp to be incorrect).
4193 + if (!_is_primordial_thread || os::Solaris::_main_stack_base == NULL) {
4194 + stack_t st = get_stack_info();
4195 + if (_is_primordial_thread) {
4196 + // cache initial value of stack base
4197 + os::Solaris::_main_stack_base = (address)st.ss_sp;
4199 + return (address)st.ss_sp;
4200 + } else {
4201 + guarantee(os::Solaris::_main_stack_base != NULL, "Attempt to use null cached stack base");
4202 + return os::Solaris::_main_stack_base;
4206 +size_t os::Solaris::current_stack_size() {
4207 + size_t size;
4209 + if (!os::is_primordial_thread()) {
4210 + size = get_stack_info().ss_size;
4211 + } else {
4212 + struct rlimit limits;
4213 + getrlimit(RLIMIT_STACK, &limits);
4214 + size = adjust_stack_size(os::Solaris::_main_stack_base, (size_t)limits.rlim_cur);
4216 + // base may not be page aligned
4217 + address base = current_stack_base();
4218 + address bottom = align_up(base - size, os::vm_page_size());;
4219 + return (size_t)(base - bottom);
4222 +void os::current_stack_base_and_size(address* stack_base, size_t* stack_size) {
4223 + *stack_base = os::Solaris::current_stack_base();
4224 + *stack_size = os::Solaris::current_stack_size();
4227 +jint os::Solaris::_os_thread_limit = 0;
4228 +volatile jint os::Solaris::_os_thread_count = 0;
4230 +julong os::available_memory() {
4231 + return Solaris::available_memory();
4234 +julong os::free_memory() {
4235 + return Solaris::available_memory();
4238 +julong os::Solaris::available_memory() {
4239 + return (julong)sysconf(_SC_AVPHYS_PAGES) * os::vm_page_size();
4242 +julong os::Solaris::_physical_memory = 0;
4244 +jlong os::total_swap_space() {
4245 + struct anoninfo ai;
4246 + pgcnt_t allocated, reserved, available;
4247 + int ret = swapctl(SC_AINFO, &ai);
4248 + if (ret == -1) {
4249 + return -1;
4251 + return (jlong)(ai.ani_max * sysconf(_SC_PAGESIZE));
4254 +jlong os::free_swap_space() {
4255 + struct anoninfo ai;
4256 + int ret = swapctl(SC_AINFO, &ai);
4257 + if (ret == -1) {
4258 + return -1;
4260 + return (jlong)(ai.ani_free * sysconf(_SC_PAGESIZE));
4263 +julong os::physical_memory() {
4264 + return Solaris::physical_memory();
4267 +static hrtime_t first_hrtime = 0;
4268 +static const hrtime_t hrtime_hz = 1000*1000*1000;
4269 +static volatile hrtime_t max_hrtime = 0;
4272 +void os::Solaris::initialize_system_info() {
4273 + set_processor_count(sysconf(_SC_NPROCESSORS_CONF));
4274 + _physical_memory = (julong)sysconf(_SC_PHYS_PAGES) *
4275 + (julong)sysconf(_SC_PAGESIZE);
4278 +uint os::processor_id() {
4279 + const processorid_t id = ::getcpuid();
4280 + assert(id >= 0 && id < _processor_count, "Invalid processor id");
4281 + return (uint)id;
4284 +int os::active_processor_count() {
4285 + // User has overridden the number of active processors
4286 + if (ActiveProcessorCount > 0) {
4287 + log_trace(os)("active_processor_count: "
4288 + "active processor count set by user : %d",
4289 + ActiveProcessorCount);
4290 + return ActiveProcessorCount;
4293 + int online_cpus = sysconf(_SC_NPROCESSORS_ONLN);
4294 + pid_t pid = getpid();
4295 + psetid_t pset = PS_NONE;
4296 + // Are we running in a processor set or is there any processor set around?
4297 + if (pset_bind(PS_QUERY, P_PID, pid, &pset) == 0) {
4298 + uint_t pset_cpus;
4299 + // Query the number of cpus available to us.
4300 + if (pset_info(pset, NULL, &pset_cpus, NULL) == 0) {
4301 + assert(pset_cpus > 0 && pset_cpus <= online_cpus, "sanity check");
4302 + return pset_cpus;
4305 + // Otherwise return number of online cpus
4306 + return online_cpus;
4309 +void os::set_native_thread_name(const char *name) {
4310 + if (Solaris::_pthread_setname_np != NULL) {
4311 + // Only the first 31 bytes of 'name' are processed by pthread_setname_np
4312 + // but we explicitly copy into a size-limited buffer to avoid any
4313 + // possible overflow.
4314 + char buf[32];
4315 + snprintf(buf, sizeof(buf), "%s", name);
4316 + buf[sizeof(buf) - 1] = '\0';
4317 + Solaris::_pthread_setname_np(pthread_self(), buf);
4321 +void os::init_system_properties_values() {
4322 + // The next steps are taken in the product version:
4323 + //
4324 + // Obtain the JAVA_HOME value from the location of libjvm.so.
4325 + // This library should be located at:
4326 + // <JAVA_HOME>/jre/lib/<arch>/{client|server}/libjvm.so.
4327 + //
4328 + // If "/jre/lib/" appears at the right place in the path, then we
4329 + // assume libjvm.so is installed in a JDK and we use this path.
4330 + //
4331 + // Otherwise exit with message: "Could not create the Java virtual machine."
4332 + //
4333 + // The following extra steps are taken in the debugging version:
4334 + //
4335 + // If "/jre/lib/" does NOT appear at the right place in the path
4336 + // instead of exit check for $JAVA_HOME environment variable.
4337 + //
4338 + // If it is defined and we are able to locate $JAVA_HOME/jre/lib/<arch>,
4339 + // then we append a fake suffix "hotspot/libjvm.so" to this path so
4340 + // it looks like libjvm.so is installed there
4341 + // <JAVA_HOME>/jre/lib/<arch>/hotspot/libjvm.so.
4342 + //
4343 + // Otherwise exit.
4344 + //
4345 + // Important note: if the location of libjvm.so changes this
4346 + // code needs to be changed accordingly.
4348 +// Base path of extensions installed on the system.
4349 +#define SYS_EXT_DIR "/usr/jdk/packages"
4350 +#define EXTENSIONS_DIR "/lib/ext"
4352 + // Buffer that fits several sprintfs.
4353 + // Note that the space for the colon and the trailing null are provided
4354 + // by the nulls included by the sizeof operator.
4355 + const size_t bufsize =
4356 + MAX3((size_t)MAXPATHLEN, // For dll_dir & friends.
4357 + sizeof(SYS_EXT_DIR) + sizeof("/lib/"), // invariant ld_library_path
4358 + (size_t)MAXPATHLEN + sizeof(EXTENSIONS_DIR) + sizeof(SYS_EXT_DIR) + sizeof(EXTENSIONS_DIR)); // extensions dir
4359 + char *buf = NEW_C_HEAP_ARRAY(char, bufsize, mtInternal);
4361 + // sysclasspath, java_home, dll_dir
4363 + char *pslash;
4364 + os::jvm_path(buf, bufsize);
4366 + // Found the full path to libjvm.so.
4367 + // Now cut the path to <java_home>/jre if we can.
4368 + *(strrchr(buf, '/')) = '\0'; // Get rid of /libjvm.so.
4369 + pslash = strrchr(buf, '/');
4370 + if (pslash != NULL) {
4371 + *pslash = '\0'; // Get rid of /{client|server|hotspot}.
4373 + Arguments::set_dll_dir(buf);
4375 + if (pslash != NULL) {
4376 + pslash = strrchr(buf, '/');
4377 + if (pslash != NULL) {
4378 + *pslash = '\0'; // Get rid of /lib.
4381 + Arguments::set_java_home(buf);
4382 + if (!set_boot_path('/', ':')) {
4383 + vm_exit_during_initialization("Failed setting boot class path.", NULL);
4387 + // Where to look for native libraries.
4389 + // Use dlinfo() to determine the correct java.library.path.
4390 + //
4391 + // If we're launched by the Java launcher, and the user
4392 + // does not set java.library.path explicitly on the commandline,
4393 + // the Java launcher sets LD_LIBRARY_PATH for us and unsets
4394 + // LD_LIBRARY_PATH_32 and LD_LIBRARY_PATH_64. In this case
4395 + // dlinfo returns LD_LIBRARY_PATH + crle settings (including
4396 + // /usr/lib), which is exactly what we want.
4397 + //
4398 + // If the user does set java.library.path, it completely
4399 + // overwrites this setting, and always has.
4400 + //
4401 + // If we're not launched by the Java launcher, we may
4402 + // get here with any/all of the LD_LIBRARY_PATH[_32|64]
4403 + // settings. Again, dlinfo does exactly what we want.
4405 + Dl_serinfo info_sz, *info = &info_sz;
4406 + Dl_serpath *path;
4407 + char *library_path;
4408 + char *common_path = buf;
4410 + // Determine search path count and required buffer size.
4411 + if (dlinfo(RTLD_SELF, RTLD_DI_SERINFOSIZE, (void *)info) == -1) {
4412 + FREE_C_HEAP_ARRAY(char, buf);
4413 + vm_exit_during_initialization("dlinfo SERINFOSIZE request", dlerror());
4416 + // Allocate new buffer and initialize.
4417 + info = (Dl_serinfo*)NEW_C_HEAP_ARRAY(char, info_sz.dls_size, mtInternal);
4418 + info->dls_size = info_sz.dls_size;
4419 + info->dls_cnt = info_sz.dls_cnt;
4421 + // Obtain search path information.
4422 + if (dlinfo(RTLD_SELF, RTLD_DI_SERINFO, (void *)info) == -1) {
4423 + FREE_C_HEAP_ARRAY(char, buf);
4424 + FREE_C_HEAP_ARRAY(char, info);
4425 + vm_exit_during_initialization("dlinfo SERINFO request", dlerror());
4428 + path = &info->dls_serpath[0];
4430 + // Note: Due to a legacy implementation, most of the library path
4431 + // is set in the launcher. This was to accommodate linking restrictions
4432 + // on legacy Solaris implementations (which are no longer supported).
4433 + // Eventually, all the library path setting will be done here.
4434 + //
4435 + // However, to prevent the proliferation of improperly built native
4436 + // libraries, the new path component /usr/jdk/packages is added here.
4438 + // Construct the invariant part of ld_library_path.
4439 + sprintf(common_path, SYS_EXT_DIR "/lib");
4441 + // Struct size is more than sufficient for the path components obtained
4442 + // through the dlinfo() call, so only add additional space for the path
4443 + // components explicitly added here.
4444 + size_t library_path_size = info->dls_size + strlen(common_path);
4445 + library_path = NEW_C_HEAP_ARRAY(char, library_path_size, mtInternal);
4446 + library_path[0] = '\0';
4448 + // Construct the desired Java library path from the linker's library
4449 + // search path.
4450 + //
4451 + // For compatibility, it is optimal that we insert the additional path
4452 + // components specific to the Java VM after those components specified
4453 + // in LD_LIBRARY_PATH (if any) but before those added by the ld.so
4454 + // infrastructure.
4455 + if (info->dls_cnt == 0) { // Not sure this can happen, but allow for it.
4456 + strcpy(library_path, common_path);
4457 + } else {
4458 + int inserted = 0;
4459 + uint_t i;
4460 + for (i = 0; i < info->dls_cnt; i++, path++) {
4461 + uint_t flags = path->dls_flags & LA_SER_MASK;
4462 + if (((flags & LA_SER_LIBPATH) == 0) && !inserted) {
4463 + strcat(library_path, common_path);
4464 + strcat(library_path, os::path_separator());
4465 + inserted = 1;
4467 + strcat(library_path, path->dls_name);
4468 + strcat(library_path, os::path_separator());
4470 + // Eliminate trailing path separator.
4471 + library_path[strlen(library_path)-1] = '\0';
4474 + // happens before argument parsing - can't use a trace flag
4475 + // tty->print_raw("init_system_properties_values: native lib path: ");
4476 + // tty->print_raw_cr(library_path);
4478 + // Callee copies into its own buffer.
4479 + Arguments::set_library_path(library_path);
4481 + FREE_C_HEAP_ARRAY(char, library_path);
4482 + FREE_C_HEAP_ARRAY(char, info);
4485 + // Extensions directories.
4486 + sprintf(buf, "%s" EXTENSIONS_DIR ":" SYS_EXT_DIR EXTENSIONS_DIR, Arguments::get_java_home());
4487 + Arguments::set_ext_dirs(buf);
4489 + FREE_C_HEAP_ARRAY(char, buf);
4491 +#undef SYS_EXT_DIR
4492 +#undef EXTENSIONS_DIR
4495 +static thread_t main_thread;
4497 +// Thread start routine for all newly created threads
4498 +extern "C" void* thread_native_entry(void* thread_addr) {
4500 + Thread* thread = (Thread*)thread_addr;
4502 + thread->record_stack_base_and_size();
4504 + // Try to randomize the cache line index of hot stack frames.
4505 + // This helps when threads of the same stack traces evict each other's
4506 + // cache lines. The threads can be either from the same JVM instance, or
4507 + // from different JVM instances. The benefit is especially true for
4508 + // processors with hyperthreading technology.
4509 + static int counter = 0;
4510 + int pid = os::current_process_id();
4511 + alloca(((pid ^ counter++) & 7) * 128);
4513 + int prio;
4515 + thread->initialize_thread_current();
4517 + OSThread* osthr = thread->osthread();
4519 + osthr->set_lwp_id(_lwp_self()); // Store lwp in case we are bound
4521 + log_info(os, thread)("Thread is alive (tid: " UINTX_FORMAT ").",
4522 + os::current_thread_id());
4524 + if (UseNUMA) {
4525 + int lgrp_id = os::numa_get_group_id();
4526 + if (lgrp_id != -1) {
4527 + thread->set_lgrp_id(lgrp_id);
4531 + // Our priority was set when we were created, and stored in the
4532 + // osthread, but couldn't be passed through to our LWP until now.
4533 + // So read back the priority and set it again.
4535 + if (osthr->thread_id() != -1) {
4536 + if (UseThreadPriorities) {
4537 + int prio = osthr->native_priority();
4538 + os::set_native_priority(thread, prio);
4542 + assert(osthr->get_state() == RUNNABLE, "invalid os thread state");
4544 + // initialize signal mask for this thread
4545 + PosixSignals::hotspot_sigmask(thread);
4547 + os::Solaris::init_thread_fpu_state();
4549 + thread->call_run();
4551 + // Note: at this point the thread object may already have deleted itself.
4552 + // Do not dereference it from here on out.
4554 + // One less thread is executing
4555 + // When the VMThread gets here, the main thread may have already exited
4556 + // which frees the CodeHeap containing the Atomic::dec code
4557 + if (thread != VMThread::vm_thread() && VMThread::vm_thread() != NULL) {
4558 + Atomic::dec(&os::Solaris::_os_thread_count);
4561 + log_info(os, thread)("Thread finished (tid: " UINTX_FORMAT ").", os::current_thread_id());
4563 + thr_exit(NULL);
4564 + ShouldNotReachHere();
4566 + return NULL;
4569 +static OSThread* create_os_thread(Thread* thread, thread_t thread_id) {
4570 + // Allocate the OSThread object
4571 + OSThread* osthread = new OSThread();
4572 + if (osthread == NULL) return NULL;
4574 + // Store info on the Solaris thread into the OSThread
4575 + osthread->set_thread_id(thread_id);
4576 + osthread->set_lwp_id(_lwp_self());
4578 + if (UseNUMA) {
4579 + int lgrp_id = os::numa_get_group_id();
4580 + if (lgrp_id != -1) {
4581 + thread->set_lgrp_id(lgrp_id);
4585 + // Initial thread state is INITIALIZED, not SUSPENDED
4586 + osthread->set_state(INITIALIZED);
4588 + return osthread;
4591 +bool os::create_attached_thread(JavaThread* thread) {
4592 +#ifdef ASSERT
4593 + thread->verify_not_published();
4594 +#endif
4595 + OSThread* osthread = create_os_thread(thread, thr_self());
4596 + if (osthread == NULL) {
4597 + return false;
4600 + // Initial thread state is RUNNABLE
4601 + osthread->set_state(RUNNABLE);
4602 + thread->set_osthread(osthread);
4604 + if (os::is_primordial_thread()) {
4605 + os::Solaris::correct_stack_boundaries_for_primordial_thread(thread);
4608 + // initialize signal mask for this thread
4609 + // and save the caller's signal mask
4610 + PosixSignals::hotspot_sigmask(thread);
4612 + log_info(os, thread)("Thread attached (tid: " UINTX_FORMAT ").",
4613 + os::current_thread_id());
4615 + return true;
4618 +bool os::create_main_thread(JavaThread* thread) {
4619 +#ifdef ASSERT
4620 + thread->verify_not_published();
4621 +#endif
4622 + if (_starting_thread == NULL) {
4623 + _starting_thread = create_os_thread(thread, main_thread);
4624 + if (_starting_thread == NULL) {
4625 + return false;
4629 + // The primodial thread is runnable from the start
4630 + _starting_thread->set_state(RUNNABLE);
4632 + thread->set_osthread(_starting_thread);
4634 + // initialize signal mask for this thread
4635 + // and save the caller's signal mask
4636 + PosixSignals::hotspot_sigmask(thread);
4638 + return true;
4641 +// Helper function to trace thread attributes, similar to os::Posix::describe_pthread_attr()
4642 +static char* describe_thr_create_attributes(char* buf, size_t buflen,
4643 + size_t stacksize, long flags) {
4644 + stringStream ss(buf, buflen);
4645 + ss.print("stacksize: " SIZE_FORMAT "k, ", stacksize / 1024);
4646 + ss.print("flags: ");
4647 + #define PRINT_FLAG(f) if (flags & f) ss.print( #f " ");
4648 + #define ALL(X) \
4649 + X(THR_SUSPENDED) \
4650 + X(THR_DETACHED) \
4651 + X(THR_BOUND) \
4652 + X(THR_NEW_LWP) \
4653 + X(THR_DAEMON)
4654 + ALL(PRINT_FLAG)
4655 + #undef ALL
4656 + #undef PRINT_FLAG
4657 + return buf;
4660 +// return default stack size for thr_type
4661 +size_t os::Posix::default_stack_size(os::ThreadType thr_type) {
4662 + // default stack size when not specified by caller is 1M (2M for LP64)
4663 + size_t s = (BytesPerWord >> 2) * K * K;
4664 + return s;
4667 +bool os::create_thread(Thread* thread, ThreadType thr_type,
4668 + size_t req_stack_size) {
4669 + // Allocate the OSThread object
4670 + OSThread* osthread = new OSThread();
4671 + if (osthread == NULL) {
4672 + return false;
4675 + // calculate stack size if it's not specified by caller
4676 + size_t stack_size = os::Posix::get_initial_stack_size(thr_type, req_stack_size);
4678 + // Initial state is ALLOCATED but not INITIALIZED
4679 + osthread->set_state(ALLOCATED);
4681 + if (os::Solaris::_os_thread_count > os::Solaris::_os_thread_limit) {
4682 + // We got lots of threads. Check if we still have some address space left.
4683 + // Need to be at least 5Mb of unreserved address space. We do check by
4684 + // trying to reserve some.
4685 + const size_t VirtualMemoryBangSize = 20*K*K;
4686 + char* mem = os::reserve_memory(VirtualMemoryBangSize);
4687 + if (mem == NULL) {
4688 + delete osthread;
4689 + return false;
4690 + } else {
4691 + // Release the memory again
4692 + os::release_memory(mem, VirtualMemoryBangSize);
4696 + // Setup osthread because the child thread may need it.
4697 + thread->set_osthread(osthread);
4699 + // Create the Solaris thread
4700 + thread_t tid = 0;
4701 + long flags = THR_DETACHED | THR_SUSPENDED;
4702 + int status;
4704 + // Mark that we don't have an lwp or thread id yet.
4705 + // In case we attempt to set the priority before the thread starts.
4706 + osthread->set_lwp_id(-1);
4707 + osthread->set_thread_id(-1);
4709 + status = thr_create(NULL, stack_size, thread_native_entry, thread, flags, &tid);
4711 + char buf[64];
4712 + if (status == 0) {
4713 + log_info(os, thread)("Thread \"%s\" started (tid: " UINTX_FORMAT ", attributes: %s). ",
4714 + thread->name(), (uintx) tid, describe_thr_create_attributes(buf, sizeof(buf), stack_size, flags));
4715 + } else {
4716 + log_warning(os, thread)("Failed to start thread \"%s\" - thr_create failed (%s) for attributes: %s.",
4717 + thread->name(), os::errno_name(status), describe_thr_create_attributes(buf, sizeof(buf), stack_size, flags));
4718 + // Log some OS information which might explain why creating the thread failed.
4719 + log_info(os, thread)("Number of threads approx. running in the VM: %d", Threads::number_of_threads());
4720 + LogStream st(Log(os, thread)::info());
4721 + os::Posix::print_rlimit_info(&st);
4722 + os::print_memory_info(&st);
4725 + if (status != 0) {
4726 + thread->set_osthread(NULL);
4727 + // Need to clean up stuff we've allocated so far
4728 + delete osthread;
4729 + return false;
4732 + Atomic::inc(&os::Solaris::_os_thread_count);
4734 + // Store info on the Solaris thread into the OSThread
4735 + osthread->set_thread_id(tid);
4737 + // Remember that we created this thread so we can set priority on it
4738 + osthread->set_vm_created();
4740 + // Most thread types will set an explicit priority before starting the thread,
4741 + // but for those that don't we need a valid value to read back in thread_native_entry.
4742 + osthread->set_native_priority(NormPriority);
4744 + // Initial thread state is INITIALIZED, not SUSPENDED
4745 + osthread->set_state(INITIALIZED);
4747 + // The thread is returned suspended (in state INITIALIZED), and is started higher up in the call chain
4748 + return true;
4751 +// CR 7190089: on Solaris, primordial thread's stack needs adjusting.
4752 +// Without the adjustment, stack size is incorrect if stack is set to unlimited (ulimit -s unlimited).
4753 +void os::Solaris::correct_stack_boundaries_for_primordial_thread(Thread* thr) {
4754 + assert(is_primordial_thread(), "Call only for primordial thread");
4756 + JavaThread* jt = (JavaThread *)thr;
4757 + assert(jt != NULL, "Sanity check");
4758 + size_t stack_size;
4759 + address base = jt->stack_base();
4760 + if (Arguments::created_by_java_launcher()) {
4761 + // Use 2MB to allow for Solaris 7 64 bit mode.
4762 + stack_size = JavaThread::stack_size_at_create() == 0
4763 + ? 2048*K : JavaThread::stack_size_at_create();
4765 + // There are rare cases when we may have already used more than
4766 + // the basic stack size allotment before this method is invoked.
4767 + // Attempt to allow for a normally sized java_stack.
4768 + size_t current_stack_offset = (size_t)(base - (address)&stack_size);
4769 + stack_size += ReservedSpace::page_align_size_down(current_stack_offset);
4770 + } else {
4771 + // 6269555: If we were not created by a Java launcher, i.e. if we are
4772 + // running embedded in a native application, treat the primordial thread
4773 + // as much like a native attached thread as possible. This means using
4774 + // the current stack size from thr_stksegment(), unless it is too large
4775 + // to reliably setup guard pages. A reasonable max size is 8MB.
4776 + size_t current_size = current_stack_size();
4777 + // This should never happen, but just in case....
4778 + if (current_size == 0) current_size = 2 * K * K;
4779 + stack_size = current_size > (8 * K * K) ? (8 * K * K) : current_size;
4781 + address bottom = align_up(base - stack_size, os::vm_page_size());;
4782 + stack_size = (size_t)(base - bottom);
4784 + assert(stack_size > 0, "Stack size calculation problem");
4786 + if (stack_size > jt->stack_size()) {
4787 +#ifndef PRODUCT
4788 + struct rlimit limits;
4789 + getrlimit(RLIMIT_STACK, &limits);
4790 + size_t size = adjust_stack_size(base, (size_t)limits.rlim_cur);
4791 + assert(size >= jt->stack_size(), "Stack size problem in main thread");
4792 +#endif
4793 + tty->print_cr("Stack size of " SIZE_FORMAT " Kb exceeds current limit of " SIZE_FORMAT " Kb.\n"
4794 + "(Stack sizes are rounded up to a multiple of the system page size.)\n"
4795 + "See limit(1) to increase the stack size limit.",
4796 + stack_size / K, jt->stack_size() / K);
4797 + vm_exit(1);
4799 + assert(jt->stack_size() >= stack_size,
4800 + "Attempt to map more stack than was allocated");
4801 + jt->set_stack_size(stack_size);
4807 +// Free Solaris resources related to the OSThread
4808 +void os::free_thread(OSThread* osthread) {
4809 + assert(osthread != NULL, "os::free_thread but osthread not set");
4811 + // We are told to free resources of the argument thread,
4812 + // but we can only really operate on the current thread.
4813 + assert(Thread::current()->osthread() == osthread,
4814 + "os::free_thread but not current thread");
4816 + // Restore caller's signal mask
4817 + sigset_t sigmask = osthread->caller_sigmask();
4818 + pthread_sigmask(SIG_SETMASK, &sigmask, NULL);
4820 + delete osthread;
4823 +void os::pd_start_thread(Thread* thread) {
4824 + int status = thr_continue(thread->osthread()->thread_id());
4825 + assert_status(status == 0, status, "thr_continue failed");
4829 +intx os::current_thread_id() {
4830 + return (intx)thr_self();
4833 +static pid_t _initial_pid = 0;
4835 +int os::current_process_id() {
4836 + return (int)(_initial_pid ? _initial_pid : getpid());
4839 +// gethrtime() should be monotonic according to the documentation,
4840 +// but some virtualized platforms are known to break this guarantee.
4841 +// getTimeNanos() must be guaranteed not to move backwards, so we
4842 +// are forced to add a check here.
4843 +inline hrtime_t getTimeNanos() {
4844 + const hrtime_t now = gethrtime();
4845 + const hrtime_t prev = max_hrtime;
4846 + if (now <= prev) {
4847 + return prev; // same or retrograde time;
4849 + const hrtime_t obsv = Atomic::cmpxchg(&max_hrtime, prev, now);
4850 + assert(obsv >= prev, "invariant"); // Monotonicity
4851 + // If the CAS succeeded then we're done and return "now".
4852 + // If the CAS failed and the observed value "obsv" is >= now then
4853 + // we should return "obsv". If the CAS failed and now > obsv > prv then
4854 + // some other thread raced this thread and installed a new value, in which case
4855 + // we could either (a) retry the entire operation, (b) retry trying to install now
4856 + // or (c) just return obsv. We use (c). No loop is required although in some cases
4857 + // we might discard a higher "now" value in deference to a slightly lower but freshly
4858 + // installed obsv value. That's entirely benign -- it admits no new orderings compared
4859 + // to (a) or (b) -- and greatly reduces coherence traffic.
4860 + // We might also condition (c) on the magnitude of the delta between obsv and now.
4861 + // Avoiding excessive CAS operations to hot RW locations is critical.
4862 + // See https://blogs.oracle.com/dave/entry/cas_and_cache_trivia_invalidate
4863 + return (prev == obsv) ? now : obsv;
4866 +double os::elapsedVTime() {
4867 + return (double)gethrvtime() / (double)hrtime_hz;
4870 +// DLL functions
4872 +// This must be hard coded because it's the system's temporary
4873 +// directory not the java application's temp directory, ala java.io.tmpdir.
4874 +const char* os::get_temp_directory() { return "/tmp"; }
4876 +// check if addr is inside libjvm.so
4877 +bool os::address_is_in_vm(address addr) {
4878 + static address libjvm_base_addr;
4879 + Dl_info dlinfo;
4881 + if (libjvm_base_addr == NULL) {
4882 + if (dladdr(CAST_FROM_FN_PTR(void *, os::address_is_in_vm), &dlinfo) != 0) {
4883 + libjvm_base_addr = (address)dlinfo.dli_fbase;
4885 + assert(libjvm_base_addr !=NULL, "Cannot obtain base address for libjvm");
4888 + if (dladdr((void *)addr, &dlinfo) != 0) {
4889 + if (libjvm_base_addr == (address)dlinfo.dli_fbase) return true;
4892 + return false;
4895 +void os::prepare_native_symbols() {
4898 +bool os::dll_address_to_function_name(address addr, char *buf,
4899 + int buflen, int * offset,
4900 + bool demangle) {
4901 + // buf is not optional, but offset is optional
4902 + assert(buf != NULL, "sanity check");
4904 + Dl_info dlinfo;
4906 +#ifdef _LP64
4907 + Elf64_Sym * info;
4908 +#else
4909 + Elf32_Sym * info;
4910 +#endif
4911 + if (dladdr1((void *)addr, &dlinfo, (void **)&info,
4912 + RTLD_DL_SYMENT) != 0) {
4913 + // see if we have a matching symbol that covers our address
4914 + if (dlinfo.dli_saddr != NULL &&
4915 + (char *)dlinfo.dli_saddr + info->st_size > (char *)addr) {
4916 + if (dlinfo.dli_sname != NULL) {
4917 + if (!(demangle && Decoder::demangle(dlinfo.dli_sname, buf, buflen))) {
4918 + jio_snprintf(buf, buflen, "%s", dlinfo.dli_sname);
4920 + if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr;
4921 + return true;
4924 + // no matching symbol so try for just file info
4925 + if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != NULL) {
4926 + if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
4927 + buf, buflen, offset, dlinfo.dli_fname, demangle)) {
4928 + return true;
4932 + buf[0] = '\0';
4933 + if (offset != NULL) *offset = -1;
4934 + return false;
4937 +bool os::dll_address_to_library_name(address addr, char* buf,
4938 + int buflen, int* offset) {
4939 + // buf is not optional, but offset is optional
4940 + assert(buf != NULL, "sanity check");
4942 + Dl_info dlinfo;
4944 + if (dladdr((void*)addr, &dlinfo) != 0) {
4945 + if (dlinfo.dli_fname != NULL) {
4946 + jio_snprintf(buf, buflen, "%s", dlinfo.dli_fname);
4948 + if (dlinfo.dli_fbase != NULL && offset != NULL) {
4949 + *offset = addr - (address)dlinfo.dli_fbase;
4951 + return true;
4954 + buf[0] = '\0';
4955 + if (offset) *offset = -1;
4956 + return false;
4959 +int os::get_loaded_modules_info(os::LoadedModulesCallbackFunc callback, void *param) {
4960 + Dl_info dli;
4961 + // Sanity check?
4962 + if (dladdr(CAST_FROM_FN_PTR(void *, os::get_loaded_modules_info), &dli) == 0 ||
4963 + dli.dli_fname == NULL) {
4964 + return 1;
4967 + void * handle = dlopen(dli.dli_fname, RTLD_LAZY);
4968 + if (handle == NULL) {
4969 + return 1;
4972 + Link_map *map;
4973 + dlinfo(handle, RTLD_DI_LINKMAP, &map);
4974 + if (map == NULL) {
4975 + dlclose(handle);
4976 + return 1;
4979 + while (map->l_prev != NULL) {
4980 + map = map->l_prev;
4983 + while (map != NULL) {
4984 + // Iterate through all map entries and call callback with fields of interest
4985 + if(callback(map->l_name, (address)map->l_addr, (address)0, param)) {
4986 + dlclose(handle);
4987 + return 1;
4989 + map = map->l_next;
4992 + dlclose(handle);
4993 + return 0;
4996 +int _print_dll_info_cb(const char * name, address base_address, address top_address, void * param) {
4997 + outputStream * out = (outputStream *) param;
4998 + out->print_cr(INTPTR_FORMAT " \t%s", (intptr_t)base_address, name);
4999 + return 0;
5002 +void os::print_dll_info(outputStream * st) {
5003 + st->print_cr("Dynamic libraries:"); st->flush();
5004 + if (get_loaded_modules_info(_print_dll_info_cb, (void *)st)) {
5005 + st->print_cr("Error: Cannot print dynamic libraries.");
5009 +static void change_endianness(Elf32_Half& val) {
5010 + unsigned char *ptr = (unsigned char *)&val;
5011 + unsigned char swp = ptr[0];
5012 + ptr[0] = ptr[1];
5013 + ptr[1] = swp;
5016 +// Loads .dll/.so and
5017 +// in case of error it checks if .dll/.so was built for the
5018 +// same architecture as Hotspot is running on
5020 +void * os::dll_load(const char *filename, char *ebuf, int ebuflen) {
5021 + log_info(os)("attempting shared library load of %s", filename);
5023 + void * result= ::dlopen(filename, RTLD_LAZY);
5024 + if (result != NULL) {
5025 + // Successful loading
5026 + Events::log(NULL, "Loaded shared library %s", filename);
5027 + log_info(os)("shared library load of %s was successful", filename);
5028 + return result;
5031 + Elf32_Ehdr elf_head;
5032 + const char* error_report = ::dlerror();
5033 + if (error_report == NULL) {
5034 + error_report = "dlerror returned no error description";
5036 + if (ebuf != NULL && ebuflen > 0) {
5037 + ::strncpy(ebuf, error_report, ebuflen-1);
5038 + ebuf[ebuflen-1]='\0';
5041 + Events::log(NULL, "Loading shared library %s failed, %s", filename, error_report);
5042 + log_info(os)("shared library load of %s failed, %s", filename, error_report);
5044 + int diag_msg_max_length=ebuflen-strlen(ebuf);
5045 + char* diag_msg_buf=ebuf+strlen(ebuf);
5047 + if (diag_msg_max_length==0) {
5048 + // No more space in ebuf for additional diagnostics message
5049 + return NULL;
5053 + int file_descriptor= ::open(filename, O_RDONLY | O_NONBLOCK);
5055 + if (file_descriptor < 0) {
5056 + // Can't open library, report dlerror() message
5057 + return NULL;
5060 + bool failed_to_read_elf_head=
5061 + (sizeof(elf_head)!=
5062 + (::read(file_descriptor, &elf_head,sizeof(elf_head))));
5064 + ::close(file_descriptor);
5065 + if (failed_to_read_elf_head) {
5066 + // file i/o error - report dlerror() msg
5067 + return NULL;
5070 + if (elf_head.e_ident[EI_DATA] != LITTLE_ENDIAN_ONLY(ELFDATA2LSB) BIG_ENDIAN_ONLY(ELFDATA2MSB)) {
5071 + // handle invalid/out of range endianness values
5072 + if (elf_head.e_ident[EI_DATA] == 0 || elf_head.e_ident[EI_DATA] > 2) {
5073 + return NULL;
5075 + change_endianness(elf_head.e_machine);
5078 + typedef struct {
5079 + Elf32_Half code; // Actual value as defined in elf.h
5080 + Elf32_Half compat_class; // Compatibility of archs at VM's sense
5081 + unsigned char elf_class; // 32 or 64 bit
5082 + unsigned char endianess; // MSB or LSB
5083 + char* name; // String representation
5084 + } arch_t;
5086 + static const arch_t arch_array[]={
5087 + {EM_386, EM_386, ELFCLASS32, ELFDATA2LSB, (char*)"IA 32"},
5088 + {EM_486, EM_386, ELFCLASS32, ELFDATA2LSB, (char*)"IA 32"},
5089 + {EM_IA_64, EM_IA_64, ELFCLASS64, ELFDATA2LSB, (char*)"IA 64"},
5090 + {EM_X86_64, EM_X86_64, ELFCLASS64, ELFDATA2LSB, (char*)"AMD 64"},
5091 + {EM_SPARC, EM_SPARC, ELFCLASS32, ELFDATA2MSB, (char*)"Sparc 32"},
5092 + {EM_SPARC32PLUS, EM_SPARC, ELFCLASS32, ELFDATA2MSB, (char*)"Sparc 32"},
5093 + {EM_SPARCV9, EM_SPARCV9, ELFCLASS64, ELFDATA2MSB, (char*)"Sparc v9 64"},
5094 + {EM_PPC, EM_PPC, ELFCLASS32, ELFDATA2MSB, (char*)"Power PC 32"},
5095 + {EM_PPC64, EM_PPC64, ELFCLASS64, ELFDATA2MSB, (char*)"Power PC 64"},
5096 + {EM_ARM, EM_ARM, ELFCLASS32, ELFDATA2LSB, (char*)"ARM"},
5097 + // we only support 64 bit z architecture
5098 + {EM_S390, EM_S390, ELFCLASS64, ELFDATA2MSB, (char*)"IBM System/390"},
5099 + {EM_AARCH64, EM_AARCH64, ELFCLASS64, ELFDATA2LSB, (char*)"AARCH64"}
5100 + };
5102 +#if (defined IA32)
5103 + static Elf32_Half running_arch_code=EM_386;
5104 +#elif (defined AMD64)
5105 + static Elf32_Half running_arch_code=EM_X86_64;
5106 +#elif (defined IA64)
5107 + static Elf32_Half running_arch_code=EM_IA_64;
5108 +#elif (defined __sparc) && (defined _LP64)
5109 + static Elf32_Half running_arch_code=EM_SPARCV9;
5110 +#elif (defined __sparc) && (!defined _LP64)
5111 + static Elf32_Half running_arch_code=EM_SPARC;
5112 +#elif (defined __powerpc64__)
5113 + static Elf32_Half running_arch_code=EM_PPC64;
5114 +#elif (defined __powerpc__)
5115 + static Elf32_Half running_arch_code=EM_PPC;
5116 +#elif (defined ARM)
5117 + static Elf32_Half running_arch_code=EM_ARM;
5118 +#else
5119 + #error Method os::dll_load requires that one of following is defined:\
5120 + IA32, AMD64, IA64, __sparc, __powerpc__, ARM, ARM
5121 +#endif
5123 + // Identify compatibility class for VM's architecture and library's architecture
5124 + // Obtain string descriptions for architectures
5126 + arch_t lib_arch={elf_head.e_machine,0,elf_head.e_ident[EI_CLASS], elf_head.e_ident[EI_DATA], NULL};
5127 + int running_arch_index=-1;
5129 + for (unsigned int i=0; i < ARRAY_SIZE(arch_array); i++) {
5130 + if (running_arch_code == arch_array[i].code) {
5131 + running_arch_index = i;
5133 + if (lib_arch.code == arch_array[i].code) {
5134 + lib_arch.compat_class = arch_array[i].compat_class;
5135 + lib_arch.name = arch_array[i].name;
5139 + assert(running_arch_index != -1,
5140 + "Didn't find running architecture code (running_arch_code) in arch_array");
5141 + if (running_arch_index == -1) {
5142 + // Even though running architecture detection failed
5143 + // we may still continue with reporting dlerror() message
5144 + return NULL;
5147 + if (lib_arch.compat_class != arch_array[running_arch_index].compat_class) {
5148 + if (lib_arch.name != NULL) {
5149 + ::snprintf(diag_msg_buf, diag_msg_max_length-1,
5150 + " (Possible cause: can't load %s .so on a %s platform)",
5151 + lib_arch.name, arch_array[running_arch_index].name);
5152 + } else {
5153 + ::snprintf(diag_msg_buf, diag_msg_max_length-1,
5154 + " (Possible cause: can't load this .so (machine code=0x%x) on a %s platform)",
5155 + lib_arch.code, arch_array[running_arch_index].name);
5157 + return NULL;
5160 + if (lib_arch.endianess != arch_array[running_arch_index].endianess) {
5161 + ::snprintf(diag_msg_buf, diag_msg_max_length-1," (Possible cause: endianness mismatch)");
5162 + return NULL;
5165 + // ELF file class/capacity : 0 - invalid, 1 - 32bit, 2 - 64bit
5166 + if (lib_arch.elf_class > 2 || lib_arch.elf_class < 1) {
5167 + ::snprintf(diag_msg_buf, diag_msg_max_length-1, " (Possible cause: invalid ELF file class)");
5168 + return NULL;
5171 + if (lib_arch.elf_class != arch_array[running_arch_index].elf_class) {
5172 + ::snprintf(diag_msg_buf, diag_msg_max_length-1,
5173 + " (Possible cause: architecture word width mismatch, can't load %d-bit .so on a %d-bit platform)",
5174 + (int) lib_arch.elf_class * 32, arch_array[running_arch_index].elf_class * 32);
5175 + return NULL;
5178 + return NULL;
5181 +static inline time_t get_mtime(const char* filename) {
5182 + struct stat st;
5183 + int ret = os::stat(filename, &st);
5184 + assert(ret == 0, "failed to stat() file '%s': %s", filename, os::strerror(errno));
5185 + return st.st_mtime;
5188 +int os::compare_file_modified_times(const char* file1, const char* file2) {
5189 + time_t t1 = get_mtime(file1);
5190 + time_t t2 = get_mtime(file2);
5191 + return t1 - t2;
5194 +static bool _print_ascii_file(const char* filename, outputStream* st) {
5195 + int fd = ::open(filename, O_RDONLY);
5196 + if (fd == -1) {
5197 + return false;
5200 + char buf[32];
5201 + int bytes;
5202 + while ((bytes = ::read(fd, buf, sizeof(buf))) > 0) {
5203 + st->print_raw(buf, bytes);
5206 + ::close(fd);
5208 + return true;
5211 +void os::print_os_info_brief(outputStream* st) {
5212 + os::Solaris::print_distro_info(st);
5214 + os::Posix::print_uname_info(st);
5216 + os::Solaris::print_libversion_info(st);
5219 +void os::print_os_info(outputStream* st) {
5220 + st->print("OS:");
5222 + os::Solaris::print_distro_info(st);
5224 + os::Posix::print_uname_info(st);
5226 + os::Posix::print_uptime_info(st);
5228 + os::Solaris::print_libversion_info(st);
5230 + os::Posix::print_rlimit_info(st);
5232 + os::Posix::print_load_average(st);
5235 +void os::Solaris::print_distro_info(outputStream* st) {
5236 + if (!_print_ascii_file("/etc/release", st)) {
5237 + st->print("Solaris");
5239 + st->cr();
5242 +void os::get_summary_os_info(char* buf, size_t buflen) {
5243 + strncpy(buf, "Solaris", buflen); // default to plain solaris
5244 + FILE* fp = fopen("/etc/release", "r");
5245 + if (fp != NULL) {
5246 + char tmp[256];
5247 + // Only get the first line and chop out everything but the os name.
5248 + if (fgets(tmp, sizeof(tmp), fp)) {
5249 + char* ptr = tmp;
5250 + // skip past whitespace characters
5251 + while (*ptr != '\0' && (*ptr == ' ' || *ptr == '\t' || *ptr == '\n')) ptr++;
5252 + if (*ptr != '\0') {
5253 + char* nl = strchr(ptr, '\n');
5254 + if (nl != NULL) *nl = '\0';
5255 + strncpy(buf, ptr, buflen);
5258 + fclose(fp);
5262 +void os::Solaris::print_libversion_info(outputStream* st) {
5263 + st->print(" (T2 libthread)");
5264 + st->cr();
5267 +static bool check_addr0(outputStream* st) {
5268 + jboolean status = false;
5269 + const int read_chunk = 200;
5270 + int ret = 0;
5271 + int nmap = 0;
5272 + int fd = ::open("/proc/self/map",O_RDONLY);
5273 + if (fd >= 0) {
5274 + prmap_t *p = NULL;
5275 + char *mbuff = (char *) calloc(read_chunk, sizeof(prmap_t));
5276 + if (NULL == mbuff) {
5277 + ::close(fd);
5278 + return status;
5280 + while ((ret = ::read(fd, mbuff, read_chunk*sizeof(prmap_t))) > 0) {
5281 + //check if read() has not read partial data
5282 + if( 0 != ret % sizeof(prmap_t)){
5283 + break;
5285 + nmap = ret / sizeof(prmap_t);
5286 + p = (prmap_t *)mbuff;
5287 + for(int i = 0; i < nmap; i++){
5288 + if (p->pr_vaddr == 0x0) {
5289 + st->print("Warning: Address: " PTR_FORMAT ", Size: " SIZE_FORMAT "K, ",p->pr_vaddr, p->pr_size/1024);
5290 + st->print("Mapped file: %s, ", p->pr_mapname[0] == '\0' ? "None" : p->pr_mapname);
5291 + st->print("Access: ");
5292 + st->print("%s",(p->pr_mflags & MA_READ) ? "r" : "-");
5293 + st->print("%s",(p->pr_mflags & MA_WRITE) ? "w" : "-");
5294 + st->print("%s",(p->pr_mflags & MA_EXEC) ? "x" : "-");
5295 + st->cr();
5296 + status = true;
5298 + p++;
5301 + free(mbuff);
5302 + ::close(fd);
5304 + return status;
5307 +void os::get_summary_cpu_info(char* buf, size_t buflen) {
5308 + // Get MHz with system call. We don't seem to already have this.
5309 + processor_info_t stats;
5310 + processorid_t id = getcpuid();
5311 + int clock = 0;
5312 + if (processor_info(id, &stats) != -1) {
5313 + clock = stats.pi_clock; // pi_processor_type isn't more informative than below
5315 + snprintf(buf, buflen, "64 bit %d MHz", clock);
5318 +void os::pd_print_cpu_info(outputStream* st, char* buf, size_t buflen) {
5319 + // Nothing to do for now.
5322 +void os::print_memory_info(outputStream* st) {
5323 + st->print("Memory:");
5324 + st->print(" " SIZE_FORMAT "k page", os::vm_page_size()>>10);
5325 + st->print(", physical " UINT64_FORMAT "k", os::physical_memory()>>10);
5326 + st->print("(" UINT64_FORMAT "k free)", os::available_memory() >> 10);
5327 + st->cr();
5328 + (void) check_addr0(st);
5331 +static int Maxsignum = 0;
5333 +static char saved_jvm_path[MAXPATHLEN] = { 0 };
5335 +// Find the full path to the current module, libjvm.so
5336 +void os::jvm_path(char *buf, jint buflen) {
5337 + // Error checking.
5338 + if (buflen < MAXPATHLEN) {
5339 + assert(false, "must use a large-enough buffer");
5340 + buf[0] = '\0';
5341 + return;
5343 + // Lazy resolve the path to current module.
5344 + if (saved_jvm_path[0] != 0) {
5345 + strcpy(buf, saved_jvm_path);
5346 + return;
5349 + Dl_info dlinfo;
5350 + int ret = dladdr(CAST_FROM_FN_PTR(void *, os::jvm_path), &dlinfo);
5351 + assert(ret != 0, "cannot locate libjvm");
5352 + if (ret != 0 && dlinfo.dli_fname != NULL) {
5353 + if (os::Posix::realpath((char *)dlinfo.dli_fname, buf, buflen) == NULL) {
5354 + return;
5356 + } else {
5357 + buf[0] = '\0';
5358 + return;
5361 + if (Arguments::sun_java_launcher_is_altjvm()) {
5362 + // Support for the java launcher's '-XXaltjvm=<path>' option. Typical
5363 + // value for buf is "<JAVA_HOME>/jre/lib/<arch>/<vmtype>/libjvm.so".
5364 + // If "/jre/lib/" appears at the right place in the string, then
5365 + // assume we are installed in a JDK and we're done. Otherwise, check
5366 + // for a JAVA_HOME environment variable and fix up the path so it
5367 + // looks like libjvm.so is installed there (append a fake suffix
5368 + // hotspot/libjvm.so).
5369 + const char *p = buf + strlen(buf) - 1;
5370 + for (int count = 0; p > buf && count < 5; ++count) {
5371 + for (--p; p > buf && *p != '/'; --p)
5372 + /* empty */ ;
5375 + if (strncmp(p, "/jre/lib/", 9) != 0) {
5376 + // Look for JAVA_HOME in the environment.
5377 + char* java_home_var = ::getenv("JAVA_HOME");
5378 + if (java_home_var != NULL && java_home_var[0] != 0) {
5379 + char* jrelib_p;
5380 + int len;
5382 + // Check the current module name "libjvm.so".
5383 + p = strrchr(buf, '/');
5384 + assert(strstr(p, "/libjvm") == p, "invalid library name");
5386 + if (os::Posix::realpath(java_home_var, buf, buflen) == NULL) {
5387 + return;
5389 + // determine if this is a legacy image or modules image
5390 + // modules image doesn't have "jre" subdirectory
5391 + len = strlen(buf);
5392 + assert(len < buflen, "Ran out of buffer space");
5393 + jrelib_p = buf + len;
5394 + snprintf(jrelib_p, buflen-len, "/jre/lib");
5395 + if (0 != access(buf, F_OK)) {
5396 + snprintf(jrelib_p, buflen-len, "/lib");
5399 + if (0 == access(buf, F_OK)) {
5400 + // Use current module name "libjvm.so"
5401 + len = strlen(buf);
5402 + snprintf(buf + len, buflen-len, "/hotspot/libjvm.so");
5403 + } else {
5404 + // Go back to path of .so
5405 + if (os::Posix::realpath((char *)dlinfo.dli_fname, buf, buflen) == NULL) {
5406 + return;
5413 + strncpy(saved_jvm_path, buf, MAXPATHLEN);
5414 + saved_jvm_path[MAXPATHLEN - 1] = '\0';
5417 +////////////////////////////////////////////////////////////////////////////////
5418 +// Virtual Memory
5420 +static bool recoverable_mmap_error(int err) {
5421 + // See if the error is one we can let the caller handle. This
5422 + // list of errno values comes from the Solaris mmap(2) man page.
5423 + switch (err) {
5424 + case EBADF:
5425 + case EINVAL:
5426 + case ENOTSUP:
5427 + // let the caller deal with these errors
5428 + return true;
5430 + default:
5431 + // Any remaining errors on this OS can cause our reserved mapping
5432 + // to be lost. That can cause confusion where different data
5433 + // structures think they have the same memory mapped. The worst
5434 + // scenario is if both the VM and a library think they have the
5435 + // same memory mapped.
5436 + return false;
5440 +static void warn_fail_commit_memory(char* addr, size_t bytes, bool exec,
5441 + int err) {
5442 + warning("INFO: os::commit_memory(" PTR_FORMAT ", " SIZE_FORMAT
5443 + ", %d) failed; error='%s' (errno=%d)", p2i(addr), bytes, exec,
5444 + os::strerror(err), err);
5447 +static void warn_fail_commit_memory(char* addr, size_t bytes,
5448 + size_t alignment_hint, bool exec,
5449 + int err) {
5450 + warning("INFO: os::commit_memory(" PTR_FORMAT ", " SIZE_FORMAT
5451 + ", " SIZE_FORMAT ", %d) failed; error='%s' (errno=%d)", p2i(addr),
5452 + bytes, alignment_hint, exec, os::strerror(err), err);
5455 +int os::Solaris::commit_memory_impl(char* addr, size_t bytes, bool exec) {
5456 + int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE;
5457 + size_t size = bytes;
5458 + char *res = Solaris::mmap_chunk(addr, size, MAP_PRIVATE|MAP_FIXED, prot);
5459 + if (res != NULL) {
5460 + if (UseNUMAInterleaving) {
5461 + numa_make_global(addr, bytes);
5463 + return 0;
5466 + int err = errno; // save errno from mmap() call in mmap_chunk()
5468 + if (!recoverable_mmap_error(err)) {
5469 + warn_fail_commit_memory(addr, bytes, exec, err);
5470 + vm_exit_out_of_memory(bytes, OOM_MMAP_ERROR, "committing reserved memory.");
5473 + return err;
5476 +bool os::pd_commit_memory(char* addr, size_t bytes, bool exec) {
5477 + return Solaris::commit_memory_impl(addr, bytes, exec) == 0;
5480 +void os::pd_commit_memory_or_exit(char* addr, size_t bytes, bool exec,
5481 + const char* mesg) {
5482 + assert(mesg != NULL, "mesg must be specified");
5483 + int err = os::Solaris::commit_memory_impl(addr, bytes, exec);
5484 + if (err != 0) {
5485 + // the caller wants all commit errors to exit with the specified mesg:
5486 + warn_fail_commit_memory(addr, bytes, exec, err);
5487 + vm_exit_out_of_memory(bytes, OOM_MMAP_ERROR, "%s", mesg);
5491 +size_t os::Solaris::page_size_for_alignment(size_t alignment) {
5492 + assert(is_aligned(alignment, (size_t) os::vm_page_size()),
5493 + SIZE_FORMAT " is not aligned to " SIZE_FORMAT,
5494 + alignment, (size_t) os::vm_page_size());
5496 + int page_sizes_max = 9;
5497 + size_t _illumos_page_sizes[page_sizes_max];
5498 + int n = getpagesizes(_illumos_page_sizes, page_sizes_max);
5499 + for (int i = 0; _illumos_page_sizes[i] != 0; i++) {
5500 + if (is_aligned(alignment, _illumos_page_sizes[i])) {
5501 + return _illumos_page_sizes[i];
5505 + return (size_t) os::vm_page_size();
5508 +int os::Solaris::commit_memory_impl(char* addr, size_t bytes,
5509 + size_t alignment_hint, bool exec) {
5510 + int err = Solaris::commit_memory_impl(addr, bytes, exec);
5511 + if (err == 0 && UseLargePages && alignment_hint > 0) {
5512 + assert(is_aligned(bytes, alignment_hint),
5513 + SIZE_FORMAT " is not aligned to " SIZE_FORMAT, bytes, alignment_hint);
5515 + // The syscall memcntl requires an exact page size (see man memcntl for details).
5516 + size_t page_size = page_size_for_alignment(alignment_hint);
5517 + if (page_size > (size_t) os::vm_page_size()) {
5518 + (void)Solaris::setup_large_pages(addr, bytes, page_size);
5521 + return err;
5524 +bool os::pd_commit_memory(char* addr, size_t bytes, size_t alignment_hint,
5525 + bool exec) {
5526 + return Solaris::commit_memory_impl(addr, bytes, alignment_hint, exec) == 0;
5529 +void os::pd_commit_memory_or_exit(char* addr, size_t bytes,
5530 + size_t alignment_hint, bool exec,
5531 + const char* mesg) {
5532 + assert(mesg != NULL, "mesg must be specified");
5533 + int err = os::Solaris::commit_memory_impl(addr, bytes, alignment_hint, exec);
5534 + if (err != 0) {
5535 + // the caller wants all commit errors to exit with the specified mesg:
5536 + warn_fail_commit_memory(addr, bytes, alignment_hint, exec, err);
5537 + vm_exit_out_of_memory(bytes, OOM_MMAP_ERROR, "%s", mesg);
5541 +// Uncommit the pages in a specified region.
5542 +void os::pd_free_memory(char* addr, size_t bytes, size_t alignment_hint) {
5543 + if (posix_madvise(addr, bytes, MADV_FREE) < 0) {
5544 + debug_only(warning("MADV_FREE failed."));
5545 + return;
5549 +size_t os::pd_pretouch_memory(void* first, void* last, size_t page_size) {
5550 + return page_size;
5553 +bool os::pd_create_stack_guard_pages(char* addr, size_t size) {
5554 + return os::commit_memory(addr, size, !ExecMem);
5557 +bool os::remove_stack_guard_pages(char* addr, size_t size) {
5558 + return os::uncommit_memory(addr, size);
5561 +// Change the page size in a given range.
5562 +void os::pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint) {
5563 + assert((intptr_t)addr % alignment_hint == 0, "Address should be aligned.");
5564 + assert((intptr_t)(addr + bytes) % alignment_hint == 0, "End should be aligned.");
5565 + if (UseLargePages) {
5566 + size_t page_size = Solaris::page_size_for_alignment(alignment_hint);
5567 + if (page_size > (size_t) os::vm_page_size()) {
5568 + Solaris::setup_large_pages(addr, bytes, page_size);
5573 +// Tell the OS to make the range local to the first-touching LWP
5574 +void os::numa_make_local(char *addr, size_t bytes, int lgrp_hint) {
5575 + assert((intptr_t)addr % os::vm_page_size() == 0, "Address should be page-aligned.");
5576 + if (posix_madvise(addr, bytes, MADV_ACCESS_LWP) < 0) {
5577 + debug_only(warning("MADV_ACCESS_LWP failed."));
5581 +// Tell the OS that this range would be accessed from different LWPs.
5582 +void os::numa_make_global(char *addr, size_t bytes) {
5583 + assert((intptr_t)addr % os::vm_page_size() == 0, "Address should be page-aligned.");
5584 + if (posix_madvise(addr, bytes, MADV_ACCESS_MANY) < 0) {
5585 + debug_only(warning("MADV_ACCESS_MANY failed."));
5589 +// Get the number of the locality groups.
5590 +size_t os::numa_get_groups_num() {
5591 + size_t n = Solaris::lgrp_nlgrps(Solaris::lgrp_cookie());
5592 + return n != -1 ? n : 1;
5595 +// Get a list of leaf locality groups. A leaf lgroup is group that
5596 +// doesn't have any children. Typical leaf group is a CPU or a CPU/memory
5597 +// board. An LWP is assigned to one of these groups upon creation.
5598 +size_t os::numa_get_leaf_groups(uint *ids, size_t size) {
5599 + if ((ids[0] = Solaris::lgrp_root(Solaris::lgrp_cookie())) == -1) {
5600 + ids[0] = 0;
5601 + return 1;
5603 + int result_size = 0, top = 1, bottom = 0, cur = 0;
5604 + for (unsigned int k = 0; k < size; k++) {
5605 + int r = Solaris::lgrp_children(Solaris::lgrp_cookie(), ids[cur],
5606 + (Solaris::lgrp_id_t*)&ids[top], size - top);
5607 + if (r == -1) {
5608 + ids[0] = 0;
5609 + return 1;
5611 + if (!r) {
5612 + // That's a leaf node.
5613 + assert(bottom <= cur, "Sanity check");
5614 + // Check if the node has memory
5615 + if (Solaris::lgrp_resources(Solaris::lgrp_cookie(), ids[cur],
5616 + NULL, 0, LGRP_RSRC_MEM) > 0) {
5617 + ids[bottom++] = ids[cur];
5620 + top += r;
5621 + cur++;
5623 + if (bottom == 0) {
5624 + // Handle a situation, when the OS reports no memory available.
5625 + // Assume UMA architecture.
5626 + ids[0] = 0;
5627 + return 1;
5629 + return bottom;
5632 +// Detect the topology change. Typically happens during CPU plugging-unplugging.
5633 +bool os::numa_topology_changed() {
5634 + int is_stale = Solaris::lgrp_cookie_stale(Solaris::lgrp_cookie());
5635 + if (is_stale != -1 && is_stale) {
5636 + Solaris::lgrp_fini(Solaris::lgrp_cookie());
5637 + Solaris::lgrp_cookie_t c = Solaris::lgrp_init(Solaris::LGRP_VIEW_CALLER);
5638 + assert(c != 0, "Failure to initialize LGRP API");
5639 + Solaris::set_lgrp_cookie(c);
5640 + return true;
5642 + return false;
5645 +// Get the group id of the current LWP.
5646 +int os::numa_get_group_id() {
5647 + int lgrp_id = Solaris::lgrp_home(P_LWPID, P_MYID);
5648 + if (lgrp_id == -1) {
5649 + return 0;
5651 + const int size = os::numa_get_groups_num();
5652 + int *ids = (int*)alloca(size * sizeof(int));
5654 + // Get the ids of all lgroups with memory; r is the count.
5655 + int r = Solaris::lgrp_resources(Solaris::lgrp_cookie(), lgrp_id,
5656 + (Solaris::lgrp_id_t*)ids, size, LGRP_RSRC_MEM);
5657 + if (r <= 0) {
5658 + return 0;
5660 + return ids[os::random() % r];
5663 +int os::numa_get_group_id_for_address(const void* address) {
5664 + return 0;
5667 +bool os::numa_get_group_ids_for_range(const void** addresses, int* lgrp_ids, size_t count) {
5668 + return false;
5671 +bool os::pd_uncommit_memory(char* addr, size_t bytes, bool exec) {
5672 + size_t size = bytes;
5673 + // Map uncommitted pages PROT_NONE so we fail early if we touch an
5674 + // uncommitted page. Otherwise, the read/write might succeed if we
5675 + // have enough swap space to back the physical page.
5676 + return
5677 + NULL != Solaris::mmap_chunk(addr, size,
5678 + MAP_PRIVATE|MAP_FIXED|MAP_NORESERVE,
5679 + PROT_NONE);
5682 +char* os::Solaris::mmap_chunk(char *addr, size_t size, int flags, int prot) {
5683 + char *b = (char *)mmap(addr, size, prot, flags, os::Solaris::_dev_zero_fd, 0);
5685 + if (b == MAP_FAILED) {
5686 + return NULL;
5688 + return b;
5691 +char* os::Solaris::anon_mmap(char* requested_addr, size_t bytes) {
5692 + char* addr = requested_addr;
5693 + int flags = MAP_PRIVATE | MAP_NORESERVE;
5695 + // Map uncommitted pages PROT_NONE so we fail early if we touch an
5696 + // uncommitted page. Otherwise, the read/write might succeed if we
5697 + // have enough swap space to back the physical page.
5698 + return mmap_chunk(addr, bytes, flags, PROT_NONE);
5701 +char* os::pd_reserve_memory(size_t bytes, bool exec) {
5702 + char* addr = Solaris::anon_mmap(NULL, bytes);
5704 + return addr;
5707 +char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, int file_desc) {
5708 + assert(file_desc >= 0, "file_desc is not valid");
5709 + char* result = pd_attempt_reserve_memory_at(requested_addr, bytes, !ExecMem);
5710 + if (result != NULL) {
5711 + if (replace_existing_mapping_with_file_mapping(result, bytes, file_desc) == NULL) {
5712 + vm_exit_during_initialization(err_msg("Error in mapping Java heap at the given filesystem directory"));
5715 + return result;
5718 +// Reserve memory at an arbitrary address, only if that area is
5719 +// available (and not reserved for something else).
5721 +char* os::pd_attempt_reserve_memory_at(char* requested_addr, size_t bytes, bool exec) {
5722 + // Assert only that the size is a multiple of the page size, since
5723 + // that's all that mmap requires, and since that's all we really know
5724 + // about at this low abstraction level. If we need higher alignment,
5725 + // we can either pass an alignment to this method or verify alignment
5726 + // in one of the methods further up the call chain. See bug 5044738.
5727 + assert(bytes % os::vm_page_size() == 0, "reserving unexpected size block");
5729 + // Since snv_84, Solaris attempts to honor the address hint - see 5003415.
5730 + char* addr = Solaris::anon_mmap(requested_addr, bytes);
5732 + volatile int err = errno;
5733 + if (addr == requested_addr) {
5734 + return addr;
5737 + if (addr != NULL) {
5738 + pd_unmap_memory(addr, bytes);
5741 + return NULL;
5744 +bool os::pd_release_memory(char* addr, size_t bytes) {
5745 + size_t size = bytes;
5746 + return munmap(addr, size) == 0;
5749 +static bool solaris_mprotect(char* addr, size_t bytes, int prot) {
5750 + assert(addr == (char*)align_down((uintptr_t)addr, os::vm_page_size()),
5751 + "addr must be page aligned");
5752 + Events::log(NULL, "Protecting memory [" INTPTR_FORMAT "," INTPTR_FORMAT "] with protection modes %x", p2i(addr), p2i(addr+bytes), prot);
5753 + int retVal = mprotect(addr, bytes, prot);
5754 + return retVal == 0;
5757 +// Protect memory (Used to pass readonly pages through
5758 +// JNI GetArray<type>Elements with empty arrays.)
5759 +// Also, used for serialization page and for compressed oops null pointer
5760 +// checking.
5761 +bool os::protect_memory(char* addr, size_t bytes, ProtType prot,
5762 + bool is_committed) {
5763 + unsigned int p = 0;
5764 + switch (prot) {
5765 + case MEM_PROT_NONE: p = PROT_NONE; break;
5766 + case MEM_PROT_READ: p = PROT_READ; break;
5767 + case MEM_PROT_RW: p = PROT_READ|PROT_WRITE; break;
5768 + case MEM_PROT_RWX: p = PROT_READ|PROT_WRITE|PROT_EXEC; break;
5769 + default:
5770 + ShouldNotReachHere();
5772 + // is_committed is unused.
5773 + return solaris_mprotect(addr, bytes, p);
5776 +// guard_memory and unguard_memory only happens within stack guard pages.
5777 +// Since ISM pertains only to the heap, guard and unguard memory should not
5778 +/// happen with an ISM region.
5779 +bool os::guard_memory(char* addr, size_t bytes) {
5780 + return solaris_mprotect(addr, bytes, PROT_NONE);
5783 +bool os::unguard_memory(char* addr, size_t bytes) {
5784 + return solaris_mprotect(addr, bytes, PROT_READ|PROT_WRITE);
5787 +// Large page support
5788 +static size_t _large_page_size = 0;
5790 +bool os::Solaris::mpss_sanity_check(bool warn, size_t* page_size) {
5791 + // Find the page sizes supported by the system
5792 + int page_sizes_max = 9;
5793 + size_t _illumos_page_sizes[page_sizes_max];
5794 + int n = getpagesizes(_illumos_page_sizes, page_sizes_max);
5795 + assert(n > 0, "illumos bug?");
5797 + if (n == 1) return false; // Only one page size available.
5799 + // Skip sizes larger than 4M (or LargePageSizeInBytes if it was set)
5800 + const size_t size_limit =
5801 + FLAG_IS_DEFAULT(LargePageSizeInBytes) ? 4 * M : LargePageSizeInBytes;
5802 + int beg;
5803 + for (beg = 0; beg < n; ++beg) {
5804 + if (_illumos_page_sizes[beg] <= size_limit) {
5805 + _page_sizes.add(_illumos_page_sizes[beg]);
5806 + if (_illumos_page_sizes[beg] > *page_size) {
5807 + *page_size = _illumos_page_sizes[beg];
5811 + // make sure we add the default
5812 + _page_sizes.add(os::vm_page_size());
5813 + return true;
5816 +void os::large_page_init() {
5817 + if (UseLargePages) {
5818 + // print a warning if any large page related flag is specified on command line
5819 + bool warn_on_failure = !FLAG_IS_DEFAULT(UseLargePages) ||
5820 + !FLAG_IS_DEFAULT(LargePageSizeInBytes);
5822 + UseLargePages = Solaris::mpss_sanity_check(warn_on_failure, &_large_page_size);
5826 +bool os::Solaris::is_valid_page_size(size_t bytes) {
5827 + return _page_sizes.contains(bytes);
5830 +bool os::Solaris::setup_large_pages(caddr_t start, size_t bytes, size_t align) {
5831 + assert(is_valid_page_size(align), SIZE_FORMAT " is not a valid page size", align);
5832 + assert(is_aligned((void*) start, align),
5833 + PTR_FORMAT " is not aligned to " SIZE_FORMAT, p2i((void*) start), align);
5834 + assert(is_aligned(bytes, align),
5835 + SIZE_FORMAT " is not aligned to " SIZE_FORMAT, bytes, align);
5837 + // Signal to OS that we want large pages for addresses
5838 + // from addr, addr + bytes
5839 + struct memcntl_mha mpss_struct;
5840 + mpss_struct.mha_cmd = MHA_MAPSIZE_VA;
5841 + mpss_struct.mha_pagesize = align;
5842 + mpss_struct.mha_flags = 0;
5843 + // Upon successful completion, memcntl() returns 0
5844 + if (memcntl(start, bytes, MC_HAT_ADVISE, (caddr_t) &mpss_struct, 0, 0)) {
5845 + debug_only(warning("Attempt to use MPSS failed."));
5846 + return false;
5848 + return true;
5851 +char* os::pd_reserve_memory_special(size_t size, size_t alignment, size_t page_size, char* addr, bool exec) {
5852 + fatal("os::reserve_memory_special should not be called on Solaris.");
5853 + return NULL;
5856 +bool os::pd_release_memory_special(char* base, size_t bytes) {
5857 + fatal("os::release_memory_special should not be called on Solaris.");
5858 + return false;
5861 +size_t os::large_page_size() {
5862 + return _large_page_size;
5865 +// MPSS allows application to commit large page memory on demand; with ISM
5866 +// the entire memory region must be allocated as shared memory.
5867 +bool os::can_commit_large_page_memory() {
5868 + return true;
5871 +size_t os::vm_min_address() {
5872 + return _vm_min_address_default;
5875 +// Interface for setting lwp priorities. We are using T2 libthread,
5876 +// which forces the use of bound threads, so all of our threads will
5877 +// be assigned to real lwp's. Using the thr_setprio function is
5878 +// meaningless in this mode so we must adjust the real lwp's priority.
5879 +// The routines below implement the getting and setting of lwp priorities.
5881 +// Note: There are three priority scales used on Solaris. Java priorities
5882 +// which range from 1 to 10, libthread "thr_setprio" scale which range
5883 +// from 0 to 127, and the current scheduling class of the process we
5884 +// are running in. This is typically from -60 to +60.
5885 +// The setting of the lwp priorities is done after a call to thr_setprio
5886 +// so Java priorities are mapped to libthread priorities and we map from
5887 +// the latter to lwp priorities. We don't keep priorities stored in
5888 +// Java priorities since some of our worker threads want to set priorities
5889 +// higher than all Java threads.
5891 +// For related information:
5892 +// (1) man -s 2 priocntl
5893 +// (2) man -s 4 priocntl
5894 +// (3) man dispadmin
5895 +// = librt.so
5896 +// = libthread/common/rtsched.c - thrp_setlwpprio().
5897 +// = ps -cL <pid> ... to validate priority.
5898 +// = sched_get_priority_min and _max
5899 +// pthread_create
5900 +// sched_setparam
5901 +// pthread_setschedparam
5903 +// Assumptions:
5904 +// + We assume that all threads in the process belong to the same
5905 +// scheduling class. IE. an homogenous process.
5906 +// + Must be root or in IA group to change change "interactive" attribute.
5907 +// Priocntl() will fail silently. The only indication of failure is when
5908 +// we read-back the value and notice that it hasn't changed.
5909 +// + Interactive threads enter the runq at the head, non-interactive at the tail.
5910 +// + For RT, change timeslice as well. Invariant:
5911 +// constant "priority integral"
5912 +// Konst == TimeSlice * (60-Priority)
5913 +// Given a priority, compute appropriate timeslice.
5914 +// + Higher numerical values have higher priority.
5916 +// sched class attributes
5917 +typedef struct {
5918 + int schedPolicy; // classID
5919 + int maxPrio;
5920 + int minPrio;
5921 +} SchedInfo;
5924 +static SchedInfo tsLimits, iaLimits, rtLimits, fxLimits;
5926 +#ifdef ASSERT
5927 +static int ReadBackValidate = 1;
5928 +#endif
5929 +static int myClass = 0;
5930 +static int myMin = 0;
5931 +static int myMax = 0;
5932 +static int myCur = 0;
5933 +static bool priocntl_enable = false;
5935 +static const int criticalPrio = FXCriticalPriority;
5936 +static int java_MaxPriority_to_os_priority = 0; // Saved mapping
5939 +// lwp_priocntl_init
5941 +// Try to determine the priority scale for our process.
5943 +// Return errno or 0 if OK.
5945 +static int lwp_priocntl_init() {
5946 + int rslt;
5947 + pcinfo_t ClassInfo;
5948 + pcparms_t ParmInfo;
5949 + int i;
5951 + if (!UseThreadPriorities) return 0;
5953 + // If ThreadPriorityPolicy is 1, switch tables
5954 + if (ThreadPriorityPolicy == 1) {
5955 + for (i = 0; i < CriticalPriority+1; i++)
5956 + os::java_to_os_priority[i] = prio_policy1[i];
5958 + if (UseCriticalJavaThreadPriority) {
5959 + // MaxPriority always maps to the FX scheduling class and criticalPrio.
5960 + // See set_native_priority() and set_lwp_class_and_priority().
5961 + // Save original MaxPriority mapping in case attempt to
5962 + // use critical priority fails.
5963 + java_MaxPriority_to_os_priority = os::java_to_os_priority[MaxPriority];
5964 + // Set negative to distinguish from other priorities
5965 + os::java_to_os_priority[MaxPriority] = -criticalPrio;
5968 + // Get IDs for a set of well-known scheduling classes.
5969 + // TODO-FIXME: GETCLINFO returns the current # of classes in the
5970 + // the system. We should have a loop that iterates over the
5971 + // classID values, which are known to be "small" integers.
5973 + strcpy(ClassInfo.pc_clname, "TS");
5974 + ClassInfo.pc_cid = -1;
5975 + rslt = priocntl(P_ALL, 0, PC_GETCID, (caddr_t)&ClassInfo);
5976 + if (rslt < 0) return errno;
5977 + assert(ClassInfo.pc_cid != -1, "cid for TS class is -1");
5978 + tsLimits.schedPolicy = ClassInfo.pc_cid;
5979 + tsLimits.maxPrio = ((tsinfo_t*)ClassInfo.pc_clinfo)->ts_maxupri;
5980 + tsLimits.minPrio = -tsLimits.maxPrio;
5982 + strcpy(ClassInfo.pc_clname, "IA");
5983 + ClassInfo.pc_cid = -1;
5984 + rslt = priocntl(P_ALL, 0, PC_GETCID, (caddr_t)&ClassInfo);
5985 + if (rslt < 0) return errno;
5986 + assert(ClassInfo.pc_cid != -1, "cid for IA class is -1");
5987 + iaLimits.schedPolicy = ClassInfo.pc_cid;
5988 + iaLimits.maxPrio = ((iainfo_t*)ClassInfo.pc_clinfo)->ia_maxupri;
5989 + iaLimits.minPrio = -iaLimits.maxPrio;
5991 + strcpy(ClassInfo.pc_clname, "RT");
5992 + ClassInfo.pc_cid = -1;
5993 + rslt = priocntl(P_ALL, 0, PC_GETCID, (caddr_t)&ClassInfo);
5994 + if (rslt < 0) return errno;
5995 + assert(ClassInfo.pc_cid != -1, "cid for RT class is -1");
5996 + rtLimits.schedPolicy = ClassInfo.pc_cid;
5997 + rtLimits.maxPrio = ((rtinfo_t*)ClassInfo.pc_clinfo)->rt_maxpri;
5998 + rtLimits.minPrio = 0;
6000 + strcpy(ClassInfo.pc_clname, "FX");
6001 + ClassInfo.pc_cid = -1;
6002 + rslt = priocntl(P_ALL, 0, PC_GETCID, (caddr_t)&ClassInfo);
6003 + if (rslt < 0) return errno;
6004 + assert(ClassInfo.pc_cid != -1, "cid for FX class is -1");
6005 + fxLimits.schedPolicy = ClassInfo.pc_cid;
6006 + fxLimits.maxPrio = ((fxinfo_t*)ClassInfo.pc_clinfo)->fx_maxupri;
6007 + fxLimits.minPrio = 0;
6009 + // Query our "current" scheduling class.
6010 + // This will normally be IA, TS or, rarely, FX or RT.
6011 + memset(&ParmInfo, 0, sizeof(ParmInfo));
6012 + ParmInfo.pc_cid = PC_CLNULL;
6013 + rslt = priocntl(P_PID, P_MYID, PC_GETPARMS, (caddr_t)&ParmInfo);
6014 + if (rslt < 0) return errno;
6015 + myClass = ParmInfo.pc_cid;
6017 + // We now know our scheduling classId, get specific information
6018 + // about the class.
6019 + ClassInfo.pc_cid = myClass;
6020 + ClassInfo.pc_clname[0] = 0;
6021 + rslt = priocntl((idtype)0, 0, PC_GETCLINFO, (caddr_t)&ClassInfo);
6022 + if (rslt < 0) return errno;
6024 + memset(&ParmInfo, 0, sizeof(pcparms_t));
6025 + ParmInfo.pc_cid = PC_CLNULL;
6026 + rslt = priocntl(P_PID, P_MYID, PC_GETPARMS, (caddr_t)&ParmInfo);
6027 + if (rslt < 0) return errno;
6029 + if (ParmInfo.pc_cid == rtLimits.schedPolicy) {
6030 + myMin = rtLimits.minPrio;
6031 + myMax = rtLimits.maxPrio;
6032 + } else if (ParmInfo.pc_cid == iaLimits.schedPolicy) {
6033 + iaparms_t *iaInfo = (iaparms_t*)ParmInfo.pc_clparms;
6034 + myMin = iaLimits.minPrio;
6035 + myMax = iaLimits.maxPrio;
6036 + myMax = MIN2(myMax, (int)iaInfo->ia_uprilim); // clamp - restrict
6037 + } else if (ParmInfo.pc_cid == tsLimits.schedPolicy) {
6038 + tsparms_t *tsInfo = (tsparms_t*)ParmInfo.pc_clparms;
6039 + myMin = tsLimits.minPrio;
6040 + myMax = tsLimits.maxPrio;
6041 + myMax = MIN2(myMax, (int)tsInfo->ts_uprilim); // clamp - restrict
6042 + } else if (ParmInfo.pc_cid == fxLimits.schedPolicy) {
6043 + fxparms_t *fxInfo = (fxparms_t*)ParmInfo.pc_clparms;
6044 + myMin = fxLimits.minPrio;
6045 + myMax = fxLimits.maxPrio;
6046 + myMax = MIN2(myMax, (int)fxInfo->fx_uprilim); // clamp - restrict
6047 + } else {
6048 + return EINVAL; // no clue, punt
6051 + priocntl_enable = true; // Enable changing priorities
6052 + return 0;
6055 +#define IAPRI(x) ((iaparms_t *)((x).pc_clparms))
6056 +#define RTPRI(x) ((rtparms_t *)((x).pc_clparms))
6057 +#define TSPRI(x) ((tsparms_t *)((x).pc_clparms))
6058 +#define FXPRI(x) ((fxparms_t *)((x).pc_clparms))
6061 +// scale_to_lwp_priority
6063 +// Convert from the libthread "thr_setprio" scale to our current
6064 +// lwp scheduling class scale.
6066 +static int scale_to_lwp_priority(int rMin, int rMax, int x) {
6067 + int v;
6069 + if (x == 127) return rMax; // avoid round-down
6070 + v = (((x*(rMax-rMin)))/128)+rMin;
6071 + return v;
6075 +// set_lwp_class_and_priority
6076 +int set_lwp_class_and_priority(int ThreadID, int lwpid,
6077 + int newPrio, int new_class, bool scale) {
6078 + int rslt;
6079 + int Actual, Expected, prv;
6080 + pcparms_t ParmInfo; // for GET-SET
6081 +#ifdef ASSERT
6082 + pcparms_t ReadBack; // for readback
6083 +#endif
6085 + // Set priority via PC_GETPARMS, update, PC_SETPARMS
6086 + // Query current values.
6087 + // TODO: accelerate this by eliminating the PC_GETPARMS call.
6088 + // Cache "pcparms_t" in global ParmCache.
6089 + // TODO: elide set-to-same-value
6091 + // If something went wrong on init, don't change priorities.
6092 + if (!priocntl_enable) {
6093 + return EINVAL;
6096 + // If lwp hasn't started yet, just return
6097 + // the _start routine will call us again.
6098 + if (lwpid <= 0) {
6099 + return 0;
6102 + memset(&ParmInfo, 0, sizeof(pcparms_t));
6103 + ParmInfo.pc_cid = PC_CLNULL;
6104 + rslt = priocntl(P_LWPID, lwpid, PC_GETPARMS, (caddr_t)&ParmInfo);
6105 + if (rslt < 0) return errno;
6107 + int cur_class = ParmInfo.pc_cid;
6108 + ParmInfo.pc_cid = (id_t)new_class;
6110 + if (new_class == rtLimits.schedPolicy) {
6111 + rtparms_t *rtInfo = (rtparms_t*)ParmInfo.pc_clparms;
6112 + rtInfo->rt_pri = scale ? scale_to_lwp_priority(rtLimits.minPrio,
6113 + rtLimits.maxPrio, newPrio)
6114 + : newPrio;
6115 + rtInfo->rt_tqsecs = RT_NOCHANGE;
6116 + rtInfo->rt_tqnsecs = RT_NOCHANGE;
6117 + } else if (new_class == iaLimits.schedPolicy) {
6118 + iaparms_t* iaInfo = (iaparms_t*)ParmInfo.pc_clparms;
6119 + int maxClamped = MIN2(iaLimits.maxPrio,
6120 + cur_class == new_class
6121 + ? (int)iaInfo->ia_uprilim : iaLimits.maxPrio);
6122 + iaInfo->ia_upri = scale ? scale_to_lwp_priority(iaLimits.minPrio,
6123 + maxClamped, newPrio)
6124 + : newPrio;
6125 + iaInfo->ia_uprilim = cur_class == new_class
6126 + ? IA_NOCHANGE : (pri_t)iaLimits.maxPrio;
6127 + iaInfo->ia_mode = IA_NOCHANGE;
6128 + } else if (new_class == tsLimits.schedPolicy) {
6129 + tsparms_t* tsInfo = (tsparms_t*)ParmInfo.pc_clparms;
6130 + int maxClamped = MIN2(tsLimits.maxPrio,
6131 + cur_class == new_class
6132 + ? (int)tsInfo->ts_uprilim : tsLimits.maxPrio);
6133 + tsInfo->ts_upri = scale ? scale_to_lwp_priority(tsLimits.minPrio,
6134 + maxClamped, newPrio)
6135 + : newPrio;
6136 + tsInfo->ts_uprilim = cur_class == new_class
6137 + ? TS_NOCHANGE : (pri_t)tsLimits.maxPrio;
6138 + } else if (new_class == fxLimits.schedPolicy) {
6139 + fxparms_t* fxInfo = (fxparms_t*)ParmInfo.pc_clparms;
6140 + int maxClamped = MIN2(fxLimits.maxPrio,
6141 + cur_class == new_class
6142 + ? (int)fxInfo->fx_uprilim : fxLimits.maxPrio);
6143 + fxInfo->fx_upri = scale ? scale_to_lwp_priority(fxLimits.minPrio,
6144 + maxClamped, newPrio)
6145 + : newPrio;
6146 + fxInfo->fx_uprilim = cur_class == new_class
6147 + ? FX_NOCHANGE : (pri_t)fxLimits.maxPrio;
6148 + fxInfo->fx_tqsecs = FX_NOCHANGE;
6149 + fxInfo->fx_tqnsecs = FX_NOCHANGE;
6150 + } else {
6151 + return EINVAL; // no clue, punt
6154 + rslt = priocntl(P_LWPID, lwpid, PC_SETPARMS, (caddr_t)&ParmInfo);
6155 + if (rslt < 0) return errno;
6157 +#ifdef ASSERT
6158 + // Sanity check: read back what we just attempted to set.
6159 + // In theory it could have changed in the interim ...
6160 + //
6161 + // The priocntl system call is tricky.
6162 + // Sometimes it'll validate the priority value argument and
6163 + // return EINVAL if unhappy. At other times it fails silently.
6164 + // Readbacks are prudent.
6166 + if (!ReadBackValidate) return 0;
6168 + memset(&ReadBack, 0, sizeof(pcparms_t));
6169 + ReadBack.pc_cid = PC_CLNULL;
6170 + rslt = priocntl(P_LWPID, lwpid, PC_GETPARMS, (caddr_t)&ReadBack);
6171 + assert(rslt >= 0, "priocntl failed");
6172 + Actual = Expected = 0xBAD;
6173 + assert(ParmInfo.pc_cid == ReadBack.pc_cid, "cid's don't match");
6174 + if (ParmInfo.pc_cid == rtLimits.schedPolicy) {
6175 + Actual = RTPRI(ReadBack)->rt_pri;
6176 + Expected = RTPRI(ParmInfo)->rt_pri;
6177 + } else if (ParmInfo.pc_cid == iaLimits.schedPolicy) {
6178 + Actual = IAPRI(ReadBack)->ia_upri;
6179 + Expected = IAPRI(ParmInfo)->ia_upri;
6180 + } else if (ParmInfo.pc_cid == tsLimits.schedPolicy) {
6181 + Actual = TSPRI(ReadBack)->ts_upri;
6182 + Expected = TSPRI(ParmInfo)->ts_upri;
6183 + } else if (ParmInfo.pc_cid == fxLimits.schedPolicy) {
6184 + Actual = FXPRI(ReadBack)->fx_upri;
6185 + Expected = FXPRI(ParmInfo)->fx_upri;
6187 +#endif
6189 + return 0;
6192 +// Solaris only gives access to 128 real priorities at a time,
6193 +// so we expand Java's ten to fill this range. This would be better
6194 +// if we dynamically adjusted relative priorities.
6196 +// The ThreadPriorityPolicy option allows us to select 2 different
6197 +// priority scales.
6199 +// ThreadPriorityPolicy=0
6200 +// Since the Solaris' default priority is MaximumPriority, we do not
6201 +// set a priority lower than Max unless a priority lower than
6202 +// NormPriority is requested.
6204 +// ThreadPriorityPolicy=1
6205 +// This mode causes the priority table to get filled with
6206 +// linear values. NormPriority get's mapped to 50% of the
6207 +// Maximum priority an so on. This will cause VM threads
6208 +// to get unfair treatment against other Solaris processes
6209 +// which do not explicitly alter their thread priorities.
6211 +int os::java_to_os_priority[CriticalPriority + 1] = {
6212 + -99999, // 0 Entry should never be used
6214 + 0, // 1 MinPriority
6215 + 32, // 2
6216 + 64, // 3
6218 + 96, // 4
6219 + 127, // 5 NormPriority
6220 + 127, // 6
6222 + 127, // 7
6223 + 127, // 8
6224 + 127, // 9 NearMaxPriority
6226 + 127, // 10 MaxPriority
6228 + -criticalPrio // 11 CriticalPriority
6231 +OSReturn os::set_native_priority(Thread* thread, int newpri) {
6232 + OSThread* osthread = thread->osthread();
6234 + // Save requested priority in case the thread hasn't been started
6235 + osthread->set_native_priority(newpri);
6237 + // Check for critical priority request
6238 + bool fxcritical = false;
6239 + if (newpri == -criticalPrio) {
6240 + fxcritical = true;
6241 + newpri = criticalPrio;
6244 + assert(newpri >= MinimumPriority && newpri <= MaximumPriority, "bad priority mapping");
6245 + if (!UseThreadPriorities) return OS_OK;
6247 + int status = 0;
6249 + if (!fxcritical) {
6250 + // Use thr_setprio only if we have a priority that thr_setprio understands
6251 + status = thr_setprio(thread->osthread()->thread_id(), newpri);
6254 + int lwp_status =
6255 + set_lwp_class_and_priority(osthread->thread_id(),
6256 + osthread->lwp_id(),
6257 + newpri,
6258 + fxcritical ? fxLimits.schedPolicy : myClass,
6259 + !fxcritical);
6260 + if (lwp_status != 0 && fxcritical) {
6261 + // Try again, this time without changing the scheduling class
6262 + newpri = java_MaxPriority_to_os_priority;
6263 + lwp_status = set_lwp_class_and_priority(osthread->thread_id(),
6264 + osthread->lwp_id(),
6265 + newpri, myClass, false);
6267 + status |= lwp_status;
6268 + return (status == 0) ? OS_OK : OS_ERR;
6272 +OSReturn os::get_native_priority(const Thread* const thread,
6273 + int *priority_ptr) {
6274 + int p;
6275 + if (!UseThreadPriorities) {
6276 + *priority_ptr = NormalPriority;
6277 + return OS_OK;
6279 + int status = thr_getprio(thread->osthread()->thread_id(), &p);
6280 + if (status != 0) {
6281 + return OS_ERR;
6283 + *priority_ptr = p;
6284 + return OS_OK;
6287 +////////////////////////////////////////////////////////////////////////////////
6289 +// This does not do anything on Solaris. This is basically a hook for being
6290 +// able to use structured exception handling (thread-local exception filters) on, e.g., Win32.
6291 +void os::os_exception_wrapper(java_call_t f, JavaValue* value,
6292 + const methodHandle& method, JavaCallArguments* args,
6293 + JavaThread* thread) {
6294 + f(value, method, args, thread);
6297 +void report_error(const char* file_name, int line_no, const char* title,
6298 + const char* format, ...);
6300 +// (Static) wrappers for the liblgrp API
6301 +os::Solaris::lgrp_home_func_t os::Solaris::_lgrp_home;
6302 +os::Solaris::lgrp_init_func_t os::Solaris::_lgrp_init;
6303 +os::Solaris::lgrp_fini_func_t os::Solaris::_lgrp_fini;
6304 +os::Solaris::lgrp_root_func_t os::Solaris::_lgrp_root;
6305 +os::Solaris::lgrp_children_func_t os::Solaris::_lgrp_children;
6306 +os::Solaris::lgrp_resources_func_t os::Solaris::_lgrp_resources;
6307 +os::Solaris::lgrp_nlgrps_func_t os::Solaris::_lgrp_nlgrps;
6308 +os::Solaris::lgrp_cookie_stale_func_t os::Solaris::_lgrp_cookie_stale;
6309 +os::Solaris::lgrp_cookie_t os::Solaris::_lgrp_cookie = 0;
6311 +static address resolve_symbol_lazy(const char* name) {
6312 + address addr = (address) dlsym(RTLD_DEFAULT, name);
6313 + if (addr == NULL) {
6314 + // RTLD_DEFAULT was not defined on some early versions of 2.5.1
6315 + addr = (address) dlsym(RTLD_NEXT, name);
6317 + return addr;
6320 +static address resolve_symbol(const char* name) {
6321 + address addr = resolve_symbol_lazy(name);
6322 + if (addr == NULL) {
6323 + fatal("resolve_symbol failed (%s)", dlerror());
6325 + return addr;
6328 +void os::Solaris::libthread_init() {
6329 + address func = (address)dlsym(RTLD_DEFAULT, "_thr_suspend_allmutators");
6331 + lwp_priocntl_init();
6333 + // RTLD_DEFAULT was not defined on some early versions of 5.5.1
6334 + if (func == NULL) {
6335 + func = (address) dlsym(RTLD_NEXT, "_thr_suspend_allmutators");
6336 + // Guarantee that this VM is running on an new enough OS (5.6 or
6337 + // later) that it will have a new enough libthread.so.
6338 + guarantee(func != NULL, "libthread.so is too old.");
6341 + int size;
6342 + void (*handler_info_func)(address *, int *);
6343 + handler_info_func = CAST_TO_FN_PTR(void (*)(address *, int *), resolve_symbol("thr_sighndlrinfo"));
6344 + handler_info_func(&handler_start, &size);
6345 + handler_end = handler_start + size;
6349 +bool os::Solaris::_synchronization_initialized;
6351 +void os::Solaris::synchronization_init() {
6352 + _synchronization_initialized = true;
6355 +bool os::Solaris::liblgrp_init() {
6356 + void *handle = dlopen("liblgrp.so.1", RTLD_LAZY);
6357 + if (handle != NULL) {
6358 + os::Solaris::set_lgrp_home(CAST_TO_FN_PTR(lgrp_home_func_t, dlsym(handle, "lgrp_home")));
6359 + os::Solaris::set_lgrp_init(CAST_TO_FN_PTR(lgrp_init_func_t, dlsym(handle, "lgrp_init")));
6360 + os::Solaris::set_lgrp_fini(CAST_TO_FN_PTR(lgrp_fini_func_t, dlsym(handle, "lgrp_fini")));
6361 + os::Solaris::set_lgrp_root(CAST_TO_FN_PTR(lgrp_root_func_t, dlsym(handle, "lgrp_root")));
6362 + os::Solaris::set_lgrp_children(CAST_TO_FN_PTR(lgrp_children_func_t, dlsym(handle, "lgrp_children")));
6363 + os::Solaris::set_lgrp_resources(CAST_TO_FN_PTR(lgrp_resources_func_t, dlsym(handle, "lgrp_resources")));
6364 + os::Solaris::set_lgrp_nlgrps(CAST_TO_FN_PTR(lgrp_nlgrps_func_t, dlsym(handle, "lgrp_nlgrps")));
6365 + os::Solaris::set_lgrp_cookie_stale(CAST_TO_FN_PTR(lgrp_cookie_stale_func_t,
6366 + dlsym(handle, "lgrp_cookie_stale")));
6368 + lgrp_cookie_t c = lgrp_init(LGRP_VIEW_CALLER);
6369 + set_lgrp_cookie(c);
6370 + return true;
6372 + return false;
6375 +// int pset_getloadavg(psetid_t pset, double loadavg[], int nelem);
6376 +typedef long (*pset_getloadavg_type)(psetid_t pset, double loadavg[], int nelem);
6377 +static pset_getloadavg_type pset_getloadavg_ptr = NULL;
6379 +void init_pset_getloadavg_ptr(void) {
6380 + pset_getloadavg_ptr =
6381 + (pset_getloadavg_type)dlsym(RTLD_DEFAULT, "pset_getloadavg");
6382 + if (pset_getloadavg_ptr == NULL) {
6383 + log_warning(os)("pset_getloadavg function not found");
6387 +int os::Solaris::_dev_zero_fd = -1;
6389 +// this is called _before_ the global arguments have been parsed
6390 +void os::init(void) {
6391 + _initial_pid = getpid();
6393 + max_hrtime = first_hrtime = gethrtime();
6395 + init_random(1234567);
6397 + int page_size = sysconf(_SC_PAGESIZE);
6398 + OSInfo::set_vm_page_size(page_size);
6399 + OSInfo::set_vm_allocation_granularity(page_size);
6400 + if (os::vm_page_size() <= 0) {
6401 + fatal("os_solaris.cpp: os::init: sysconf failed (%s)", os::strerror(errno));
6403 + _page_sizes.add(os::vm_page_size());
6405 + Solaris::initialize_system_info();
6407 + int fd = ::open("/dev/zero", O_RDWR);
6408 + if (fd < 0) {
6409 + fatal("os::init: cannot open /dev/zero (%s)", os::strerror(errno));
6410 + } else {
6411 + Solaris::set_dev_zero_fd(fd);
6413 + // Close on exec, child won't inherit.
6414 + fcntl(fd, F_SETFD, FD_CLOEXEC);
6417 + clock_tics_per_sec = CLK_TCK;
6419 + // main_thread points to the thread that created/loaded the JVM.
6420 + main_thread = thr_self();
6422 + // dynamic lookup of functions that may not be available in our lowest
6423 + // supported Solaris release
6424 + void * handle = dlopen("libc.so.1", RTLD_LAZY);
6425 + if (handle != NULL) {
6426 + Solaris::_pthread_setname_np = // from 11.3
6427 + (Solaris::pthread_setname_np_func_t)dlsym(handle, "pthread_setname_np");
6430 + // Shared Posix initialization
6431 + os::Posix::init();
6434 +// To install functions for atexit system call
6435 +extern "C" {
6436 + static void perfMemory_exit_helper() {
6437 + perfMemory_exit();
6441 +// this is called _after_ the global arguments have been parsed
6442 +jint os::init_2(void) {
6443 + Solaris::libthread_init();
6445 + if (UseNUMA) {
6446 + if (!Solaris::liblgrp_init()) {
6447 + FLAG_SET_ERGO(UseNUMA, false);
6448 + } else {
6449 + size_t lgrp_limit = os::numa_get_groups_num();
6450 + uint *lgrp_ids = NEW_C_HEAP_ARRAY(uint, lgrp_limit, mtInternal);
6451 + size_t lgrp_num = os::numa_get_leaf_groups(lgrp_ids, lgrp_limit);
6452 + FREE_C_HEAP_ARRAY(uint, lgrp_ids);
6453 + if (lgrp_num < 2) {
6454 + // There's only one locality group, disable NUMA
6455 + UseNUMA = false;
6460 + // When NUMA requested, not-NUMA-aware allocations default to interleaving.
6461 + if (UseNUMA && !UseNUMAInterleaving) {
6462 + FLAG_SET_ERGO_IF_DEFAULT(UseNUMAInterleaving, true);
6465 + if (PosixSignals::init() == JNI_ERR) {
6466 + return JNI_ERR;
6469 + // initialize synchronization primitives
6470 + Solaris::synchronization_init();
6471 + DEBUG_ONLY(os::set_mutex_init_done();)
6473 + if (MaxFDLimit) {
6474 + // set the number of file descriptors to max. print out error
6475 + // if getrlimit/setrlimit fails but continue regardless.
6476 + struct rlimit nbr_files;
6477 + int status = getrlimit(RLIMIT_NOFILE, &nbr_files);
6478 + if (status != 0) {
6479 + log_info(os)("os::init_2 getrlimit failed: %s", os::strerror(errno));
6480 + } else {
6481 + nbr_files.rlim_cur = nbr_files.rlim_max;
6482 + status = setrlimit(RLIMIT_NOFILE, &nbr_files);
6483 + if (status != 0) {
6484 + log_info(os)("os::init_2 setrlimit failed: %s", os::strerror(errno));
6489 + // Calculate theoretical max. size of Threads to guard gainst
6490 + // artifical out-of-memory situations, where all available address-
6491 + // space has been reserved by thread stacks. Default stack size is 1Mb.
6492 + size_t pre_thread_stack_size = (JavaThread::stack_size_at_create()) ?
6493 + JavaThread::stack_size_at_create() : (1*K*K);
6494 + assert(pre_thread_stack_size != 0, "Must have a stack");
6495 + // Solaris has a maximum of 4Gb of user programs. Calculate the thread limit when
6496 + // we should start doing Virtual Memory banging. Currently when the threads will
6497 + // have used all but 200Mb of space.
6498 + size_t max_address_space = ((unsigned int)4 * K * K * K) - (200 * K * K);
6499 + Solaris::_os_thread_limit = max_address_space / pre_thread_stack_size;
6501 + // at-exit methods are called in the reverse order of their registration.
6502 + // In Solaris 7 and earlier, atexit functions are called on return from
6503 + // main or as a result of a call to exit(3C). There can be only 32 of
6504 + // these functions registered and atexit() does not set errno. In Solaris
6505 + // 8 and later, there is no limit to the number of functions registered
6506 + // and atexit() sets errno. In addition, in Solaris 8 and later, atexit
6507 + // functions are called upon dlclose(3DL) in addition to return from main
6508 + // and exit(3C).
6510 + if (PerfAllowAtExitRegistration) {
6511 + // only register atexit functions if PerfAllowAtExitRegistration is set.
6512 + // atexit functions can be delayed until process exit time, which
6513 + // can be problematic for embedded VM situations. Embedded VMs should
6514 + // call DestroyJavaVM() to assure that VM resources are released.
6516 + // note: perfMemory_exit_helper atexit function may be removed in
6517 + // the future if the appropriate cleanup code can be added to the
6518 + // VM_Exit VMOperation's doit method.
6519 + if (atexit(perfMemory_exit_helper) != 0) {
6520 + warning("os::init2 atexit(perfMemory_exit_helper) failed");
6524 + // Init pset_loadavg function pointer
6525 + init_pset_getloadavg_ptr();
6527 + // Shared Posix initialization
6528 + os::Posix::init_2();
6530 + return JNI_OK;
6533 +// This code originates from JDK's sysOpen and open64_w
6534 +// from src/solaris/hpi/src/system_md.c
6536 +int os::open(const char *path, int oflag, int mode) {
6537 + if (strlen(path) > MAX_PATH - 1) {
6538 + errno = ENAMETOOLONG;
6539 + return -1;
6541 + int fd;
6543 + fd = ::open64(path, oflag, mode);
6544 + if (fd == -1) return -1;
6546 + // If the open succeeded, the file might still be a directory
6548 + struct stat64 buf64;
6549 + int ret = ::fstat64(fd, &buf64);
6550 + int st_mode = buf64.st_mode;
6552 + if (ret != -1) {
6553 + if ((st_mode & S_IFMT) == S_IFDIR) {
6554 + errno = EISDIR;
6555 + ::close(fd);
6556 + return -1;
6558 + } else {
6559 + ::close(fd);
6560 + return -1;
6564 + // All file descriptors that are opened in the JVM and not
6565 + // specifically destined for a subprocess should have the
6566 + // close-on-exec flag set. If we don't set it, then careless 3rd
6567 + // party native code might fork and exec without closing all
6568 + // appropriate file descriptors (e.g. as we do in closeDescriptors in
6569 + // UNIXProcess.c), and this in turn might:
6570 + //
6571 + // - cause end-of-file to fail to be detected on some file
6572 + // descriptors, resulting in mysterious hangs, or
6573 + //
6574 + // - might cause an fopen in the subprocess to fail on a system
6575 + // suffering from bug 1085341.
6576 + //
6577 + // (Yes, the default setting of the close-on-exec flag is a Unix
6578 + // design flaw)
6579 + //
6580 + // See:
6581 + // 1085341: 32-bit stdio routines should support file descriptors >255
6582 + // 4843136: (process) pipe file descriptor from Runtime.exec not being closed
6583 + // 6339493: (process) Runtime.exec does not close all file descriptors on Solaris 9
6584 + //
6585 +#ifdef FD_CLOEXEC
6587 + int flags = ::fcntl(fd, F_GETFD);
6588 + if (flags != -1) {
6589 + ::fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
6592 +#endif
6594 + return fd;
6597 +// return current position of file pointer
6598 +jlong os::current_file_offset(int fd) {
6599 + return (jlong)::lseek64(fd, (off64_t)0, SEEK_CUR);
6602 +// move file pointer to the specified offset
6603 +jlong os::seek_to_file_offset(int fd, jlong offset) {
6604 + return (jlong)::lseek64(fd, (off64_t)offset, SEEK_SET);
6607 +const intptr_t thr_time_off = (intptr_t)(&((prusage_t *)(NULL))->pr_utime);
6608 +const intptr_t thr_time_size = (intptr_t)(&((prusage_t *)(NULL))->pr_ttime) -
6609 + (intptr_t)(&((prusage_t *)(NULL))->pr_utime);
6612 +// JVMTI & JVM monitoring and management support
6613 +// The thread_cpu_time() and current_thread_cpu_time() are only
6614 +// supported if is_thread_cpu_time_supported() returns true.
6615 +// They are not supported on Solaris T1.
6617 +// current_thread_cpu_time(bool) and thread_cpu_time(Thread*, bool)
6618 +// are used by JVM M&M and JVMTI to get user+sys or user CPU time
6619 +// of a thread.
6621 +// current_thread_cpu_time() and thread_cpu_time(Thread *)
6622 +// returns the fast estimate available on the platform.
6624 +// hrtime_t gethrvtime() return value includes
6625 +// user time but does not include system time
6626 +jlong os::current_thread_cpu_time() {
6627 + return (jlong) gethrvtime();
6630 +jlong os::thread_cpu_time(Thread *thread) {
6631 + // return user level CPU time only to be consistent with
6632 + // what current_thread_cpu_time returns.
6633 + // thread_cpu_time_info() must be changed if this changes
6634 + return os::thread_cpu_time(thread, false /* user time only */);
6637 +jlong os::current_thread_cpu_time(bool user_sys_cpu_time) {
6638 + if (user_sys_cpu_time) {
6639 + return os::thread_cpu_time(Thread::current(), user_sys_cpu_time);
6640 + } else {
6641 + return os::current_thread_cpu_time();
6645 +jlong os::thread_cpu_time(Thread *thread, bool user_sys_cpu_time) {
6646 + char proc_name[64];
6647 + int count;
6648 + prusage_t prusage;
6649 + jlong lwp_time;
6650 + int fd;
6652 + sprintf(proc_name, "/proc/%d/lwp/%d/lwpusage",
6653 + getpid(),
6654 + thread->osthread()->lwp_id());
6655 + fd = ::open(proc_name, O_RDONLY);
6656 + if (fd == -1) return -1;
6658 + do {
6659 + count = ::pread(fd,
6660 + (void *)&prusage.pr_utime,
6661 + thr_time_size,
6662 + thr_time_off);
6663 + } while (count < 0 && errno == EINTR);
6664 + ::close(fd);
6665 + if (count < 0) return -1;
6667 + if (user_sys_cpu_time) {
6668 + // user + system CPU time
6669 + lwp_time = (((jlong)prusage.pr_stime.tv_sec +
6670 + (jlong)prusage.pr_utime.tv_sec) * (jlong)1000000000) +
6671 + (jlong)prusage.pr_stime.tv_nsec +
6672 + (jlong)prusage.pr_utime.tv_nsec;
6673 + } else {
6674 + // user level CPU time only
6675 + lwp_time = ((jlong)prusage.pr_utime.tv_sec * (jlong)1000000000) +
6676 + (jlong)prusage.pr_utime.tv_nsec;
6679 + return (lwp_time);
6682 +void os::current_thread_cpu_time_info(jvmtiTimerInfo *info_ptr) {
6683 + info_ptr->max_value = ALL_64_BITS; // will not wrap in less than 64 bits
6684 + info_ptr->may_skip_backward = false; // elapsed time not wall time
6685 + info_ptr->may_skip_forward = false; // elapsed time not wall time
6686 + info_ptr->kind = JVMTI_TIMER_USER_CPU; // only user time is returned
6689 +void os::thread_cpu_time_info(jvmtiTimerInfo *info_ptr) {
6690 + info_ptr->max_value = ALL_64_BITS; // will not wrap in less than 64 bits
6691 + info_ptr->may_skip_backward = false; // elapsed time not wall time
6692 + info_ptr->may_skip_forward = false; // elapsed time not wall time
6693 + info_ptr->kind = JVMTI_TIMER_USER_CPU; // only user time is returned
6696 +bool os::is_thread_cpu_time_supported() {
6697 + return true;
6700 +// System loadavg support. Returns -1 if load average cannot be obtained.
6701 +// Return the load average for our processor set if the primitive exists
6702 +// (Solaris 9 and later). Otherwise just return system wide loadavg.
6703 +int os::loadavg(double loadavg[], int nelem) {
6704 + if (pset_getloadavg_ptr != NULL) {
6705 + return (*pset_getloadavg_ptr)(PS_MYID, loadavg, nelem);
6706 + } else {
6707 + return ::getloadavg(loadavg, nelem);
6711 +//---------------------------------------------------------------------------------
6713 +bool os::find(address addr, outputStream* st) {
6714 + Dl_info dlinfo;
6715 + memset(&dlinfo, 0, sizeof(dlinfo));
6716 + if (dladdr(addr, &dlinfo) != 0) {
6717 + st->print(PTR_FORMAT ": ", p2i(addr));
6718 + if (dlinfo.dli_sname != NULL && dlinfo.dli_saddr != NULL) {
6719 + st->print("%s+" PTR_FORMAT, dlinfo.dli_sname,
6720 + p2i(addr) - p2i(dlinfo.dli_saddr));
6721 + } else if (dlinfo.dli_fbase != NULL) {
6722 + st->print("<offset " PTR_FORMAT ">", p2i(addr) - p2i(dlinfo.dli_fbase));
6723 + } else {
6724 + st->print("<absolute address>");
6726 + if (dlinfo.dli_fname != NULL) {
6727 + st->print(" in %s", dlinfo.dli_fname);
6729 + if (dlinfo.dli_fbase != NULL) {
6730 + st->print(" at " PTR_FORMAT, p2i(dlinfo.dli_fbase));
6732 + st->cr();
6734 + if (Verbose) {
6735 + // decode some bytes around the PC
6736 + address begin = clamp_address_in_page(addr-40, addr, os::vm_page_size());
6737 + address end = clamp_address_in_page(addr+40, addr, os::vm_page_size());
6738 + address lowest = (address) dlinfo.dli_sname;
6739 + if (!lowest) lowest = (address) dlinfo.dli_fbase;
6740 + if (begin < lowest) begin = lowest;
6741 + Dl_info dlinfo2;
6742 + if (dladdr(end, &dlinfo2) != 0 && dlinfo2.dli_saddr != dlinfo.dli_saddr
6743 + && end > dlinfo2.dli_saddr && dlinfo2.dli_saddr > begin) {
6744 + end = (address) dlinfo2.dli_saddr;
6746 + Disassembler::decode(begin, end, st);
6748 + return true;
6750 + return false;
6753 +// Following function has been added to support HotSparc's libjvm.so running
6754 +// under Solaris production JDK 1.2.2 / 1.3.0. These came from
6755 +// src/solaris/hpi/native_threads in the EVM codebase.
6757 +// NOTE: This is no longer needed in the 1.3.1 and 1.4 production release
6758 +// libraries and should thus be removed. We will leave it behind for a while
6759 +// until we no longer want to able to run on top of 1.3.0 Solaris production
6760 +// JDK. See 4341971.
6762 +#define STACK_SLACK 0x800
6764 +extern "C" {
6765 + intptr_t sysThreadAvailableStackWithSlack() {
6766 + stack_t st;
6767 + intptr_t retval, stack_top;
6768 + retval = thr_stksegment(&st);
6769 + assert(retval == 0, "incorrect return value from thr_stksegment");
6770 + assert((address)&st < (address)st.ss_sp, "Invalid stack base returned");
6771 + assert((address)&st > (address)st.ss_sp-st.ss_size, "Invalid stack size returned");
6772 + stack_top=(intptr_t)st.ss_sp-st.ss_size;
6773 + return ((intptr_t)&stack_top - stack_top - STACK_SLACK);
6777 +// ObjectMonitor park-unpark infrastructure ...
6779 +// We implement Solaris and Linux PlatformEvents with the
6780 +// obvious condvar-mutex-flag triple.
6781 +// Another alternative that works quite well is pipes:
6782 +// Each PlatformEvent consists of a pipe-pair.
6783 +// The thread associated with the PlatformEvent
6784 +// calls park(), which reads from the input end of the pipe.
6785 +// Unpark() writes into the other end of the pipe.
6786 +// The write-side of the pipe must be set NDELAY.
6787 +// Unfortunately pipes consume a large # of handles.
6788 +// Native solaris lwp_park() and lwp_unpark() work nicely, too.
6789 +// Using pipes for the 1st few threads might be workable, however.
6791 +// park() is permitted to return spuriously.
6792 +// Callers of park() should wrap the call to park() in
6793 +// an appropriate loop. A litmus test for the correct
6794 +// usage of park is the following: if park() were modified
6795 +// to immediately return 0 your code should still work,
6796 +// albeit degenerating to a spin loop.
6798 +// In a sense, park()-unpark() just provides more polite spinning
6799 +// and polling with the key difference over naive spinning being
6800 +// that a parked thread needs to be explicitly unparked() in order
6801 +// to wake up and to poll the underlying condition.
6803 +// Assumption:
6804 +// Only one parker can exist on an event, which is why we allocate
6805 +// them per-thread. Multiple unparkers can coexist.
6807 +// _event transitions in park()
6808 +// -1 => -1 : illegal
6809 +// 1 => 0 : pass - return immediately
6810 +// 0 => -1 : block; then set _event to 0 before returning
6812 +// _event transitions in unpark()
6813 +// 0 => 1 : just return
6814 +// 1 => 1 : just return
6815 +// -1 => either 0 or 1; must signal target thread
6816 +// That is, we can safely transition _event from -1 to either
6817 +// 0 or 1.
6819 +// _event serves as a restricted-range semaphore.
6820 +// -1 : thread is blocked, i.e. there is a waiter
6821 +// 0 : neutral: thread is running or ready,
6822 +// could have been signaled after a wait started
6823 +// 1 : signaled - thread is running or ready
6825 +// Another possible encoding of _event would be with
6826 +// explicit "PARKED" == 01b and "SIGNALED" == 10b bits.
6828 +// TODO-FIXME: add DTRACE probes for:
6829 +// 1. Tx parks
6830 +// 2. Ty unparks Tx
6831 +// 3. Tx resumes from park
6833 +// JSR166
6834 +// -------------------------------------------------------
6836 +// The solaris and linux implementations of park/unpark are fairly
6837 +// conservative for now, but can be improved. They currently use a
6838 +// mutex/condvar pair, plus _counter.
6839 +// Park decrements _counter if > 0, else does a condvar wait. Unpark
6840 +// sets count to 1 and signals condvar. Only one thread ever waits
6841 +// on the condvar. Contention seen when trying to park implies that someone
6842 +// is unparking you, so don't wait. And spurious returns are fine, so there
6843 +// is no need to track notifications.
6845 +// Get the default path to the core file
6846 +// Returns the length of the string
6847 +int os::get_core_path(char* buffer, size_t bufferSize) {
6848 + const char* p = get_current_directory(buffer, bufferSize);
6850 + if (p == NULL) {
6851 + assert(p != NULL, "failed to get current directory");
6852 + return 0;
6855 + jio_snprintf(buffer, bufferSize, "%s/core or core.%d",
6856 + p, current_process_id());
6858 + return strlen(buffer);
6861 +bool os::supports_map_sync() {
6862 + return false;
6865 +#ifndef PRODUCT
6866 +void TestReserveMemorySpecial_test() {
6867 + // No tests available for this platform
6869 +#endif
6871 +bool os::start_debugging(char *buf, int buflen) {
6872 + int len = (int)strlen(buf);
6873 + char *p = &buf[len];
6875 + jio_snprintf(p, buflen-len,
6876 + "\n\n"
6877 + "Do you want to debug the problem?\n\n"
6878 + "To debug, run 'dbx - %d'; then switch to thread " INTX_FORMAT "\n"
6879 + "Enter 'yes' to launch dbx automatically (PATH must include dbx)\n"
6880 + "Otherwise, press RETURN to abort...",
6881 + os::current_process_id(), os::current_thread_id());
6883 + bool yes = os::message_box("Unexpected Error", buf);
6885 + if (yes) {
6886 + // yes, user asked VM to launch debugger
6887 + jio_snprintf(buf, sizeof(buf), "dbx - %d", os::current_process_id());
6889 + os::fork_and_exec(buf);
6890 + yes = false;
6892 + return yes;
6895 +void os::print_memory_mappings(char* addr, size_t bytes, outputStream* st) {}
6897 +#if INCLUDE_JFR
6899 +void os::jfr_report_memory_info() {}
6901 +#endif // INCLUDE_JFR
6903 +bool os::pd_dll_unload(void* libhandle, char* ebuf, int ebuflen) {
6905 + if (ebuf && ebuflen > 0) {
6906 + ebuf[0] = '\0';
6907 + ebuf[ebuflen - 1] = '\0';
6910 + bool res = (0 == ::dlclose(libhandle));
6911 + if (!res) {
6912 + // error analysis when dlopen fails
6913 + const char* error_report = ::dlerror();
6914 + if (error_report == nullptr) {
6915 + error_report = "dlerror returned no error description";
6917 + if (ebuf != nullptr && ebuflen > 0) {
6918 + snprintf(ebuf, ebuflen - 1, "%s", error_report);
6922 + return res;
6923 +} // end: os::pd_dll_unload()
6924 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/os/solaris/os_solaris.hpp jdk23u-jdk-23-36/src/hotspot/os/solaris/os_solaris.hpp
6925 --- jdk23u-jdk-23-36.orig/src/hotspot/os/solaris/os_solaris.hpp 1970-01-01 01:00:00.000000000 +0100
6926 +++ jdk23u-jdk-23-36/src/hotspot/os/solaris/os_solaris.hpp 2024-08-17 19:50:33.145845258 +0200
6927 @@ -0,0 +1,201 @@
6929 + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
6930 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6932 + * This code is free software; you can redistribute it and/or modify it
6933 + * under the terms of the GNU General Public License version 2 only, as
6934 + * published by the Free Software Foundation.
6936 + * This code is distributed in the hope that it will be useful, but WITHOUT
6937 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
6938 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
6939 + * version 2 for more details (a copy is included in the LICENSE file that
6940 + * accompanied this code).
6942 + * You should have received a copy of the GNU General Public License version
6943 + * 2 along with this work; if not, write to the Free Software Foundation,
6944 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
6946 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
6947 + * or visit www.oracle.com if you need additional information or have any
6948 + * questions.
6950 + */
6952 +#ifndef OS_SOLARIS_OS_SOLARIS_HPP
6953 +#define OS_SOLARIS_OS_SOLARIS_HPP
6955 +#include "runtime/os.hpp"
6957 +// Solaris_OS defines the interface to Solaris operating systems
6959 +// see thr_setprio(3T) for the basis of these numbers
6960 +#define MinimumPriority 0
6961 +#define NormalPriority 64
6962 +#define MaximumPriority 127
6964 +// FX/60 is critical thread class/priority on T4
6965 +#define FXCriticalPriority 60
6967 +class os::Solaris {
6968 + friend class os;
6970 + private:
6972 + static bool _synchronization_initialized;
6974 + typedef uintptr_t lgrp_cookie_t;
6975 + typedef id_t lgrp_id_t;
6976 + typedef int lgrp_rsrc_t;
6977 + typedef enum lgrp_view {
6978 + LGRP_VIEW_CALLER, // what's available to the caller
6979 + LGRP_VIEW_OS // what's available to operating system
6980 + } lgrp_view_t;
6982 + typedef lgrp_id_t (*lgrp_home_func_t)(idtype_t idtype, id_t id);
6983 + typedef lgrp_cookie_t (*lgrp_init_func_t)(lgrp_view_t view);
6984 + typedef int (*lgrp_fini_func_t)(lgrp_cookie_t cookie);
6985 + typedef lgrp_id_t (*lgrp_root_func_t)(lgrp_cookie_t cookie);
6986 + typedef int (*lgrp_children_func_t)(lgrp_cookie_t cookie, lgrp_id_t parent,
6987 + lgrp_id_t *lgrp_array, uint_t lgrp_array_size);
6988 + typedef int (*lgrp_resources_func_t)(lgrp_cookie_t cookie, lgrp_id_t lgrp,
6989 + lgrp_id_t *lgrp_array, uint_t lgrp_array_size,
6990 + lgrp_rsrc_t type);
6991 + typedef int (*lgrp_nlgrps_func_t)(lgrp_cookie_t cookie);
6992 + typedef int (*lgrp_cookie_stale_func_t)(lgrp_cookie_t cookie);
6994 + static lgrp_home_func_t _lgrp_home;
6995 + static lgrp_init_func_t _lgrp_init;
6996 + static lgrp_fini_func_t _lgrp_fini;
6997 + static lgrp_root_func_t _lgrp_root;
6998 + static lgrp_children_func_t _lgrp_children;
6999 + static lgrp_resources_func_t _lgrp_resources;
7000 + static lgrp_nlgrps_func_t _lgrp_nlgrps;
7001 + static lgrp_cookie_stale_func_t _lgrp_cookie_stale;
7002 + static lgrp_cookie_t _lgrp_cookie;
7004 + // Large Page Support
7005 + static bool is_valid_page_size(size_t bytes);
7006 + static size_t page_size_for_alignment(size_t alignment);
7007 + static bool setup_large_pages(caddr_t start, size_t bytes, size_t align);
7009 + typedef int (*pthread_setname_np_func_t)(pthread_t, const char*);
7010 + static pthread_setname_np_func_t _pthread_setname_np;
7012 + public:
7013 + // Large Page Support--ISM.
7014 + static bool largepage_range(char* addr, size_t size);
7016 + static address handler_start, handler_end; // start and end pc of thr_sighndlrinfo
7018 + static bool valid_ucontext(Thread* thread, const ucontext_t* valid, const ucontext_t* suspect);
7019 + static const ucontext_t* get_valid_uc_in_signal_handler(Thread* thread,
7020 + const ucontext_t* uc);
7022 + static intptr_t* ucontext_get_sp(const ucontext_t* uc);
7023 + // ucontext_get_fp() is only used by Solaris X86 (see note below)
7024 + static intptr_t* ucontext_get_fp(const ucontext_t* uc);
7026 + static bool get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr);
7028 + static void init_thread_fpu_state(void);
7030 + protected:
7031 + // Solaris-specific interface goes here
7032 + static julong available_memory();
7033 + static julong free_memory();
7034 + static julong physical_memory() { return _physical_memory; }
7035 + static julong _physical_memory;
7036 + static void initialize_system_info();
7037 + static int _dev_zero_fd;
7038 + static int get_dev_zero_fd() { return _dev_zero_fd; }
7039 + static void set_dev_zero_fd(int fd) { _dev_zero_fd = fd; }
7040 + static int commit_memory_impl(char* addr, size_t bytes, bool exec);
7041 + static int commit_memory_impl(char* addr, size_t bytes,
7042 + size_t alignment_hint, bool exec);
7043 + static char* mmap_chunk(char *addr, size_t size, int flags, int prot);
7044 + static char* anon_mmap(char* requested_addr, size_t bytes);
7045 + static bool mpss_sanity_check(bool warn, size_t * page_size);
7047 + static address current_stack_base();
7048 + static size_t current_stack_size();
7050 + // Workaround for 4352906. thr_stksegment sometimes returns
7051 + // a bad value for the primordial thread's stack base when
7052 + // it is called more than one time.
7053 + // Workaround is to cache the initial value to avoid further
7054 + // calls to thr_stksegment.
7055 + // It appears that someone (Hotspot?) is trashing the user's
7056 + // proc_t structure (note that this is a system struct).
7057 + static address _main_stack_base;
7059 + static void print_distro_info(outputStream* st);
7060 + static void print_libversion_info(outputStream* st);
7062 + public:
7063 + static void libthread_init();
7064 + static void synchronization_init();
7065 + static bool liblgrp_init();
7067 + // alignment with os_posix means we use pthreads
7068 + static int mutex_lock(pthread_mutex_t *mx) { return pthread_mutex_lock(mx); }
7069 + static int mutex_trylock(pthread_mutex_t *mx) { return pthread_mutex_trylock(mx); }
7070 + static int mutex_unlock(pthread_mutex_t *mx) { return pthread_mutex_unlock(mx); }
7071 + static int mutex_init(pthread_mutex_t *mx) { return pthread_mutex_init(mx, NULL); }
7072 + static int mutex_destroy(pthread_mutex_t *mx) { return pthread_mutex_destroy(mx); }
7074 + static int cond_timedwait(pthread_cond_t *cv, pthread_mutex_t *mx, timestruc_t *abst) { return pthread_cond_timedwait(cv, mx, abst); }
7075 + static int cond_wait(pthread_cond_t *cv, pthread_mutex_t *mx) { return pthread_cond_wait(cv, mx); }
7076 + static int cond_signal(pthread_cond_t *cv) { return pthread_cond_signal(cv); }
7077 + static int cond_broadcast(pthread_cond_t *cv) { return pthread_cond_broadcast(cv); }
7078 + static int cond_init(pthread_cond_t *cv) { return pthread_cond_init(cv, NULL); }
7079 + static int cond_destroy(pthread_cond_t *cv) { return pthread_cond_destroy(cv); }
7081 + static bool synchronization_initialized() { return _synchronization_initialized; }
7083 + static void set_lgrp_home(lgrp_home_func_t func) { _lgrp_home = func; }
7084 + static void set_lgrp_init(lgrp_init_func_t func) { _lgrp_init = func; }
7085 + static void set_lgrp_fini(lgrp_fini_func_t func) { _lgrp_fini = func; }
7086 + static void set_lgrp_root(lgrp_root_func_t func) { _lgrp_root = func; }
7087 + static void set_lgrp_children(lgrp_children_func_t func) { _lgrp_children = func; }
7088 + static void set_lgrp_resources(lgrp_resources_func_t func) { _lgrp_resources = func; }
7089 + static void set_lgrp_nlgrps(lgrp_nlgrps_func_t func) { _lgrp_nlgrps = func; }
7090 + static void set_lgrp_cookie_stale(lgrp_cookie_stale_func_t func) { _lgrp_cookie_stale = func; }
7091 + static void set_lgrp_cookie(lgrp_cookie_t cookie) { _lgrp_cookie = cookie; }
7093 + static id_t lgrp_home(idtype_t type, id_t id) { return _lgrp_home != NULL ? _lgrp_home(type, id) : -1; }
7094 + static lgrp_cookie_t lgrp_init(lgrp_view_t view) { return _lgrp_init != NULL ? _lgrp_init(view) : 0; }
7095 + static int lgrp_fini(lgrp_cookie_t cookie) { return _lgrp_fini != NULL ? _lgrp_fini(cookie) : -1; }
7096 + static lgrp_id_t lgrp_root(lgrp_cookie_t cookie) { return _lgrp_root != NULL ? _lgrp_root(cookie) : -1; }
7097 + static int lgrp_children(lgrp_cookie_t cookie, lgrp_id_t parent,
7098 + lgrp_id_t *lgrp_array, uint_t lgrp_array_size) {
7099 + return _lgrp_children != NULL ? _lgrp_children(cookie, parent, lgrp_array, lgrp_array_size) : -1;
7101 + static int lgrp_resources(lgrp_cookie_t cookie, lgrp_id_t lgrp,
7102 + lgrp_id_t *lgrp_array, uint_t lgrp_array_size,
7103 + lgrp_rsrc_t type) {
7104 + return _lgrp_resources != NULL ? _lgrp_resources(cookie, lgrp, lgrp_array, lgrp_array_size, type) : -1;
7107 + static int lgrp_nlgrps(lgrp_cookie_t cookie) { return _lgrp_nlgrps != NULL ? _lgrp_nlgrps(cookie) : -1; }
7108 + static int lgrp_cookie_stale(lgrp_cookie_t cookie) {
7109 + return _lgrp_cookie_stale != NULL ? _lgrp_cookie_stale(cookie) : -1;
7111 + static lgrp_cookie_t lgrp_cookie() { return _lgrp_cookie; }
7113 + static sigset_t* unblocked_signals();
7114 + static sigset_t* vm_signals();
7116 + // %%% Following should be promoted to os.hpp:
7117 + // Trace number of created threads
7118 + static jint _os_thread_limit;
7119 + static volatile jint _os_thread_count;
7121 + static void correct_stack_boundaries_for_primordial_thread(Thread* thr);
7123 + // Stack repair handling
7125 + // none present
7128 +#endif // OS_SOLARIS_OS_SOLARIS_HPP
7129 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/os/solaris/os_solaris.inline.hpp jdk23u-jdk-23-36/src/hotspot/os/solaris/os_solaris.inline.hpp
7130 --- jdk23u-jdk-23-36.orig/src/hotspot/os/solaris/os_solaris.inline.hpp 1970-01-01 01:00:00.000000000 +0100
7131 +++ jdk23u-jdk-23-36/src/hotspot/os/solaris/os_solaris.inline.hpp 2024-08-17 19:50:33.146105432 +0200
7132 @@ -0,0 +1,72 @@
7134 + * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
7135 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7137 + * This code is free software; you can redistribute it and/or modify it
7138 + * under the terms of the GNU General Public License version 2 only, as
7139 + * published by the Free Software Foundation.
7141 + * This code is distributed in the hope that it will be useful, but WITHOUT
7142 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7143 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7144 + * version 2 for more details (a copy is included in the LICENSE file that
7145 + * accompanied this code).
7147 + * You should have received a copy of the GNU General Public License version
7148 + * 2 along with this work; if not, write to the Free Software Foundation,
7149 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7151 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7152 + * or visit www.oracle.com if you need additional information or have any
7153 + * questions.
7155 + */
7157 +#ifndef OS_SOLARIS_OS_SOLARIS_INLINE_HPP
7158 +#define OS_SOLARIS_OS_SOLARIS_INLINE_HPP
7160 +#include "os_solaris.hpp"
7162 +#include "runtime/os.hpp"
7163 +#include "os_posix.inline.hpp"
7165 +// System includes
7166 +#include <sys/param.h>
7167 +#include <dlfcn.h>
7168 +#include <sys/socket.h>
7169 +#include <poll.h>
7170 +#include <sys/filio.h>
7171 +#include <unistd.h>
7172 +#include <netdb.h>
7173 +#include <setjmp.h>
7175 +inline bool os::zero_page_read_protected() {
7176 + return true;
7179 +inline bool os::uses_stack_guard_pages() {
7180 + return true;
7183 +inline bool os::must_commit_stack_guard_pages() {
7184 + assert(uses_stack_guard_pages(), "sanity check");
7185 + int r = thr_main() ;
7186 + guarantee (r == 0 || r == 1, "CR6501650 or CR6493689") ;
7187 + return r;
7191 +// Bang the shadow pages if they need to be touched to be mapped.
7192 +inline void os::map_stack_shadow_pages(address sp) {
7195 +// stubbed-out trim-native support
7196 +inline bool os::can_trim_native_heap() { return false; }
7197 +inline bool os::trim_native_heap(os::size_change_t* rss_change) { return false; }
7199 +//////////////////////////////////////////////////////////////////////////////
7200 +////////////////////////////////////////////////////////////////////////////////
7202 +inline bool os::numa_has_group_homing() { return true; }
7204 +#endif // OS_SOLARIS_OS_SOLARIS_INLINE_HPP
7205 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/os/solaris/osThread_solaris.cpp jdk23u-jdk-23-36/src/hotspot/os/solaris/osThread_solaris.cpp
7206 --- jdk23u-jdk-23-36.orig/src/hotspot/os/solaris/osThread_solaris.cpp 1970-01-01 01:00:00.000000000 +0100
7207 +++ jdk23u-jdk-23-36/src/hotspot/os/solaris/osThread_solaris.cpp 2024-08-17 19:50:33.143071799 +0200
7208 @@ -0,0 +1,47 @@
7210 + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
7211 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7213 + * This code is free software; you can redistribute it and/or modify it
7214 + * under the terms of the GNU General Public License version 2 only, as
7215 + * published by the Free Software Foundation.
7217 + * This code is distributed in the hope that it will be useful, but WITHOUT
7218 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7219 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7220 + * version 2 for more details (a copy is included in the LICENSE file that
7221 + * accompanied this code).
7223 + * You should have received a copy of the GNU General Public License version
7224 + * 2 along with this work; if not, write to the Free Software Foundation,
7225 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7227 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7228 + * or visit www.oracle.com if you need additional information or have any
7229 + * questions.
7231 + */
7233 +// no precompiled headers
7234 +#include "runtime/handles.inline.hpp"
7235 +#include "runtime/mutexLocker.hpp"
7236 +#include "runtime/os.hpp"
7237 +#include "runtime/osThread.hpp"
7238 +#include "runtime/safepoint.hpp"
7239 +#include "runtime/vmThread.hpp"
7241 +#include <signal.h>
7243 + // ***************************************************************
7244 + // Platform dependent initialization and cleanup
7245 + // ***************************************************************
7247 +void OSThread::pd_initialize() {
7248 + _thread_id = 0;
7249 + sigemptyset(&_caller_sigmask);
7251 + _vm_created_thread = false;
7254 +void OSThread::pd_destroy() {
7256 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/os/solaris/osThread_solaris.hpp jdk23u-jdk-23-36/src/hotspot/os/solaris/osThread_solaris.hpp
7257 --- jdk23u-jdk-23-36.orig/src/hotspot/os/solaris/osThread_solaris.hpp 1970-01-01 01:00:00.000000000 +0100
7258 +++ jdk23u-jdk-23-36/src/hotspot/os/solaris/osThread_solaris.hpp 2024-08-17 19:50:33.143330936 +0200
7259 @@ -0,0 +1,93 @@
7261 + * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
7262 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7264 + * This code is free software; you can redistribute it and/or modify it
7265 + * under the terms of the GNU General Public License version 2 only, as
7266 + * published by the Free Software Foundation.
7268 + * This code is distributed in the hope that it will be useful, but WITHOUT
7269 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7270 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7271 + * version 2 for more details (a copy is included in the LICENSE file that
7272 + * accompanied this code).
7274 + * You should have received a copy of the GNU General Public License version
7275 + * 2 along with this work; if not, write to the Free Software Foundation,
7276 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7278 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7279 + * or visit www.oracle.com if you need additional information or have any
7280 + * questions.
7282 + */
7284 +#ifndef OS_SOLARIS_OSTHREAD_SOLARIS_HPP
7285 +#define OS_SOLARIS_OSTHREAD_SOLARIS_HPP
7287 +// This is embedded via include into the class OSThread
7288 + public:
7289 + typedef thread_t thread_id_t;
7291 + private:
7292 + uint _lwp_id; // lwp ID, only used with bound threads
7293 + int _native_priority; // Saved native priority when starting
7294 + // a bound thread
7295 + sigset_t _caller_sigmask; // Caller's signal mask
7296 + bool _vm_created_thread; // true if the VM created this thread,
7297 + // false if primary thread or attached thread
7298 + public:
7299 + uint lwp_id() const { return _lwp_id; }
7300 + int native_priority() const { return _native_priority; }
7302 + // Set and get state of _vm_created_thread flag
7303 + void set_vm_created() { _vm_created_thread = true; }
7304 + bool is_vm_created() { return _vm_created_thread; }
7306 + // Methods to save/restore caller's signal mask
7307 + sigset_t caller_sigmask() const { return _caller_sigmask; }
7308 + void set_caller_sigmask(sigset_t sigmask) { _caller_sigmask = sigmask; }
7310 +#ifndef PRODUCT
7311 + // Used for debugging, return a unique integer for each thread.
7312 + int thread_identifier() const { return _thread_id; }
7313 +#endif
7314 +#ifdef ASSERT
7315 + // On solaris reposition can fail in two ways:
7316 + // 1: a mismatched pc, because signal is delivered too late, target thread
7317 + // is resumed.
7318 + // 2: on a timeout where signal is lost, target thread is resumed.
7319 + bool valid_reposition_failure() {
7320 + // only 1 and 2 can happen and we can handle both of them
7321 + return true;
7323 +#endif
7324 + void set_lwp_id(uint id) { _lwp_id = id; }
7325 + void set_native_priority(int prio) { _native_priority = prio; }
7327 + public:
7328 + pthread_t pthread_id() const {
7329 + // Here: same as OSThread::thread_id()
7330 + return _thread_id;
7332 + SuspendResume sr;
7334 + private:
7335 + void* _siginfo;
7336 + ucontext_t* _ucontext;
7338 + public:
7339 + void set_siginfo(void* ptr) { _siginfo = ptr; }
7340 + ucontext_t* ucontext() const { return _ucontext; }
7341 + void set_ucontext(ucontext_t* ptr) { _ucontext = ptr; }
7343 + // ***************************************************************
7344 + // Platform dependent initialization and cleanup
7345 + // ***************************************************************
7347 +private:
7349 + void pd_initialize();
7350 + void pd_destroy();
7352 +#endif // OS_SOLARIS_OSTHREAD_SOLARIS_HPP
7353 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/os/solaris/vmStructs_solaris.hpp jdk23u-jdk-23-36/src/hotspot/os/solaris/vmStructs_solaris.hpp
7354 --- jdk23u-jdk-23-36.orig/src/hotspot/os/solaris/vmStructs_solaris.hpp 1970-01-01 01:00:00.000000000 +0100
7355 +++ jdk23u-jdk-23-36/src/hotspot/os/solaris/vmStructs_solaris.hpp 2024-08-17 19:50:33.146349617 +0200
7356 @@ -0,0 +1,44 @@
7358 + * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
7359 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7361 + * This code is free software; you can redistribute it and/or modify it
7362 + * under the terms of the GNU General Public License version 2 only, as
7363 + * published by the Free Software Foundation.
7365 + * This code is distributed in the hope that it will be useful, but WITHOUT
7366 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7367 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7368 + * version 2 for more details (a copy is included in the LICENSE file that
7369 + * accompanied this code).
7371 + * You should have received a copy of the GNU General Public License version
7372 + * 2 along with this work; if not, write to the Free Software Foundation,
7373 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7375 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7376 + * or visit www.oracle.com if you need additional information or have any
7377 + * questions.
7379 + */
7381 +#ifndef OS_SOLARIS_VMSTRUCTS_SOLARIS_HPP
7382 +#define OS_SOLARIS_VMSTRUCTS_SOLARIS_HPP
7384 +// These are the OS-specific fields, types and integer
7385 +// constants required by the Serviceability Agent. This file is
7386 +// referenced by vmStructs.cpp.
7388 +#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) \
7389 + nonstatic_field(OSThread, _thread_id, OSThread::thread_id_t)
7391 +#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) \
7392 + declare_unsigned_integer_type(OSThread::thread_id_t)
7394 +#define VM_INT_CONSTANTS_OS(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
7396 +#define VM_LONG_CONSTANTS_OS(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
7398 +#define VM_ADDRESSES_OS(declare_address, declare_preprocessor_address, declare_function)
7400 +#endif // OS_SOLARIS_VMSTRUCTS_SOLARIS_HPP
7401 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/os_cpu/solaris_x86/assembler_solaris_x86.cpp jdk23u-jdk-23-36/src/hotspot/os_cpu/solaris_x86/assembler_solaris_x86.cpp
7402 --- jdk23u-jdk-23-36.orig/src/hotspot/os_cpu/solaris_x86/assembler_solaris_x86.cpp 1970-01-01 01:00:00.000000000 +0100
7403 +++ jdk23u-jdk-23-36/src/hotspot/os_cpu/solaris_x86/assembler_solaris_x86.cpp 2024-08-17 19:50:33.146734343 +0200
7404 @@ -0,0 +1,37 @@
7406 + * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
7407 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7409 + * This code is free software; you can redistribute it and/or modify it
7410 + * under the terms of the GNU General Public License version 2 only, as
7411 + * published by the Free Software Foundation.
7413 + * This code is distributed in the hope that it will be useful, but WITHOUT
7414 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7415 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7416 + * version 2 for more details (a copy is included in the LICENSE file that
7417 + * accompanied this code).
7419 + * You should have received a copy of the GNU General Public License version
7420 + * 2 along with this work; if not, write to the Free Software Foundation,
7421 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7423 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7424 + * or visit www.oracle.com if you need additional information or have any
7425 + * questions.
7427 + */
7429 +#include "precompiled.hpp"
7430 +#include "asm/macroAssembler.inline.hpp"
7431 +#include "runtime/os.hpp"
7433 +void MacroAssembler::int3() {
7434 + push(rax);
7435 + push(rdx);
7436 + push(rcx);
7437 + call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint)));
7438 + pop(rcx);
7439 + pop(rdx);
7440 + pop(rax);
7442 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/os_cpu/solaris_x86/atomic_solaris_x86.hpp jdk23u-jdk-23-36/src/hotspot/os_cpu/solaris_x86/atomic_solaris_x86.hpp
7443 --- jdk23u-jdk-23-36.orig/src/hotspot/os_cpu/solaris_x86/atomic_solaris_x86.hpp 1970-01-01 01:00:00.000000000 +0100
7444 +++ jdk23u-jdk-23-36/src/hotspot/os_cpu/solaris_x86/atomic_solaris_x86.hpp 2024-08-17 19:50:33.147051687 +0200
7445 @@ -0,0 +1,182 @@
7447 + * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
7448 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7450 + * This code is free software; you can redistribute it and/or modify it
7451 + * under the terms of the GNU General Public License version 2 only, as
7452 + * published by the Free Software Foundation.
7454 + * This code is distributed in the hope that it will be useful, but WITHOUT
7455 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7456 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7457 + * version 2 for more details (a copy is included in the LICENSE file that
7458 + * accompanied this code).
7460 + * You should have received a copy of the GNU General Public License version
7461 + * 2 along with this work; if not, write to the Free Software Foundation,
7462 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7464 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7465 + * or visit www.oracle.com if you need additional information or have any
7466 + * questions.
7468 + */
7470 +#ifndef OS_CPU_SOLARIS_X86_ATOMIC_SOLARIS_X86_HPP
7471 +#define OS_CPU_SOLARIS_X86_ATOMIC_SOLARIS_X86_HPP
7473 +inline int32_t _Atomic_add(int32_t add_value, volatile int32_t* dest) {
7474 + int32_t rv = add_value;
7475 + __asm__ volatile ("lock xaddl %0,(%2)"
7476 + : "=r" (rv)
7477 + : "0" (rv), "r" (dest)
7478 + : "cc", "memory");
7479 + return rv + add_value;
7481 +inline int64_t _Atomic_add_long(int64_t add_value, volatile int64_t* dest) {
7482 + int64_t rv = add_value;
7483 + __asm__ volatile ("lock xaddq %0,(%2)"
7484 + : "=r" (rv)
7485 + : "0" (rv), "r" (dest)
7486 + : "cc", "memory");
7487 + return rv + add_value;
7489 +inline int32_t _Atomic_xchg(int32_t exchange_value, volatile int32_t* dest) {
7490 + __asm__ __volatile__ ("xchgl (%2),%0"
7491 + : "=r" (exchange_value)
7492 + : "0" (exchange_value), "r" (dest)
7493 + : "memory");
7494 + return exchange_value;
7496 +inline int64_t _Atomic_xchg_long(int64_t exchange_value, volatile int64_t* dest) {
7497 + __asm__ __volatile__ ("xchgq (%2),%0"
7498 + : "=r" (exchange_value)
7499 + : "0" (exchange_value), "r" (dest)
7500 + : "memory");
7501 + return exchange_value;
7503 +inline int8_t _Atomic_cmpxchg_byte(int8_t exchange_value, volatile int8_t* dest, int8_t compare_value) {
7504 + __asm__ volatile ("lock cmpxchgb %1,(%3)"
7505 + : "=a" (exchange_value)
7506 + : "q" (exchange_value), "a" (compare_value), "r" (dest)
7507 + : "cc", "memory");
7508 + return exchange_value;
7510 +inline int32_t _Atomic_cmpxchg(int32_t exchange_value, volatile int32_t* dest, int32_t compare_value) {
7511 + __asm__ volatile ("lock cmpxchgl %1,(%3)"
7512 + : "=a" (exchange_value)
7513 + : "q" (exchange_value), "a" (compare_value), "r" (dest)
7514 + : "cc", "memory");
7515 + return exchange_value;
7517 +inline int64_t _Atomic_cmpxchg_long(int64_t exchange_value, volatile int64_t* dest, int64_t compare_value) {
7518 + __asm__ volatile ("lock cmpxchgq %1,(%3)"
7519 + : "=a" (exchange_value)
7520 + : "q" (exchange_value), "a" (compare_value), "r" (dest)
7521 + : "cc", "memory");
7522 + return exchange_value;
7525 +template<size_t byte_size>
7526 +struct Atomic::PlatformAdd {
7527 + template<typename D, typename I>
7528 + D add_then_fetch(D volatile* dest, I add_value, atomic_memory_order order) const;
7530 + template<typename D, typename I>
7531 + D fetch_then_add(D volatile* dest, I add_value, atomic_memory_order order) const {
7532 + return add_then_fetch(dest, add_value, order) - add_value;
7536 +// Not using add_using_helper; see comment for cmpxchg.
7537 +template<>
7538 +template<typename D, typename I>
7539 +inline D Atomic::PlatformAdd<4>::add_then_fetch(D volatile* dest, I add_value,
7540 + atomic_memory_order order) const {
7541 + STATIC_ASSERT(4 == sizeof(I));
7542 + STATIC_ASSERT(4 == sizeof(D));
7543 + return PrimitiveConversions::cast<D>(
7544 + _Atomic_add(PrimitiveConversions::cast<int32_t>(add_value),
7545 + reinterpret_cast<int32_t volatile*>(dest)));
7548 +// Not using add_using_helper; see comment for cmpxchg.
7549 +template<>
7550 +template<typename D, typename I>
7551 +inline D Atomic::PlatformAdd<8>::add_then_fetch(D volatile* dest, I add_value,
7552 + atomic_memory_order order) const {
7553 + STATIC_ASSERT(8 == sizeof(I));
7554 + STATIC_ASSERT(8 == sizeof(D));
7555 + return PrimitiveConversions::cast<D>(
7556 + _Atomic_add_long(PrimitiveConversions::cast<int64_t>(add_value),
7557 + reinterpret_cast<int64_t volatile*>(dest)));
7560 +template<>
7561 +template<typename T>
7562 +inline T Atomic::PlatformXchg<4>::operator()(T volatile* dest,
7563 + T exchange_value,
7564 + atomic_memory_order order) const {
7565 + STATIC_ASSERT(4 == sizeof(T));
7566 + return PrimitiveConversions::cast<T>(
7567 + _Atomic_xchg(PrimitiveConversions::cast<int32_t>(exchange_value),
7568 + reinterpret_cast<int32_t volatile*>(dest)));
7571 +template<>
7572 +template<typename T>
7573 +inline T Atomic::PlatformXchg<8>::operator()(T volatile* dest,
7574 + T exchange_value,
7575 + atomic_memory_order order) const {
7576 + STATIC_ASSERT(8 == sizeof(T));
7577 + return PrimitiveConversions::cast<T>(
7578 + _Atomic_xchg_long(PrimitiveConversions::cast<int64_t>(exchange_value),
7579 + reinterpret_cast<int64_t volatile*>(dest)));
7582 +// Not using cmpxchg_using_helper here, because some configurations of
7583 +// Solaris compiler don't deal well with passing a "defined in .il"
7584 +// function as an argument. We *should* switch to using gcc-style
7585 +// inline assembly, but attempting to do so with Studio 12.4 ran into
7586 +// segfaults.
7588 +template<>
7589 +template<typename T>
7590 +inline T Atomic::PlatformCmpxchg<1>::operator()(T volatile* dest,
7591 + T compare_value,
7592 + T exchange_value,
7593 + atomic_memory_order order) const {
7594 + STATIC_ASSERT(1 == sizeof(T));
7595 + return PrimitiveConversions::cast<T>(
7596 + _Atomic_cmpxchg_byte(PrimitiveConversions::cast<int8_t>(exchange_value),
7597 + reinterpret_cast<int8_t volatile*>(dest),
7598 + PrimitiveConversions::cast<int8_t>(compare_value)));
7601 +template<>
7602 +template<typename T>
7603 +inline T Atomic::PlatformCmpxchg<4>::operator()(T volatile* dest,
7604 + T compare_value,
7605 + T exchange_value,
7606 + atomic_memory_order order) const {
7607 + STATIC_ASSERT(4 == sizeof(T));
7608 + return PrimitiveConversions::cast<T>(
7609 + _Atomic_cmpxchg(PrimitiveConversions::cast<int32_t>(exchange_value),
7610 + reinterpret_cast<int32_t volatile*>(dest),
7611 + PrimitiveConversions::cast<int32_t>(compare_value)));
7614 +template<>
7615 +template<typename T>
7616 +inline T Atomic::PlatformCmpxchg<8>::operator()(T volatile* dest,
7617 + T compare_value,
7618 + T exchange_value,
7619 + atomic_memory_order order) const {
7620 + STATIC_ASSERT(8 == sizeof(T));
7621 + return PrimitiveConversions::cast<T>(
7622 + _Atomic_cmpxchg_long(PrimitiveConversions::cast<int64_t>(exchange_value),
7623 + reinterpret_cast<int64_t volatile*>(dest),
7624 + PrimitiveConversions::cast<int64_t>(compare_value)));
7627 +#endif // OS_CPU_SOLARIS_X86_ATOMIC_SOLARIS_X86_HPP
7628 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/os_cpu/solaris_x86/bytes_solaris_x86.hpp jdk23u-jdk-23-36/src/hotspot/os_cpu/solaris_x86/bytes_solaris_x86.hpp
7629 --- jdk23u-jdk-23-36.orig/src/hotspot/os_cpu/solaris_x86/bytes_solaris_x86.hpp 1970-01-01 01:00:00.000000000 +0100
7630 +++ jdk23u-jdk-23-36/src/hotspot/os_cpu/solaris_x86/bytes_solaris_x86.hpp 2024-08-17 19:50:33.147295557 +0200
7631 @@ -0,0 +1,60 @@
7633 + * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
7634 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7636 + * This code is free software; you can redistribute it and/or modify it
7637 + * under the terms of the GNU General Public License version 2 only, as
7638 + * published by the Free Software Foundation.
7640 + * This code is distributed in the hope that it will be useful, but WITHOUT
7641 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7642 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7643 + * version 2 for more details (a copy is included in the LICENSE file that
7644 + * accompanied this code).
7646 + * You should have received a copy of the GNU General Public License version
7647 + * 2 along with this work; if not, write to the Free Software Foundation,
7648 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7650 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7651 + * or visit www.oracle.com if you need additional information or have any
7652 + * questions.
7654 + */
7656 +#ifndef OS_CPU_SOLARIS_X86_BYTES_SOLARIS_X86_HPP
7657 +#define OS_CPU_SOLARIS_X86_BYTES_SOLARIS_X86_HPP
7659 +extern "C" {
7660 + inline u2 _raw_swap_u2(u2 x) {
7661 + unsigned short int __dest;
7662 + __asm__ ("rorw $8, %w0": "=r" (__dest): "0" (x): "cc");
7663 + return __dest;
7665 + inline u4 _raw_swap_u4(u4 x) {
7666 + unsigned int __dest;
7667 + __asm__ ("bswap %0" : "=r" (__dest) : "0" (x));
7668 + return __dest;
7670 + inline u8 _raw_swap_u8(u8 x) {
7671 + unsigned long __dest;
7672 + __asm__ ("bswap %q0" : "=r" (__dest) : "0" (x));
7673 + return __dest;
7677 +// Efficient swapping of data bytes from Java byte
7678 +// ordering to native byte ordering and vice versa.
7679 +inline u2 Bytes::swap_u2(u2 x) {
7680 + return _raw_swap_u2(x);
7683 +inline u4 Bytes::swap_u4(u4 x) {
7684 + return _raw_swap_u4(x);
7687 +inline u8 Bytes::swap_u8(u8 x) {
7688 + return _raw_swap_u8(x);
7691 +#endif // OS_CPU_SOLARIS_X86_BYTES_SOLARIS_X86_HPP
7692 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/os_cpu/solaris_x86/copy_solaris_x86.hpp jdk23u-jdk-23-36/src/hotspot/os_cpu/solaris_x86/copy_solaris_x86.hpp
7693 --- jdk23u-jdk-23-36.orig/src/hotspot/os_cpu/solaris_x86/copy_solaris_x86.hpp 1970-01-01 01:00:00.000000000 +0100
7694 +++ jdk23u-jdk-23-36/src/hotspot/os_cpu/solaris_x86/copy_solaris_x86.hpp 2024-08-17 19:50:33.147539594 +0200
7695 @@ -0,0 +1,30 @@
7697 + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
7698 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7700 + * This code is free software; you can redistribute it and/or modify it
7701 + * under the terms of the GNU General Public License version 2 only, as
7702 + * published by the Free Software Foundation.
7704 + * This code is distributed in the hope that it will be useful, but WITHOUT
7705 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7706 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7707 + * version 2 for more details (a copy is included in the LICENSE file that
7708 + * accompanied this code).
7710 + * You should have received a copy of the GNU General Public License version
7711 + * 2 along with this work; if not, write to the Free Software Foundation,
7712 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7714 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7715 + * or visit www.oracle.com if you need additional information or have any
7716 + * questions.
7718 + */
7720 +#ifndef OS_CPU_SOLARIS_X86_COPY_SOLARIS_X86_HPP
7721 +#define OS_CPU_SOLARIS_X86_COPY_SOLARIS_X86_HPP
7723 +// now in central copy_x86.hpp
7725 +#endif // OS_CPU_SOLARIS_X86_COPY_SOLARIS_X86_HPP
7726 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/os_cpu/solaris_x86/globals_solaris_x86.hpp jdk23u-jdk-23-36/src/hotspot/os_cpu/solaris_x86/globals_solaris_x86.hpp
7727 --- jdk23u-jdk-23-36.orig/src/hotspot/os_cpu/solaris_x86/globals_solaris_x86.hpp 1970-01-01 01:00:00.000000000 +0100
7728 +++ jdk23u-jdk-23-36/src/hotspot/os_cpu/solaris_x86/globals_solaris_x86.hpp 2024-08-17 19:50:33.147811847 +0200
7729 @@ -0,0 +1,40 @@
7731 + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
7732 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7734 + * This code is free software; you can redistribute it and/or modify it
7735 + * under the terms of the GNU General Public License version 2 only, as
7736 + * published by the Free Software Foundation.
7738 + * This code is distributed in the hope that it will be useful, but WITHOUT
7739 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7740 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7741 + * version 2 for more details (a copy is included in the LICENSE file that
7742 + * accompanied this code).
7744 + * You should have received a copy of the GNU General Public License version
7745 + * 2 along with this work; if not, write to the Free Software Foundation,
7746 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7748 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7749 + * or visit www.oracle.com if you need additional information or have any
7750 + * questions.
7752 + */
7754 +#ifndef OS_CPU_SOLARIS_X86_GLOBALS_SOLARIS_X86_HPP
7755 +#define OS_CPU_SOLARIS_X86_GLOBALS_SOLARIS_X86_HPP
7757 +// Sets the default values for platform dependent flags used by the runtime system.
7758 +// (see globals.hpp)
7760 +define_pd_global(bool, DontYieldALot, true); // Determined in the design center
7761 +define_pd_global(intx, CompilerThreadStackSize, 1024);
7762 +define_pd_global(intx, ThreadStackSize, 1024); // 0 => use system default
7763 +define_pd_global(intx, VMThreadStackSize, 1024);
7764 +define_pd_global(size_t, JVMInvokeMethodSlack, 8*K);
7766 +// Used on 64 bit platforms for UseCompressedOops base address
7767 +define_pd_global(size_t, HeapBaseMinAddress, 2*G);
7769 +#endif // OS_CPU_SOLARIS_X86_GLOBALS_SOLARIS_X86_HPP
7770 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/os_cpu/solaris_x86/javaThread_solaris_x86.cpp jdk23u-jdk-23-36/src/hotspot/os_cpu/solaris_x86/javaThread_solaris_x86.cpp
7771 --- jdk23u-jdk-23-36.orig/src/hotspot/os_cpu/solaris_x86/javaThread_solaris_x86.cpp 1970-01-01 01:00:00.000000000 +0100
7772 +++ jdk23u-jdk-23-36/src/hotspot/os_cpu/solaris_x86/javaThread_solaris_x86.cpp 2024-08-17 19:50:33.150096916 +0200
7773 @@ -0,0 +1,97 @@
7775 + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
7776 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7778 + * This code is free software; you can redistribute it and/or modify it
7779 + * under the terms of the GNU General Public License version 2 only, as
7780 + * published by the Free Software Foundation.
7782 + * This code is distributed in the hope that it will be useful, but WITHOUT
7783 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7784 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7785 + * version 2 for more details (a copy is included in the LICENSE file that
7786 + * accompanied this code).
7788 + * You should have received a copy of the GNU General Public License version
7789 + * 2 along with this work; if not, write to the Free Software Foundation,
7790 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7792 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7793 + * or visit www.oracle.com if you need additional information or have any
7794 + * questions.
7796 + */
7798 +#include "precompiled.hpp"
7799 +#include "runtime/frame.inline.hpp"
7800 +#include "runtime/javaThread.hpp"
7802 +frame JavaThread::pd_last_frame() {
7803 + assert(has_last_Java_frame(), "must have last_Java_sp() when suspended");
7804 + vmassert(_anchor.last_Java_pc() != NULL, "not walkable");
7805 + return frame(_anchor.last_Java_sp(), _anchor.last_Java_fp(), _anchor.last_Java_pc());
7808 +// For Forte Analyzer AsyncGetCallTrace profiling support - thread is
7809 +// currently interrupted by SIGPROF
7810 +bool JavaThread::pd_get_top_frame_for_signal_handler(frame* fr_addr,
7811 + void* ucontext, bool isInJava) {
7812 + assert(Thread::current() == this, "caller must be current thread");
7813 + return pd_get_top_frame(fr_addr, ucontext, isInJava);
7816 +bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr,
7817 + void* ucontext, bool isInJava) {
7818 + return pd_get_top_frame(fr_addr, ucontext, isInJava);
7821 +bool JavaThread::pd_get_top_frame(frame* fr_addr,
7822 + void* ucontext, bool isInJava) {
7823 + assert(this->is_Java_thread(), "must be JavaThread");
7824 + JavaThread* jt = (JavaThread *)this;
7826 + // There is small window where last_Java_frame is not walkable or safe
7827 + if (jt->has_last_Java_frame() && jt->frame_anchor()->walkable()) {
7828 + *fr_addr = jt->pd_last_frame();
7829 + return true;
7832 + ucontext_t* uc = (ucontext_t*) ucontext;
7834 + // We always want to use the initial frame we create from the ucontext as
7835 + // it certainly signals where we currently are. However that frame may not
7836 + // be safe for calling sender. In that case if we have a last_Java_frame
7837 + // then the forte walker will switch to that frame as the virtual sender
7838 + // for the frame we create here which is not sender safe.
7840 + intptr_t* ret_fp;
7841 + intptr_t* ret_sp;
7842 + address addr = os::fetch_frame_from_context(uc, &ret_sp, &ret_fp);
7844 + // Something would really have to be screwed up to get a NULL pc
7846 + if (addr == NULL) {
7847 + // ucontext wasn't useful
7848 + return false;
7851 + // If sp and fp are nonsense just leave them out
7853 + if (!jt->is_in_full_stack((address)ret_sp)) {
7854 + ret_sp = NULL;
7855 + ret_fp = NULL;
7856 + } else {
7857 + // sp is reasonable is fp reasonable?
7858 + if (!jt->is_in_stack_range_incl((address)ret_fp, (address)ret_sp)) {
7859 + ret_fp = NULL;
7863 + frame ret_frame(ret_sp, ret_fp, addr);
7865 + *fr_addr = ret_frame;
7866 + return true;
7870 +void JavaThread::cache_global_variables() { }
7871 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/os_cpu/solaris_x86/javaThread_solaris_x86.hpp jdk23u-jdk-23-36/src/hotspot/os_cpu/solaris_x86/javaThread_solaris_x86.hpp
7872 --- jdk23u-jdk-23-36.orig/src/hotspot/os_cpu/solaris_x86/javaThread_solaris_x86.hpp 1970-01-01 01:00:00.000000000 +0100
7873 +++ jdk23u-jdk-23-36/src/hotspot/os_cpu/solaris_x86/javaThread_solaris_x86.hpp 2024-08-17 19:50:33.150360719 +0200
7874 @@ -0,0 +1,59 @@
7876 + * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
7877 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7879 + * This code is free software; you can redistribute it and/or modify it
7880 + * under the terms of the GNU General Public License version 2 only, as
7881 + * published by the Free Software Foundation.
7883 + * This code is distributed in the hope that it will be useful, but WITHOUT
7884 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7885 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7886 + * version 2 for more details (a copy is included in the LICENSE file that
7887 + * accompanied this code).
7889 + * You should have received a copy of the GNU General Public License version
7890 + * 2 along with this work; if not, write to the Free Software Foundation,
7891 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7893 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7894 + * or visit www.oracle.com if you need additional information or have any
7895 + * questions.
7897 + */
7899 +#ifndef OS_CPU_SOLARIS_X86_JAVATHREAD_SOLARIS_X86_HPP
7900 +#define OS_CPU_SOLARIS_X86_JAVATHREAD_SOLARIS_X86_HPP
7902 + private:
7903 + void pd_initialize() { _anchor.clear(); }
7905 + frame pd_last_frame();
7907 + public:
7909 + void set_base_of_stack_pointer(intptr_t* base_sp) {}
7911 + static ByteSize last_Java_fp_offset() {
7912 + return byte_offset_of(JavaThread, _anchor) + JavaFrameAnchor::last_Java_fp_offset();
7915 + intptr_t* base_of_stack_pointer() { return NULL; }
7916 + void record_base_of_stack_pointer() {}
7918 + bool pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext,
7919 + bool isInJava);
7920 + bool pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext,
7921 + bool isInJava);
7922 +private:
7923 + bool pd_get_top_frame(frame* fr_addr, void* ucontext,
7924 + bool isInJava);
7925 +public:
7927 + // These routines are only used on cpu architectures that
7928 + // have separate register stacks (Itanium).
7929 + static bool register_stack_overflow() { return false; }
7930 + static void enable_register_stack_guard() {}
7931 + static void disable_register_stack_guard() {}
7933 +#endif // OS_CPU_SOLARIS_X86_JAVATHREAD_SOLARIS_X86_HPP
7934 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/os_cpu/solaris_x86/orderAccess_solaris_x86.hpp jdk23u-jdk-23-36/src/hotspot/os_cpu/solaris_x86/orderAccess_solaris_x86.hpp
7935 --- jdk23u-jdk-23-36.orig/src/hotspot/os_cpu/solaris_x86/orderAccess_solaris_x86.hpp 1970-01-01 01:00:00.000000000 +0100
7936 +++ jdk23u-jdk-23-36/src/hotspot/os_cpu/solaris_x86/orderAccess_solaris_x86.hpp 2024-08-17 19:50:33.148128114 +0200
7937 @@ -0,0 +1,58 @@
7939 + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
7940 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7942 + * This code is free software; you can redistribute it and/or modify it
7943 + * under the terms of the GNU General Public License version 2 only, as
7944 + * published by the Free Software Foundation.
7946 + * This code is distributed in the hope that it will be useful, but WITHOUT
7947 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7948 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7949 + * version 2 for more details (a copy is included in the LICENSE file that
7950 + * accompanied this code).
7952 + * You should have received a copy of the GNU General Public License version
7953 + * 2 along with this work; if not, write to the Free Software Foundation,
7954 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7956 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7957 + * or visit www.oracle.com if you need additional information or have any
7958 + * questions.
7960 + */
7962 +#ifndef OS_CPU_SOLARIS_X86_ORDERACCESS_SOLARIS_X86_HPP
7963 +#define OS_CPU_SOLARIS_X86_ORDERACCESS_SOLARIS_X86_HPP
7965 +// Included in orderAccess.hpp header file.
7967 +// Compiler version last used for testing: solaris studio 12u3
7968 +// Please update this information when this file changes
7970 +// Implementation of class OrderAccess.
7972 +// A compiler barrier, forcing the C++ compiler to invalidate all memory assumptions
7973 +inline void compiler_barrier() {
7974 + __asm__ volatile ("" : : : "memory");
7977 +inline void OrderAccess::loadload() { compiler_barrier(); }
7978 +inline void OrderAccess::storestore() { compiler_barrier(); }
7979 +inline void OrderAccess::loadstore() { compiler_barrier(); }
7980 +inline void OrderAccess::storeload() { fence(); }
7982 +inline void OrderAccess::acquire() { compiler_barrier(); }
7983 +inline void OrderAccess::release() { compiler_barrier(); }
7985 +inline void OrderAccess::fence() {
7986 + __asm__ volatile ("lock; addl $0,0(%%rsp)" : : : "cc", "memory");
7987 + compiler_barrier();
7990 +inline void OrderAccess::cross_modify_fence_impl() {
7991 + int idx = 0;
7992 + __asm__ volatile ("cpuid " : "+a" (idx) : : "ebx", "ecx", "edx", "memory");
7995 +#endif // OS_CPU_SOLARIS_X86_ORDERACCESS_SOLARIS_X86_HPP
7996 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.cpp jdk23u-jdk-23-36/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.cpp
7997 --- jdk23u-jdk-23-36.orig/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.cpp 1970-01-01 01:00:00.000000000 +0100
7998 +++ jdk23u-jdk-23-36/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.cpp 2024-08-17 19:50:33.148671291 +0200
7999 @@ -0,0 +1,660 @@
8001 + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.
8002 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8004 + * This code is free software; you can redistribute it and/or modify it
8005 + * under the terms of the GNU General Public License version 2 only, as
8006 + * published by the Free Software Foundation.
8008 + * This code is distributed in the hope that it will be useful, but WITHOUT
8009 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8010 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
8011 + * version 2 for more details (a copy is included in the LICENSE file that
8012 + * accompanied this code).
8014 + * You should have received a copy of the GNU General Public License version
8015 + * 2 along with this work; if not, write to the Free Software Foundation,
8016 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
8018 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
8019 + * or visit www.oracle.com if you need additional information or have any
8020 + * questions.
8022 + */
8024 +// no precompiled headers
8025 +#include "jvm.h"
8026 +#include "asm/macroAssembler.hpp"
8027 +#include "classfile/classLoader.hpp"
8028 +#include "classfile/systemDictionary.hpp"
8029 +#include "classfile/vmSymbols.hpp"
8030 +#include "code/codeCache.hpp"
8031 +#include "code/vtableStubs.hpp"
8032 +#include "interpreter/interpreter.hpp"
8033 +#include "logging/log.hpp"
8034 +#include "memory/allocation.inline.hpp"
8035 +#include "os_solaris.hpp"
8036 +#include "os_posix.hpp"
8037 +#include "prims/jniFastGetField.hpp"
8038 +#include "prims/jvm_misc.hpp"
8039 +#include "runtime/arguments.hpp"
8040 +#include "runtime/frame.inline.hpp"
8041 +#include "runtime/interfaceSupport.inline.hpp"
8042 +#include "runtime/java.hpp"
8043 +#include "runtime/javaCalls.hpp"
8044 +#include "runtime/mutexLocker.hpp"
8045 +#include "runtime/osThread.hpp"
8046 +#include "runtime/safepointMechanism.hpp"
8047 +#include "runtime/sharedRuntime.hpp"
8048 +#include "runtime/stubRoutines.hpp"
8049 +#include "runtime/thread.inline.hpp"
8050 +#include "runtime/timer.hpp"
8051 +#include "signals_posix.hpp"
8052 +#include "utilities/align.hpp"
8053 +#include "utilities/events.hpp"
8054 +#include "utilities/vmError.hpp"
8056 +// put OS-includes here
8057 +# include <sys/types.h>
8058 +# include <sys/mman.h>
8059 +# include <pthread.h>
8060 +# include <signal.h>
8061 +# include <setjmp.h>
8062 +# include <errno.h>
8063 +# include <dlfcn.h>
8064 +# include <stdio.h>
8065 +# include <unistd.h>
8066 +# include <sys/resource.h>
8067 +# include <thread.h>
8068 +# include <sys/stat.h>
8069 +# include <sys/time.h>
8070 +# include <sys/filio.h>
8071 +# include <sys/utsname.h>
8072 +# include <sys/systeminfo.h>
8073 +# include <sys/socket.h>
8074 +# include <sys/trap.h>
8075 +# include <sys/lwp.h>
8076 +# include <poll.h>
8077 +# include <sys/lwp.h>
8078 +# include <procfs.h>
8081 +#define MAX_PATH (2 * K)
8083 +// Minimum usable stack sizes required to get to user code. Space for
8084 +// HotSpot guard pages is added later.
8085 +#ifdef _LP64
8086 +// The adlc generated method 'State::MachNodeGenerator(int)' used by the C2 compiler
8087 +// threads requires a large stack with the Solaris Studio C++ compiler version 5.13
8088 +// and product VM builds (debug builds require significantly less stack space).
8089 +size_t os::_compiler_thread_min_stack_allowed = 325 * K;
8090 +size_t os::_java_thread_min_stack_allowed = 48 * K;
8091 +size_t os::_vm_internal_thread_min_stack_allowed = 224 * K;
8092 +#else
8093 +size_t os::_compiler_thread_min_stack_allowed = 32 * K;
8094 +size_t os::_java_thread_min_stack_allowed = 32 * K;
8095 +size_t os::_vm_internal_thread_min_stack_allowed = 64 * K;
8096 +#endif // _LP64
8098 +#ifdef AMD64
8099 +#define REG_SP REG_RSP
8100 +#define REG_PC REG_RIP
8101 +#define REG_FP REG_RBP
8102 +#else
8103 +#define REG_SP UESP
8104 +#define REG_PC EIP
8105 +#define REG_FP EBP
8106 +// 4900493 counter to prevent runaway LDTR refresh attempt
8108 +static volatile int ldtr_refresh = 0;
8109 +// the libthread instruction that faults because of the stale LDTR
8111 +static const unsigned char movlfs[] = { 0x8e, 0xe0 // movl %eax,%fs
8112 + };
8113 +#endif // AMD64
8115 +char* os::non_memory_address_word() {
8116 + // Must never look like an address returned by reserve_memory,
8117 + // even in its subfields (as defined by the CPU immediate fields,
8118 + // if the CPU splits constants across multiple instructions).
8119 + return (char*) -1;
8123 +// Validate a ucontext retrieved from walking a uc_link of a ucontext.
8124 +// There are issues with libthread giving out uc_links for different threads
8125 +// on the same uc_link chain and bad or circular links.
8127 +bool os::Solaris::valid_ucontext(Thread* thread, const ucontext_t* valid, const ucontext_t* suspect) {
8128 + if (valid >= suspect ||
8129 + valid->uc_stack.ss_flags != suspect->uc_stack.ss_flags ||
8130 + valid->uc_stack.ss_sp != suspect->uc_stack.ss_sp ||
8131 + valid->uc_stack.ss_size != suspect->uc_stack.ss_size) {
8132 + DEBUG_ONLY(tty->print_cr("valid_ucontext: failed test 1");)
8133 + return false;
8136 + if (thread->is_Java_thread()) {
8137 + if (!thread->is_in_full_stack_checked((address)suspect)) {
8138 + DEBUG_ONLY(tty->print_cr("valid_ucontext: uc_link not in thread stack");)
8139 + return false;
8141 + if (!thread->is_in_full_stack_checked((address) suspect->uc_mcontext.gregs[REG_SP])) {
8142 + DEBUG_ONLY(tty->print_cr("valid_ucontext: stackpointer not in thread stack");)
8143 + return false;
8146 + return true;
8149 +// We will only follow one level of uc_link since there are libthread
8150 +// issues with ucontext linking and it is better to be safe and just
8151 +// let caller retry later.
8152 +const ucontext_t* os::Solaris::get_valid_uc_in_signal_handler(Thread *thread,
8153 + const ucontext_t *uc) {
8155 + const ucontext_t *retuc = NULL;
8157 + if (uc != NULL) {
8158 + if (uc->uc_link == NULL) {
8159 + // cannot validate without uc_link so accept current ucontext
8160 + retuc = uc;
8161 + } else if (os::Solaris::valid_ucontext(thread, uc, uc->uc_link)) {
8162 + // first ucontext is valid so try the next one
8163 + uc = uc->uc_link;
8164 + if (uc->uc_link == NULL) {
8165 + // cannot validate without uc_link so accept current ucontext
8166 + retuc = uc;
8167 + } else if (os::Solaris::valid_ucontext(thread, uc, uc->uc_link)) {
8168 + // the ucontext one level down is also valid so return it
8169 + retuc = uc;
8173 + return retuc;
8176 +void os::Posix::ucontext_set_pc(ucontext_t* uc, address pc) {
8177 + uc->uc_mcontext.gregs [REG_PC] = (greg_t) pc;
8180 +// Assumes ucontext is valid
8181 +intptr_t* os::Solaris::ucontext_get_sp(const ucontext_t *uc) {
8182 + return (intptr_t*)uc->uc_mcontext.gregs[REG_SP];
8185 +// Assumes ucontext is valid
8186 +intptr_t* os::Solaris::ucontext_get_fp(const ucontext_t *uc) {
8187 + return (intptr_t*)uc->uc_mcontext.gregs[REG_FP];
8190 +address os::Posix::ucontext_get_pc(const ucontext_t *uc) {
8191 + return (address) uc->uc_mcontext.gregs[REG_PC];
8194 +address os::fetch_frame_from_context(const void* ucVoid,
8195 + intptr_t** ret_sp, intptr_t** ret_fp) {
8197 + address epc;
8198 + const ucontext_t *uc = (const ucontext_t*)ucVoid;
8200 + if (uc != NULL) {
8201 + epc = os::Posix::ucontext_get_pc(uc);
8202 + if (ret_sp) *ret_sp = os::Solaris::ucontext_get_sp(uc);
8203 + if (ret_fp) *ret_fp = os::Solaris::ucontext_get_fp(uc);
8204 + } else {
8205 + epc = NULL;
8206 + if (ret_sp) *ret_sp = (intptr_t *)NULL;
8207 + if (ret_fp) *ret_fp = (intptr_t *)NULL;
8210 + return epc;
8213 +frame os::fetch_frame_from_context(const void* ucVoid) {
8214 + intptr_t* sp;
8215 + intptr_t* fp;
8216 + address epc = fetch_frame_from_context(ucVoid, &sp, &fp);
8217 + return frame(sp, fp, epc);
8220 +bool os::Solaris::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr) {
8221 + address pc = (address) os::Solaris::ucontext_get_pc(uc);
8222 + if (Interpreter::contains(pc)) {
8223 + // interpreter performs stack banging after the fixed frame header has
8224 + // been generated while the compilers perform it before. To maintain
8225 + // semantic consistency between interpreted and compiled frames, the
8226 + // method returns the Java sender of the current frame.
8227 + *fr = os::fetch_frame_from_context(uc);
8228 + if (!fr->is_first_java_frame()) {
8229 + // get_frame_at_stack_banging_point() is only called when we
8230 + // have well defined stacks so java_sender() calls do not need
8231 + // to assert safe_for_sender() first.
8232 + *fr = fr->java_sender();
8234 + } else {
8235 + // more complex code with compiled code
8236 + assert(!Interpreter::contains(pc), "Interpreted methods should have been handled above");
8237 + CodeBlob* cb = CodeCache::find_blob(pc);
8238 + if (cb == NULL || !cb->is_nmethod() || cb->is_frame_complete_at(pc)) {
8239 + // Not sure where the pc points to, fallback to default
8240 + // stack overflow handling
8241 + return false;
8242 + } else {
8243 + // in compiled code, the stack banging is performed just after the return pc
8244 + // has been pushed on the stack
8245 + intptr_t* fp = os::Solaris::ucontext_get_fp(uc);
8246 + intptr_t* sp = os::Solaris::ucontext_get_sp(uc);
8247 + *fr = frame(sp + 1, fp, (address)*sp);
8248 + if (!fr->is_java_frame()) {
8249 + // See java_sender() comment above.
8250 + *fr = fr->java_sender();
8254 + assert(fr->is_java_frame(), "Safety check");
8255 + return true;
8258 +frame os::get_sender_for_C_frame(frame* fr) {
8259 + return frame(fr->sender_sp(), fr->link(), fr->sender_pc());
8262 +extern "C" intptr_t *_get_current_sp() {
8263 + register intptr_t *rsp __asm__ ("rsp");
8264 + return rsp;
8267 +address os::current_stack_pointer() {
8268 + return (address)_get_current_sp();
8271 +extern "C" intptr_t *_get_current_fp() {
8272 + register intptr_t **rbp __asm__ ("rbp");
8273 + return (intptr_t*) *rbp;
8276 +frame os::current_frame() {
8277 + intptr_t* fp = _get_current_fp(); // it's inlined so want current fp
8278 + // fp is for os::current_frame. We want the fp for our caller.
8279 + frame myframe((intptr_t*)os::current_stack_pointer(),
8280 + (intptr_t*)fp,
8281 + CAST_FROM_FN_PTR(address, os::current_frame));
8282 + frame caller_frame = os::get_sender_for_C_frame(&myframe);
8284 + if (os::is_first_C_frame(&caller_frame)) {
8285 + // stack is not walkable
8286 + frame ret; // This will be a null useless frame
8287 + return ret;
8288 + } else {
8289 + // return frame for our caller's caller
8290 + return os::get_sender_for_C_frame(&caller_frame);
8295 +bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info,
8296 + ucontext_t* uc, JavaThread* thread) {
8298 + if (info == NULL || info->si_code <= 0 || info->si_code == SI_NOINFO) {
8299 + // can't decode this kind of signal
8300 + info = NULL;
8301 + } else {
8302 + assert(sig == info->si_signo, "bad siginfo");
8305 + // decide if this trap can be handled by a stub
8306 + address stub = NULL;
8308 + address pc = NULL;
8310 + //%note os_trap_1
8311 + if (info != NULL && uc != NULL && thread != NULL) {
8312 + // factor me: getPCfromContext
8313 + pc = (address) uc->uc_mcontext.gregs[REG_PC];
8315 + // Handle ALL stack overflow variations here
8316 + if (sig == SIGSEGV && info->si_code == SEGV_ACCERR) {
8317 + address addr = (address) info->si_addr;
8318 + if (thread->in_stack_yellow_reserved_zone(addr)) {
8319 + if (thread->thread_state() == _thread_in_Java) {
8320 + if (thread->in_stack_reserved_zone(addr)) {
8321 + frame fr;
8322 + if (os::Solaris::get_frame_at_stack_banging_point(thread, uc, &fr)) {
8323 + assert(fr.is_java_frame(), "Must be Java frame");
8324 + frame activation = SharedRuntime::look_for_reserved_stack_annotated_method(thread, fr);
8325 + if (activation.sp() != NULL) {
8326 + thread->disable_stack_reserved_zone();
8327 + if (activation.is_interpreted_frame()) {
8328 + thread->set_reserved_stack_activation((address)(
8329 + activation.fp() + frame::interpreter_frame_initial_sp_offset));
8330 + } else {
8331 + thread->set_reserved_stack_activation((address)activation.unextended_sp());
8333 + return true;
8337 + // Throw a stack overflow exception. Guard pages will be reenabled
8338 + // while unwinding the stack.
8339 + thread->disable_stack_yellow_reserved_zone();
8340 + stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW);
8341 + } else {
8342 + // Thread was in the vm or native code. Return and try to finish.
8343 + thread->disable_stack_yellow_reserved_zone();
8344 + return true;
8346 + } else if (thread->in_stack_red_zone(addr)) {
8347 + // Fatal red zone violation. Disable the guard pages and fall through
8348 + // to handle_unexpected_exception way down below.
8349 + thread->disable_stack_red_zone();
8350 + tty->print_raw_cr("An irrecoverable stack overflow has occurred.");
8354 + if ((sig == SIGSEGV) && VM_Version::is_cpuinfo_segv_addr(pc)) {
8355 + // Verify that OS save/restore AVX registers.
8356 + stub = VM_Version::cpuinfo_cont_addr();
8359 + if (thread->thread_state() == _thread_in_vm ||
8360 + thread->thread_state() == _thread_in_native) {
8361 + if (sig == SIGBUS && info->si_code == BUS_OBJERR && thread->doing_unsafe_access()) {
8362 + address next_pc = Assembler::locate_next_instruction(pc);
8363 + if (UnsafeMemoryAccess::contains_pc(pc)) {
8364 + next_pc = UnsafeMemoryAccess::page_error_continue_pc(pc);
8366 + stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
8370 + if (thread->thread_state() == _thread_in_Java) {
8371 + // Support Safepoint Polling
8372 + if ( sig == SIGSEGV && SafepointMechanism::is_poll_address((address)info->si_addr)) {
8373 + stub = SharedRuntime::get_poll_stub(pc);
8375 + else if (sig == SIGBUS && info->si_code == BUS_OBJERR) {
8376 + // BugId 4454115: A read from a MappedByteBuffer can fault
8377 + // here if the underlying file has been truncated.
8378 + // Do not crash the VM in such a case.
8379 + CodeBlob* cb = CodeCache::find_blob(pc);
8380 + if (cb != NULL) {
8381 + nmethod* nm = cb->as_nmethod_or_null();
8382 + bool is_unsafe_memory_access = thread->doing_unsafe_access() && UnsafeMemoryAccess::contains_pc(pc);
8383 + if ((nm != NULL && nm->has_unsafe_access()) || is_unsafe_memory_access) {
8384 + address next_pc = Assembler::locate_next_instruction(pc);
8385 + if (is_unsafe_memory_access) {
8386 + next_pc = UnsafeMemoryAccess::page_error_continue_pc(pc);
8388 + stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
8391 + } else
8392 + if (sig == SIGFPE && info->si_code == FPE_INTDIV) {
8393 + // integer divide by zero
8394 + stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_DIVIDE_BY_ZERO);
8396 +#ifndef AMD64
8397 + else if (sig == SIGFPE && info->si_code == FPE_FLTDIV) {
8398 + // floating-point divide by zero
8399 + stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_DIVIDE_BY_ZERO);
8401 + else if (sig == SIGFPE && info->si_code == FPE_FLTINV) {
8402 + // The encoding of D2I in i486.ad can cause an exception prior
8403 + // to the fist instruction if there was an invalid operation
8404 + // pending. We want to dismiss that exception. From the win_32
8405 + // side it also seems that if it really was the fist causing
8406 + // the exception that we do the d2i by hand with different
8407 + // rounding. Seems kind of weird. QQQ TODO
8408 + // Note that we take the exception at the NEXT floating point instruction.
8409 + if (pc[0] == 0xDB) {
8410 + assert(pc[0] == 0xDB, "not a FIST opcode");
8411 + assert(pc[1] == 0x14, "not a FIST opcode");
8412 + assert(pc[2] == 0x24, "not a FIST opcode");
8413 + return true;
8414 + } else {
8415 + assert(pc[-3] == 0xDB, "not an flt invalid opcode");
8416 + assert(pc[-2] == 0x14, "not an flt invalid opcode");
8417 + assert(pc[-1] == 0x24, "not an flt invalid opcode");
8420 + else if (sig == SIGFPE ) {
8421 + tty->print_cr("caught SIGFPE, info 0x%x.", info->si_code);
8423 +#endif // !AMD64
8425 + // QQQ It doesn't seem that we need to do this on x86 because we should be able
8426 + // to return properly from the handler without this extra stuff on the back side.
8428 + else if (sig == SIGSEGV && info->si_code > 0 &&
8429 + MacroAssembler::uses_implicit_null_check(info->si_addr)) {
8430 + // Determination of interpreter/vtable stub/compiled code null exception
8431 + stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL);
8435 + // jni_fast_Get<Primitive>Field can trap at certain pc's if a GC kicks in
8436 + // and the heap gets shrunk before the field access.
8437 + if ((sig == SIGSEGV) || (sig == SIGBUS)) {
8438 + address addr = JNI_FastGetField::find_slowcase_pc(pc);
8439 + if (addr != (address)-1) {
8440 + stub = addr;
8445 + // Execution protection violation
8446 + //
8447 + // Preventative code for future versions of Solaris which may
8448 + // enable execution protection when running the 32-bit VM on AMD64.
8449 + //
8450 + // This should be kept as the last step in the triage. We don't
8451 + // have a dedicated trap number for a no-execute fault, so be
8452 + // conservative and allow other handlers the first shot.
8453 + //
8454 + // Note: We don't test that info->si_code == SEGV_ACCERR here.
8455 + // this si_code is so generic that it is almost meaningless; and
8456 + // the si_code for this condition may change in the future.
8457 + // Furthermore, a false-positive should be harmless.
8458 + if (UnguardOnExecutionViolation > 0 &&
8459 + (sig == SIGSEGV || sig == SIGBUS) &&
8460 + uc->uc_mcontext.gregs[TRAPNO] == T_PGFLT) { // page fault
8461 + int page_size = os::vm_page_size();
8462 + address addr = (address) info->si_addr;
8463 + address pc = (address) uc->uc_mcontext.gregs[REG_PC];
8464 + // Make sure the pc and the faulting address are sane.
8465 + //
8466 + // If an instruction spans a page boundary, and the page containing
8467 + // the beginning of the instruction is executable but the following
8468 + // page is not, the pc and the faulting address might be slightly
8469 + // different - we still want to unguard the 2nd page in this case.
8470 + //
8471 + // 15 bytes seems to be a (very) safe value for max instruction size.
8472 + bool pc_is_near_addr =
8473 + (pointer_delta((void*) addr, (void*) pc, sizeof(char)) < 15);
8474 + bool instr_spans_page_boundary =
8475 + (align_down((intptr_t) pc ^ (intptr_t) addr,
8476 + (intptr_t) page_size) > 0);
8478 + if (pc == addr || (pc_is_near_addr && instr_spans_page_boundary)) {
8479 + static volatile address last_addr =
8480 + (address) os::non_memory_address_word();
8482 + // In conservative mode, don't unguard unless the address is in the VM
8483 + if (addr != last_addr &&
8484 + (UnguardOnExecutionViolation > 1 || os::address_is_in_vm(addr))) {
8486 + // Make memory rwx and retry
8487 + address page_start = align_down(addr, page_size);
8488 + bool res = os::protect_memory((char*) page_start, page_size,
8489 + os::MEM_PROT_RWX);
8491 + log_debug(os)("Execution protection violation "
8492 + "at " INTPTR_FORMAT
8493 + ", unguarding " INTPTR_FORMAT ": %s, errno=%d", p2i(addr),
8494 + p2i(page_start), (res ? "success" : "failed"), errno);
8495 + stub = pc;
8497 + // Set last_addr so if we fault again at the same address, we don't end
8498 + // up in an endless loop.
8499 + //
8500 + // There are two potential complications here. Two threads trapping at
8501 + // the same address at the same time could cause one of the threads to
8502 + // think it already unguarded, and abort the VM. Likely very rare.
8503 + //
8504 + // The other race involves two threads alternately trapping at
8505 + // different addresses and failing to unguard the page, resulting in
8506 + // an endless loop. This condition is probably even more unlikely than
8507 + // the first.
8508 + //
8509 + // Although both cases could be avoided by using locks or thread local
8510 + // last_addr, these solutions are unnecessary complication: this
8511 + // handler is a best-effort safety net, not a complete solution. It is
8512 + // disabled by default and should only be used as a workaround in case
8513 + // we missed any no-execute-unsafe VM code.
8515 + last_addr = addr;
8520 + if (stub != NULL) {
8521 + // save all thread context in case we need to restore it
8523 + if (thread != NULL) thread->set_saved_exception_pc(pc);
8524 + // 12/02/99: On Sparc it appears that the full context is also saved
8525 + // but as yet, no one looks at or restores that saved context
8526 + os::Posix::ucontext_set_pc(uc, stub);
8527 + return true;
8530 + return false;
8533 +void os::print_context(outputStream *st, const void *context) {
8534 + if (context == NULL) return;
8536 + const ucontext_t *uc = (const ucontext_t*)context;
8537 + st->print_cr("Registers:");
8538 +#ifdef AMD64
8539 + st->print( "RAX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RAX]);
8540 + st->print(", RBX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RBX]);
8541 + st->print(", RCX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RCX]);
8542 + st->print(", RDX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RDX]);
8543 + st->cr();
8544 + st->print( "RSP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RSP]);
8545 + st->print(", RBP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RBP]);
8546 + st->print(", RSI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RSI]);
8547 + st->print(", RDI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RDI]);
8548 + st->cr();
8549 + st->print( "R8 =" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R8]);
8550 + st->print(", R9 =" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R9]);
8551 + st->print(", R10=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R10]);
8552 + st->print(", R11=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R11]);
8553 + st->cr();
8554 + st->print( "R12=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R12]);
8555 + st->print(", R13=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R13]);
8556 + st->print(", R14=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R14]);
8557 + st->print(", R15=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R15]);
8558 + st->cr();
8559 + st->print( "RIP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RIP]);
8560 + st->print(", RFLAGS=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RFL]);
8561 +#else
8562 + st->print( "EAX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EAX]);
8563 + st->print(", EBX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EBX]);
8564 + st->print(", ECX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[ECX]);
8565 + st->print(", EDX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EDX]);
8566 + st->cr();
8567 + st->print( "ESP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[UESP]);
8568 + st->print(", EBP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EBP]);
8569 + st->print(", ESI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[ESI]);
8570 + st->print(", EDI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EDI]);
8571 + st->cr();
8572 + st->print( "EIP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EIP]);
8573 + st->print(", EFLAGS=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EFL]);
8574 +#endif // AMD64
8575 + st->cr();
8576 + st->cr();
8579 +void os::print_tos_pc(outputStream *st, const void *context) {
8580 + if (context == NULL) return;
8582 + const ucontext_t* uc = (const ucontext_t*)context;
8584 + intptr_t *sp = (intptr_t *)os::Solaris::ucontext_get_sp(uc);
8585 + st->print_cr("Top of Stack: (sp=" INTPTR_FORMAT ")", (intptr_t)sp);
8586 + print_hex_dump(st, (address)sp, (address)(sp + 8*sizeof(intptr_t)), sizeof(intptr_t));
8587 + st->cr();
8589 + // Note: it may be unsafe to inspect memory near pc. For example, pc may
8590 + // point to garbage if entry point in an nmethod is corrupted. Leave
8591 + // this at the end, and hope for the best.
8592 + address pc = os::Posix::ucontext_get_pc(uc);
8593 + print_instructions(st, pc, sizeof(char));
8594 + st->cr();
8597 +void os::print_register_info(outputStream *st, const void *context, int& continuation) {
8598 + const int register_count = AMD64_ONLY(16) NOT_AMD64(8);
8599 + int n = continuation;
8600 + assert(n >= 0 && n <= register_count, "Invalid continuation value");
8601 + if (context == nullptr || n == register_count) {
8602 + return;
8605 + const ucontext_t *uc = (const ucontext_t*)context;
8606 + while (n < register_count) {
8607 + // Update continuation with next index before printing location
8608 + continuation = n + 1;
8609 +# define CASE_PRINT_REG(n, str, id) case n: st->print(str); print_location(st, uc->uc_mcontext.gregs[REG_##id]);
8610 + switch (n) {
8611 +#ifdef AMD64
8612 + CASE_PRINT_REG( 0, "RAX=", RAX); break;
8613 + CASE_PRINT_REG( 1, "RBX=", RBX); break;
8614 + CASE_PRINT_REG( 2, "RCX=", RCX); break;
8615 + CASE_PRINT_REG( 3, "RDX=", RDX); break;
8616 + CASE_PRINT_REG( 4, "RSP=", RSP); break;
8617 + CASE_PRINT_REG( 5, "RBP=", RBP); break;
8618 + CASE_PRINT_REG( 6, "RSI=", RSI); break;
8619 + CASE_PRINT_REG( 7, "RDI=", RDI); break;
8620 + CASE_PRINT_REG( 8, "R8 =", R8); break;
8621 + CASE_PRINT_REG( 9, "R9 =", R9); break;
8622 + CASE_PRINT_REG(10, "R10=", R10); break;
8623 + CASE_PRINT_REG(11, "R11=", R11); break;
8624 + CASE_PRINT_REG(12, "R12=", R12); break;
8625 + CASE_PRINT_REG(13, "R13=", R13); break;
8626 + CASE_PRINT_REG(14, "R14=", R14); break;
8627 + CASE_PRINT_REG(15, "R15=", R15); break;
8628 +#else
8629 + CASE_PRINT_REG(0, "EAX=", EAX); break;
8630 + CASE_PRINT_REG(1, "EBX=", EBX); break;
8631 + CASE_PRINT_REG(2, "ECX=", ECX); break;
8632 + CASE_PRINT_REG(3, "EDX=", EDX); break;
8633 + CASE_PRINT_REG(4, "ESP=", ESP); break;
8634 + CASE_PRINT_REG(5, "EBP=", EBP); break;
8635 + CASE_PRINT_REG(6, "ESI=", ESI); break;
8636 + CASE_PRINT_REG(7, "EDI=", EDI); break;
8637 +#endif // AMD64
8639 +# undef CASE_PRINT_REG
8640 + ++n;
8645 +void os::Solaris::init_thread_fpu_state(void) {
8646 + // Nothing to do
8648 +void os::setup_fpu() {}
8650 +#ifndef PRODUCT
8651 +void os::verify_stack_alignment() {
8652 + assert(((intptr_t)os::current_stack_pointer() & (StackAlignmentInBytes-1)) == 0, "incorrect stack alignment");
8654 +#endif
8656 +int os::extra_bang_size_in_bytes() {
8657 + // JDK-8050147 requires the full cache line bang for x86.
8658 + return VM_Version::L1_line_size();
8660 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.hpp jdk23u-jdk-23-36/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.hpp
8661 --- jdk23u-jdk-23-36.orig/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.hpp 1970-01-01 01:00:00.000000000 +0100
8662 +++ jdk23u-jdk-23-36/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.hpp 2024-08-17 19:50:33.148934839 +0200
8663 @@ -0,0 +1,55 @@
8665 + * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
8666 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8668 + * This code is free software; you can redistribute it and/or modify it
8669 + * under the terms of the GNU General Public License version 2 only, as
8670 + * published by the Free Software Foundation.
8672 + * This code is distributed in the hope that it will be useful, but WITHOUT
8673 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8674 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
8675 + * version 2 for more details (a copy is included in the LICENSE file that
8676 + * accompanied this code).
8678 + * You should have received a copy of the GNU General Public License version
8679 + * 2 along with this work; if not, write to the Free Software Foundation,
8680 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
8682 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
8683 + * or visit www.oracle.com if you need additional information or have any
8684 + * questions.
8686 + */
8688 +#ifndef OS_CPU_SOLARIS_X86_OS_SOLARIS_X86_HPP
8689 +#define OS_CPU_SOLARIS_X86_OS_SOLARIS_X86_HPP
8691 + //
8692 + // NOTE: we are back in class os here, not Solaris
8693 + //
8694 +#ifdef AMD64
8695 + static void setup_fpu() {}
8696 +#else
8697 + static int32_t (*atomic_xchg_func) (int32_t, volatile int32_t*);
8698 + static int32_t (*atomic_cmpxchg_func) (int32_t, volatile int32_t*, int32_t);
8699 + static int64_t (*atomic_cmpxchg_long_func)(int64_t, volatile int64_t*, int64_t);
8700 + static int32_t (*atomic_add_func) (int32_t, volatile int32_t*);
8702 + static int32_t atomic_xchg_bootstrap (int32_t, volatile int32_t*);
8703 + static int32_t atomic_cmpxchg_bootstrap (int32_t, volatile int32_t*, int32_t);
8704 + static int64_t atomic_cmpxchg_long_bootstrap(int64_t, volatile int64_t*, int64_t);
8705 + static int32_t atomic_add_bootstrap (int32_t, volatile int32_t*);
8707 + static void setup_fpu();
8708 +#endif // AMD64
8710 + static jlong rdtsc();
8712 + static bool is_allocatable(size_t bytes);
8714 + // Used to register dynamic code cache area with the OS
8715 + // Note: Currently only used in 64 bit Windows implementations
8716 + static bool register_code_area(char *low, char *high) { return true; }
8718 +#endif // OS_CPU_SOLARIS_X86_OS_SOLARIS_X86_HPP
8719 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.inline.hpp jdk23u-jdk-23-36/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.inline.hpp
8720 --- jdk23u-jdk-23-36.orig/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.inline.hpp 1970-01-01 01:00:00.000000000 +0100
8721 +++ jdk23u-jdk-23-36/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.inline.hpp 2024-08-17 19:50:33.149169582 +0200
8722 @@ -0,0 +1,39 @@
8724 + * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
8725 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8727 + * This code is free software; you can redistribute it and/or modify it
8728 + * under the terms of the GNU General Public License version 2 only, as
8729 + * published by the Free Software Foundation.
8731 + * This code is distributed in the hope that it will be useful, but WITHOUT
8732 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8733 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
8734 + * version 2 for more details (a copy is included in the LICENSE file that
8735 + * accompanied this code).
8737 + * You should have received a copy of the GNU General Public License version
8738 + * 2 along with this work; if not, write to the Free Software Foundation,
8739 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
8741 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
8742 + * or visit www.oracle.com if you need additional information or have any
8743 + * questions.
8745 + */
8747 +#ifndef OS_CPU_SOLARIS_X86_OS_SOLARIS_X86_INLINE_HPP
8748 +#define OS_CPU_SOLARIS_X86_OS_SOLARIS_X86_INLINE_HPP
8750 +#include "runtime/os.hpp"
8752 +// See http://www.technovelty.org/code/c/reading-rdtsc.htl for details
8753 +inline jlong os::rdtsc() {
8754 + uint64_t res;
8755 + uint32_t ts1, ts2;
8756 + __asm__ __volatile__ ("rdtsc" : "=a" (ts1), "=d" (ts2));
8757 + res = ((uint64_t)ts1 | (uint64_t)ts2 << 32);
8758 + return (jlong)res;
8761 +#endif // OS_CPU_SOLARIS_X86_OS_SOLARIS_X86_INLINE_HPP
8762 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/os_cpu/solaris_x86/prefetch_solaris_x86.inline.hpp jdk23u-jdk-23-36/src/hotspot/os_cpu/solaris_x86/prefetch_solaris_x86.inline.hpp
8763 --- jdk23u-jdk-23-36.orig/src/hotspot/os_cpu/solaris_x86/prefetch_solaris_x86.inline.hpp 1970-01-01 01:00:00.000000000 +0100
8764 +++ jdk23u-jdk-23-36/src/hotspot/os_cpu/solaris_x86/prefetch_solaris_x86.inline.hpp 2024-08-17 19:50:33.149438204 +0200
8765 @@ -0,0 +1,42 @@
8767 + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
8768 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8770 + * This code is free software; you can redistribute it and/or modify it
8771 + * under the terms of the GNU General Public License version 2 only, as
8772 + * published by the Free Software Foundation.
8774 + * This code is distributed in the hope that it will be useful, but WITHOUT
8775 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8776 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
8777 + * version 2 for more details (a copy is included in the LICENSE file that
8778 + * accompanied this code).
8780 + * You should have received a copy of the GNU General Public License version
8781 + * 2 along with this work; if not, write to the Free Software Foundation,
8782 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
8784 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
8785 + * or visit www.oracle.com if you need additional information or have any
8786 + * questions.
8788 + */
8790 +#ifndef OS_CPU_SOLARIS_X86_PREFETCH_SOLARIS_X86_INLINE_HPP
8791 +#define OS_CPU_SOLARIS_X86_PREFETCH_SOLARIS_X86_INLINE_HPP
8793 +#include "runtime/prefetch.hpp"
8795 +inline void Prefetch::read (const void *loc, intx interval) {
8796 +#ifdef AMD64
8797 + __asm__ ("prefetcht0 (%0,%1,1)" : : "r" (loc), "r" (interval));
8798 +#endif // AMD64
8801 +inline void Prefetch::write(void *loc, intx interval) {
8802 +#ifdef AMD64
8803 + __asm__ ("prefetcht0 (%0,%1,1)" : : "r" (loc), "r" (interval));
8804 +#endif // AMD64
8807 +#endif // OS_CPU_SOLARIS_X86_PREFETCH_SOLARIS_X86_INLINE_HPP
8808 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/os_cpu/solaris_x86/solaris_x86_64.S jdk23u-jdk-23-36/src/hotspot/os_cpu/solaris_x86/solaris_x86_64.S
8809 --- jdk23u-jdk-23-36.orig/src/hotspot/os_cpu/solaris_x86/solaris_x86_64.S 1970-01-01 01:00:00.000000000 +0100
8810 +++ jdk23u-jdk-23-36/src/hotspot/os_cpu/solaris_x86/solaris_x86_64.S 2024-08-17 19:50:33.149834166 +0200
8811 @@ -0,0 +1,386 @@
8813 +# Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
8814 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8816 +# This code is free software; you can redistribute it and/or modify it
8817 +# under the terms of the GNU General Public License version 2 only, as
8818 +# published by the Free Software Foundation.
8820 +# This code is distributed in the hope that it will be useful, but WITHOUT
8821 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8822 +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
8823 +# version 2 for more details (a copy is included in the LICENSE file that
8824 +# accompanied this code).
8826 +# You should have received a copy of the GNU General Public License version
8827 +# 2 along with this work; if not, write to the Free Software Foundation,
8828 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
8830 +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
8831 +# or visit www.oracle.com if you need additional information or have any
8832 +# questions.
8835 + .globl fs_load
8836 + .globl fs_thread
8838 + ## NOTE WELL! The _Copy functions are called directly
8839 + ## from server-compiler-generated code via CallLeafNoFP,
8840 + ## which means that they *must* either not use floating
8841 + ## point or use it in the same manner as does the server
8842 + ## compiler.
8844 + .globl _Copy_arrayof_conjoint_bytes
8845 + .globl _Copy_conjoint_jshorts_atomic
8846 + .globl _Copy_arrayof_conjoint_jshorts
8847 + .globl _Copy_conjoint_jints_atomic
8848 + .globl _Copy_arrayof_conjoint_jints
8849 + .globl _Copy_conjoint_jlongs_atomic
8850 + .globl _Copy_arrayof_conjoint_jlongs
8852 + .section .text,"ax"
8854 + # Fast thread accessors, used by threadLS_solaris_amd64.cpp
8855 + .align 16
8856 +fs_load:
8857 + movq %fs:(%rdi),%rax
8858 + ret
8860 + .align 16
8861 +fs_thread:
8862 + movq %fs:0x0,%rax
8863 + ret
8865 + .globl SpinPause
8866 + .align 16
8867 +SpinPause:
8868 + rep
8869 + nop
8870 + movq $1, %rax
8871 + ret
8874 + # Support for void Copy::arrayof_conjoint_bytes(void* from,
8875 + # void* to,
8876 + # size_t count)
8877 + # rdi - from
8878 + # rsi - to
8879 + # rdx - count, treated as ssize_t
8881 + .align 16
8882 +_Copy_arrayof_conjoint_bytes:
8883 + movq %rdx,%r8 # byte count
8884 + shrq $3,%rdx # qword count
8885 + cmpq %rdi,%rsi
8886 + leaq -1(%rdi,%r8,1),%rax # from + bcount*1 - 1
8887 + jbe acb_CopyRight
8888 + cmpq %rax,%rsi
8889 + jbe acb_CopyLeft
8890 +acb_CopyRight:
8891 + leaq -8(%rdi,%rdx,8),%rax # from + qcount*8 - 8
8892 + leaq -8(%rsi,%rdx,8),%rcx # to + qcount*8 - 8
8893 + negq %rdx
8894 + jmp 7f
8895 + .align 16
8896 +1: movq 8(%rax,%rdx,8),%rsi
8897 + movq %rsi,8(%rcx,%rdx,8)
8898 + addq $1,%rdx
8899 + jnz 1b
8900 +2: testq $4,%r8 # check for trailing dword
8901 + jz 3f
8902 + movl 8(%rax),%esi # copy trailing dword
8903 + movl %esi,8(%rcx)
8904 + addq $4,%rax
8905 + addq $4,%rcx # original %rsi is trashed, so we
8906 + # can't use it as a base register
8907 +3: testq $2,%r8 # check for trailing word
8908 + jz 4f
8909 + movw 8(%rax),%si # copy trailing word
8910 + movw %si,8(%rcx)
8911 + addq $2,%rcx
8912 +4: testq $1,%r8 # check for trailing byte
8913 + jz 5f
8914 + movb -1(%rdi,%r8,1),%al # copy trailing byte
8915 + movb %al,8(%rcx)
8916 +5: ret
8917 + .align 16
8918 +6: movq -24(%rax,%rdx,8),%rsi
8919 + movq %rsi,-24(%rcx,%rdx,8)
8920 + movq -16(%rax,%rdx,8),%rsi
8921 + movq %rsi,-16(%rcx,%rdx,8)
8922 + movq -8(%rax,%rdx,8),%rsi
8923 + movq %rsi,-8(%rcx,%rdx,8)
8924 + movq (%rax,%rdx,8),%rsi
8925 + movq %rsi,(%rcx,%rdx,8)
8926 +7: addq $4,%rdx
8927 + jle 6b
8928 + subq $4,%rdx
8929 + jl 1b
8930 + jmp 2b
8931 +acb_CopyLeft:
8932 + testq $1,%r8 # check for trailing byte
8933 + jz 1f
8934 + movb -1(%rdi,%r8,1),%cl # copy trailing byte
8935 + movb %cl,-1(%rsi,%r8,1)
8936 + subq $1,%r8 # adjust for possible trailing word
8937 +1: testq $2,%r8 # check for trailing word
8938 + jz 2f
8939 + movw -2(%rdi,%r8,1),%cx # copy trailing word
8940 + movw %cx,-2(%rsi,%r8,1)
8941 +2: testq $4,%r8 # check for trailing dword
8942 + jz 5f
8943 + movl (%rdi,%rdx,8),%ecx # copy trailing dword
8944 + movl %ecx,(%rsi,%rdx,8)
8945 + jmp 5f
8946 + .align 16
8947 +3: movq -8(%rdi,%rdx,8),%rcx
8948 + movq %rcx,-8(%rsi,%rdx,8)
8949 + subq $1,%rdx
8950 + jnz 3b
8951 + ret
8952 + .align 16
8953 +4: movq 24(%rdi,%rdx,8),%rcx
8954 + movq %rcx,24(%rsi,%rdx,8)
8955 + movq 16(%rdi,%rdx,8),%rcx
8956 + movq %rcx,16(%rsi,%rdx,8)
8957 + movq 8(%rdi,%rdx,8),%rcx
8958 + movq %rcx,8(%rsi,%rdx,8)
8959 + movq (%rdi,%rdx,8),%rcx
8960 + movq %rcx,(%rsi,%rdx,8)
8961 +5: subq $4,%rdx
8962 + jge 4b
8963 + addq $4,%rdx
8964 + jg 3b
8965 + ret
8967 + # Support for void Copy::arrayof_conjoint_jshorts(void* from,
8968 + # void* to,
8969 + # size_t count)
8970 + # Equivalent to
8971 + # conjoint_jshorts_atomic
8973 + # If 'from' and/or 'to' are aligned on 4- or 2-byte boundaries, we
8974 + # let the hardware handle it. The tow or four words within dwords
8975 + # or qwords that span cache line boundaries will still be loaded
8976 + # and stored atomically.
8978 + # rdi - from
8979 + # rsi - to
8980 + # rdx - count, treated as ssize_t
8982 + .align 16
8983 +_Copy_arrayof_conjoint_jshorts:
8984 +_Copy_conjoint_jshorts_atomic:
8985 + movq %rdx,%r8 # word count
8986 + shrq $2,%rdx # qword count
8987 + cmpq %rdi,%rsi
8988 + leaq -2(%rdi,%r8,2),%rax # from + wcount*2 - 2
8989 + jbe acs_CopyRight
8990 + cmpq %rax,%rsi
8991 + jbe acs_CopyLeft
8992 +acs_CopyRight:
8993 + leaq -8(%rdi,%rdx,8),%rax # from + qcount*8 - 8
8994 + leaq -8(%rsi,%rdx,8),%rcx # to + qcount*8 - 8
8995 + negq %rdx
8996 + jmp 6f
8997 +1: movq 8(%rax,%rdx,8),%rsi
8998 + movq %rsi,8(%rcx,%rdx,8)
8999 + addq $1,%rdx
9000 + jnz 1b
9001 +2: testq $2,%r8 # check for trailing dword
9002 + jz 3f
9003 + movl 8(%rax),%esi # copy trailing dword
9004 + movl %esi,8(%rcx)
9005 + addq $4,%rcx # original %rsi is trashed, so we
9006 + # can't use it as a base register
9007 +3: testq $1,%r8 # check for trailing word
9008 + jz 4f
9009 + movw -2(%rdi,%r8,2),%si # copy trailing word
9010 + movw %si,8(%rcx)
9011 +4: ret
9012 + .align 16
9013 +5: movq -24(%rax,%rdx,8),%rsi
9014 + movq %rsi,-24(%rcx,%rdx,8)
9015 + movq -16(%rax,%rdx,8),%rsi
9016 + movq %rsi,-16(%rcx,%rdx,8)
9017 + movq -8(%rax,%rdx,8),%rsi
9018 + movq %rsi,-8(%rcx,%rdx,8)
9019 + movq (%rax,%rdx,8),%rsi
9020 + movq %rsi,(%rcx,%rdx,8)
9021 +6: addq $4,%rdx
9022 + jle 5b
9023 + subq $4,%rdx
9024 + jl 1b
9025 + jmp 2b
9026 +acs_CopyLeft:
9027 + testq $1,%r8 # check for trailing word
9028 + jz 1f
9029 + movw -2(%rdi,%r8,2),%cx # copy trailing word
9030 + movw %cx,-2(%rsi,%r8,2)
9031 +1: testq $2,%r8 # check for trailing dword
9032 + jz 4f
9033 + movl (%rdi,%rdx,8),%ecx # copy trailing dword
9034 + movl %ecx,(%rsi,%rdx,8)
9035 + jmp 4f
9036 +2: movq -8(%rdi,%rdx,8),%rcx
9037 + movq %rcx,-8(%rsi,%rdx,8)
9038 + subq $1,%rdx
9039 + jnz 2b
9040 + ret
9041 + .align 16
9042 +3: movq 24(%rdi,%rdx,8),%rcx
9043 + movq %rcx,24(%rsi,%rdx,8)
9044 + movq 16(%rdi,%rdx,8),%rcx
9045 + movq %rcx,16(%rsi,%rdx,8)
9046 + movq 8(%rdi,%rdx,8),%rcx
9047 + movq %rcx,8(%rsi,%rdx,8)
9048 + movq (%rdi,%rdx,8),%rcx
9049 + movq %rcx,(%rsi,%rdx,8)
9050 +4: subq $4,%rdx
9051 + jge 3b
9052 + addq $4,%rdx
9053 + jg 2b
9054 + ret
9056 + # Support for void Copy::arrayof_conjoint_jints(jint* from,
9057 + # jint* to,
9058 + # size_t count)
9059 + # Equivalent to
9060 + # conjoint_jints_atomic
9062 + # If 'from' and/or 'to' are aligned on 4-byte boundaries, we let
9063 + # the hardware handle it. The two dwords within qwords that span
9064 + # cache line boundaries will still be loaded and stored atomically.
9066 + # rdi - from
9067 + # rsi - to
9068 + # rdx - count, treated as ssize_t
9070 + .align 16
9071 +_Copy_arrayof_conjoint_jints:
9072 +_Copy_conjoint_jints_atomic:
9073 + movq %rdx,%r8 # dword count
9074 + shrq %rdx # qword count
9075 + cmpq %rdi,%rsi
9076 + leaq -4(%rdi,%r8,4),%rax # from + dcount*4 - 4
9077 + jbe aci_CopyRight
9078 + cmpq %rax,%rsi
9079 + jbe aci_CopyLeft
9080 +aci_CopyRight:
9081 + leaq -8(%rdi,%rdx,8),%rax # from + qcount*8 - 8
9082 + leaq -8(%rsi,%rdx,8),%rcx # to + qcount*8 - 8
9083 + negq %rdx
9084 + jmp 5f
9085 + .align 16
9086 +1: movq 8(%rax,%rdx,8),%rsi
9087 + movq %rsi,8(%rcx,%rdx,8)
9088 + addq $1,%rdx
9089 + jnz 1b
9090 +2: testq $1,%r8 # check for trailing dword
9091 + jz 3f
9092 + movl 8(%rax),%esi # copy trailing dword
9093 + movl %esi,8(%rcx)
9094 +3: ret
9095 + .align 16
9096 +4: movq -24(%rax,%rdx,8),%rsi
9097 + movq %rsi,-24(%rcx,%rdx,8)
9098 + movq -16(%rax,%rdx,8),%rsi
9099 + movq %rsi,-16(%rcx,%rdx,8)
9100 + movq -8(%rax,%rdx,8),%rsi
9101 + movq %rsi,-8(%rcx,%rdx,8)
9102 + movq (%rax,%rdx,8),%rsi
9103 + movq %rsi,(%rcx,%rdx,8)
9104 +5: addq $4,%rdx
9105 + jle 4b
9106 + subq $4,%rdx
9107 + jl 1b
9108 + jmp 2b
9109 +aci_CopyLeft:
9110 + testq $1,%r8 # check for trailing dword
9111 + jz 3f
9112 + movl -4(%rdi,%r8,4),%ecx # copy trailing dword
9113 + movl %ecx,-4(%rsi,%r8,4)
9114 + jmp 3f
9115 +1: movq -8(%rdi,%rdx,8),%rcx
9116 + movq %rcx,-8(%rsi,%rdx,8)
9117 + subq $1,%rdx
9118 + jnz 1b
9119 + ret
9120 + .align 16
9121 +2: movq 24(%rdi,%rdx,8),%rcx
9122 + movq %rcx,24(%rsi,%rdx,8)
9123 + movq 16(%rdi,%rdx,8),%rcx
9124 + movq %rcx,16(%rsi,%rdx,8)
9125 + movq 8(%rdi,%rdx,8),%rcx
9126 + movq %rcx,8(%rsi,%rdx,8)
9127 + movq (%rdi,%rdx,8),%rcx
9128 + movq %rcx,(%rsi,%rdx,8)
9129 +3: subq $4,%rdx
9130 + jge 2b
9131 + addq $4,%rdx
9132 + jg 1b
9133 + ret
9135 + # Support for void Copy::arrayof_conjoint_jlongs(jlong* from,
9136 + # jlong* to,
9137 + # size_t count)
9138 + # Equivalent to
9139 + # conjoint_jlongs_atomic
9140 + # arrayof_conjoint_oops
9141 + # conjoint_oops_atomic
9143 + # rdi - from
9144 + # rsi - to
9145 + # rdx - count, treated as ssize_t
9147 + .align 16
9148 +_Copy_arrayof_conjoint_jlongs:
9149 +_Copy_conjoint_jlongs_atomic:
9150 + cmpq %rdi,%rsi
9151 + leaq -8(%rdi,%rdx,8),%rax # from + count*8 - 8
9152 + jbe acl_CopyRight
9153 + cmpq %rax,%rsi
9154 + jbe acl_CopyLeft
9155 +acl_CopyRight:
9156 + leaq -8(%rsi,%rdx,8),%rcx # to + count*8 - 8
9157 + negq %rdx
9158 + jmp 3f
9159 +1: movq 8(%rax,%rdx,8),%rsi
9160 + movq %rsi,8(%rcx,%rdx,8)
9161 + addq $1,%rdx
9162 + jnz 1b
9163 + ret
9164 + .align 16
9165 +2: movq -24(%rax,%rdx,8),%rsi
9166 + movq %rsi,-24(%rcx,%rdx,8)
9167 + movq -16(%rax,%rdx,8),%rsi
9168 + movq %rsi,-16(%rcx,%rdx,8)
9169 + movq -8(%rax,%rdx,8),%rsi
9170 + movq %rsi,-8(%rcx,%rdx,8)
9171 + movq (%rax,%rdx,8),%rsi
9172 + movq %rsi,(%rcx,%rdx,8)
9173 +3: addq $4,%rdx
9174 + jle 2b
9175 + subq $4,%rdx
9176 + jl 1b
9177 + ret
9178 +4: movq -8(%rdi,%rdx,8),%rcx
9179 + movq %rcx,-8(%rsi,%rdx,8)
9180 + subq $1,%rdx
9181 + jnz 4b
9182 + ret
9183 + .align 16
9184 +5: movq 24(%rdi,%rdx,8),%rcx
9185 + movq %rcx,24(%rsi,%rdx,8)
9186 + movq 16(%rdi,%rdx,8),%rcx
9187 + movq %rcx,16(%rsi,%rdx,8)
9188 + movq 8(%rdi,%rdx,8),%rcx
9189 + movq %rcx,8(%rsi,%rdx,8)
9190 + movq (%rdi,%rdx,8),%rcx
9191 + movq %rcx,(%rsi,%rdx,8)
9192 +acl_CopyLeft:
9193 + subq $4,%rdx
9194 + jge 5b
9195 + addq $4,%rdx
9196 + jg 4b
9197 + ret
9198 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/os_cpu/solaris_x86/vm_version_solaris_x86.cpp jdk23u-jdk-23-36/src/hotspot/os_cpu/solaris_x86/vm_version_solaris_x86.cpp
9199 --- jdk23u-jdk-23-36.orig/src/hotspot/os_cpu/solaris_x86/vm_version_solaris_x86.cpp 1970-01-01 01:00:00.000000000 +0100
9200 +++ jdk23u-jdk-23-36/src/hotspot/os_cpu/solaris_x86/vm_version_solaris_x86.cpp 2024-08-17 19:50:33.150897702 +0200
9201 @@ -0,0 +1,28 @@
9203 + * Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved.
9204 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
9206 + * This code is free software; you can redistribute it and/or modify it
9207 + * under the terms of the GNU General Public License version 2 only, as
9208 + * published by the Free Software Foundation.
9210 + * This code is distributed in the hope that it will be useful, but WITHOUT
9211 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
9212 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
9213 + * version 2 for more details (a copy is included in the LICENSE file that
9214 + * accompanied this code).
9216 + * You should have received a copy of the GNU General Public License version
9217 + * 2 along with this work; if not, write to the Free Software Foundation,
9218 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
9220 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
9221 + * or visit www.oracle.com if you need additional information or have any
9222 + * questions.
9224 + */
9226 +#include "precompiled.hpp"
9227 +#include "runtime/os.hpp"
9228 +#include "runtime/vm_version.hpp"
9230 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/os_cpu/solaris_x86/vmStructs_solaris_x86.hpp jdk23u-jdk-23-36/src/hotspot/os_cpu/solaris_x86/vmStructs_solaris_x86.hpp
9231 --- jdk23u-jdk-23-36.orig/src/hotspot/os_cpu/solaris_x86/vmStructs_solaris_x86.hpp 1970-01-01 01:00:00.000000000 +0100
9232 +++ jdk23u-jdk-23-36/src/hotspot/os_cpu/solaris_x86/vmStructs_solaris_x86.hpp 2024-08-17 19:50:33.150634578 +0200
9233 @@ -0,0 +1,40 @@
9235 + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
9236 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
9238 + * This code is free software; you can redistribute it and/or modify it
9239 + * under the terms of the GNU General Public License version 2 only, as
9240 + * published by the Free Software Foundation.
9242 + * This code is distributed in the hope that it will be useful, but WITHOUT
9243 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
9244 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
9245 + * version 2 for more details (a copy is included in the LICENSE file that
9246 + * accompanied this code).
9248 + * You should have received a copy of the GNU General Public License version
9249 + * 2 along with this work; if not, write to the Free Software Foundation,
9250 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
9252 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
9253 + * or visit www.oracle.com if you need additional information or have any
9254 + * questions.
9256 + */
9258 +#ifndef OS_CPU_SOLARIS_X86_VMSTRUCTS_SOLARIS_X86_HPP
9259 +#define OS_CPU_SOLARIS_X86_VMSTRUCTS_SOLARIS_X86_HPP
9261 +// These are the OS and CPU-specific fields, types and integer
9262 +// constants required by the Serviceability Agent. This file is
9263 +// referenced by vmStructs.cpp.
9265 +#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)
9267 +#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)
9269 +#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
9271 +#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
9273 +#endif // OS_CPU_SOLARIS_X86_VMSTRUCTS_SOLARIS_X86_HPP
9274 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/share/c1/c1_LIR.cpp jdk23u-jdk-23-36/src/hotspot/share/c1/c1_LIR.cpp
9275 --- jdk23u-jdk-23-36.orig/src/hotspot/share/c1/c1_LIR.cpp 2024-08-07 00:08:22.000000000 +0200
9276 +++ jdk23u-jdk-23-36/src/hotspot/share/c1/c1_LIR.cpp 2024-08-17 19:50:33.091601170 +0200
9277 @@ -452,6 +452,8 @@
9278 case lir_monaddr: // input and result always valid, info always invalid
9279 case lir_null_check: // input and info always valid, result always invalid
9280 case lir_move: // input and result always valid, may have info
9281 + case lir_pack64: // input and result always valid
9282 + case lir_unpack64: // input and result always valid
9284 assert(op->as_Op1() != nullptr, "must be");
9285 LIR_Op1* op1 = (LIR_Op1*)op;
9286 @@ -1736,6 +1738,8 @@
9287 case lir_convert: s = "convert"; break;
9288 case lir_alloc_object: s = "alloc_obj"; break;
9289 case lir_monaddr: s = "mon_addr"; break;
9290 + case lir_pack64: s = "pack64"; break;
9291 + case lir_unpack64: s = "unpack64"; break;
9292 // LIR_Op2
9293 case lir_cmp: s = "cmp"; break;
9294 case lir_cmp_l2i: s = "cmp_l2i"; break;
9295 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/share/c1/c1_LIR.hpp jdk23u-jdk-23-36/src/hotspot/share/c1/c1_LIR.hpp
9296 --- jdk23u-jdk-23-36.orig/src/hotspot/share/c1/c1_LIR.hpp 2024-08-07 00:08:22.000000000 +0200
9297 +++ jdk23u-jdk-23-36/src/hotspot/share/c1/c1_LIR.hpp 2024-08-17 19:50:33.092480161 +0200
9298 @@ -939,6 +939,8 @@
9299 , lir_monaddr
9300 , lir_roundfp
9301 , lir_safepoint
9302 + , lir_pack64
9303 + , lir_unpack64
9304 , lir_unwind
9305 , lir_load_klass
9306 , end_op1
9307 @@ -2237,6 +2239,9 @@
9308 void logical_or (LIR_Opr left, LIR_Opr right, LIR_Opr dst) { append(new LIR_Op2(lir_logic_or, left, right, dst)); }
9309 void logical_xor (LIR_Opr left, LIR_Opr right, LIR_Opr dst) { append(new LIR_Op2(lir_logic_xor, left, right, dst)); }
9311 + void pack64(LIR_Opr src, LIR_Opr dst) { append(new LIR_Op1(lir_pack64, src, dst, T_LONG, lir_patch_none, NULL)); }
9312 + void unpack64(LIR_Opr src, LIR_Opr dst) { append(new LIR_Op1(lir_unpack64, src, dst, T_LONG, lir_patch_none, NULL)); }
9314 void null_check(LIR_Opr opr, CodeEmitInfo* info, bool deoptimize_on_null = false);
9315 void throw_exception(LIR_Opr exceptionPC, LIR_Opr exceptionOop, CodeEmitInfo* info) {
9316 append(new LIR_Op2(lir_throw, exceptionPC, exceptionOop, LIR_OprFact::illegalOpr, info));
9317 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/share/cds/classListParser.cpp jdk23u-jdk-23-36/src/hotspot/share/cds/classListParser.cpp
9318 --- jdk23u-jdk-23-36.orig/src/hotspot/share/cds/classListParser.cpp 2024-08-07 00:08:22.000000000 +0200
9319 +++ jdk23u-jdk-23-36/src/hotspot/share/cds/classListParser.cpp 2024-08-17 19:50:33.093004628 +0200
9320 @@ -456,7 +456,7 @@
9321 // This function is used for loading classes for customized class loaders
9322 // during archive dumping.
9323 InstanceKlass* ClassListParser::load_class_from_source(Symbol* class_name, TRAPS) {
9324 -#if !(defined(_LP64) && (defined(LINUX) || defined(__APPLE__) || defined(_WINDOWS)))
9325 +#if !(defined(_LP64) && (defined(LINUX)|| defined(SOLARIS) || defined(__APPLE__) || defined(_WINDOWS)))
9326 // The only supported platforms are: (1) Linux/64-bit and (2) Solaris/64-bit and
9327 // (3) MacOSX/64-bit and (4) Windowss/64-bit
9328 // This #if condition should be in sync with the areCustomLoadersSupportedForCDS
9329 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/share/nmt/memTracker.cpp jdk23u-jdk-23-36/src/hotspot/share/nmt/memTracker.cpp
9330 --- jdk23u-jdk-23-36.orig/src/hotspot/share/nmt/memTracker.cpp 2024-08-07 00:08:22.000000000 +0200
9331 +++ jdk23u-jdk-23-36/src/hotspot/share/nmt/memTracker.cpp 2024-08-17 19:50:33.094606611 +0200
9332 @@ -48,6 +48,12 @@
9333 #include <windows.h>
9334 #endif
9336 +#ifdef SOLARIS
9337 + volatile bool NMT_stack_walkable = false;
9338 +#else
9339 + volatile bool NMT_stack_walkable = true;
9340 +#endif
9342 NMT_TrackingLevel MemTracker::_tracking_level = NMT_unknown;
9344 MemBaseline MemTracker::_baseline;
9345 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/share/nmt/memTracker.hpp jdk23u-jdk-23-36/src/hotspot/share/nmt/memTracker.hpp
9346 --- jdk23u-jdk-23-36.orig/src/hotspot/share/nmt/memTracker.hpp 2024-08-07 00:08:22.000000000 +0200
9347 +++ jdk23u-jdk-23-36/src/hotspot/share/nmt/memTracker.hpp 2024-08-17 19:50:33.094996481 +0200
9348 @@ -35,9 +35,11 @@
9349 #include "utilities/debug.hpp"
9350 #include "utilities/nativeCallStack.hpp"
9352 -#define CURRENT_PC ((MemTracker::tracking_level() == NMT_detail) ? \
9353 +extern volatile bool NMT_stack_walkable;
9355 +#define CURRENT_PC ((MemTracker::tracking_level() == NMT_detail && NMT_stack_walkable) ? \
9356 NativeCallStack(0) : FAKE_CALLSTACK)
9357 -#define CALLER_PC ((MemTracker::tracking_level() == NMT_detail) ? \
9358 +#define CALLER_PC ((MemTracker::tracking_level() == NMT_detail && NMT_stack_walkable) ? \
9359 NativeCallStack(1) : FAKE_CALLSTACK)
9361 class MemBaseline;
9362 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/share/runtime/abstract_vm_version.cpp jdk23u-jdk-23-36/src/hotspot/share/runtime/abstract_vm_version.cpp
9363 --- jdk23u-jdk-23-36.orig/src/hotspot/share/runtime/abstract_vm_version.cpp 2024-08-07 00:08:22.000000000 +0200
9364 +++ jdk23u-jdk-23-36/src/hotspot/share/runtime/abstract_vm_version.cpp 2024-08-17 19:50:33.093765045 +0200
9365 @@ -171,6 +171,7 @@
9367 #define OS LINUX_ONLY("linux") \
9368 WINDOWS_ONLY("windows") \
9369 + SOLARIS_ONLY("solaris") \
9370 AIX_ONLY("aix") \
9371 BSD_ONLY("bsd")
9373 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/share/runtime/semaphore.hpp jdk23u-jdk-23-36/src/hotspot/share/runtime/semaphore.hpp
9374 --- jdk23u-jdk-23-36.orig/src/hotspot/share/runtime/semaphore.hpp 2024-08-07 00:08:22.000000000 +0200
9375 +++ jdk23u-jdk-23-36/src/hotspot/share/runtime/semaphore.hpp 2024-08-17 19:50:33.094185823 +0200
9376 @@ -28,7 +28,7 @@
9377 #include "memory/allocation.hpp"
9378 #include "utilities/globalDefinitions.hpp"
9380 -#if defined(LINUX) || defined(AIX)
9381 +#if defined(LINUX) || defined(SOLARIS) || defined(AIX)
9382 # include "semaphore_posix.hpp"
9383 #else
9384 # include OS_HEADER(semaphore)
9385 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/share/services/dtraceAttacher.cpp jdk23u-jdk-23-36/src/hotspot/share/services/dtraceAttacher.cpp
9386 --- jdk23u-jdk-23-36.orig/src/hotspot/share/services/dtraceAttacher.cpp 1970-01-01 01:00:00.000000000 +0100
9387 +++ jdk23u-jdk-23-36/src/hotspot/share/services/dtraceAttacher.cpp 2024-08-17 19:50:33.151225291 +0200
9388 @@ -0,0 +1,99 @@
9390 + * Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved.
9391 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
9393 + * This code is free software; you can redistribute it and/or modify it
9394 + * under the terms of the GNU General Public License version 2 only, as
9395 + * published by the Free Software Foundation.
9397 + * This code is distributed in the hope that it will be useful, but WITHOUT
9398 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
9399 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
9400 + * version 2 for more details (a copy is included in the LICENSE file that
9401 + * accompanied this code).
9403 + * You should have received a copy of the GNU General Public License version
9404 + * 2 along with this work; if not, write to the Free Software Foundation,
9405 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
9407 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
9408 + * or visit www.oracle.com if you need additional information or have any
9409 + * questions.
9411 + */
9413 +#include "precompiled.hpp"
9414 +#include "code/codeCache.hpp"
9415 +#include "memory/resourceArea.hpp"
9416 +#include "runtime/deoptimization.hpp"
9417 +#include "runtime/flags/jvmFlag.hpp"
9418 +#include "runtime/vmThread.hpp"
9419 +#include "runtime/vmOperations.hpp"
9420 +#include "services/dtraceAttacher.hpp"
9421 +#include "runtime/flags/jvmFlagAccess.hpp"
9423 +#ifdef SOLARIS
9425 +static void set_bool_flag(const char* name, bool value) {
9426 + JVMFlag* flag = JVMFlag::find_flag(name);
9427 + JVMFlagAccess::set_bool(flag, &value, JVMFlagOrigin::ATTACH_ON_DEMAND);
9430 +// Enable the "fine grained" flags.
9431 +void DTrace::enable_dprobes(int probes) {
9432 + bool changed = false;
9433 + if (!DTraceAllocProbes && (probes & DTRACE_ALLOC_PROBES)) {
9434 + set_bool_flag("DTraceAllocProbes", true);
9435 + changed = true;
9437 + if (!DTraceMethodProbes && (probes & DTRACE_METHOD_PROBES)) {
9438 + set_bool_flag("DTraceMethodProbes", true);
9439 + changed = true;
9441 + if (!DTraceMonitorProbes && (probes & DTRACE_MONITOR_PROBES)) {
9442 + set_bool_flag("DTraceMonitorProbes", true);
9443 + changed = true;
9446 + if (changed) {
9447 + // one or more flags changed, need to deoptimize
9448 + DeoptimizationScope deopt_scope;
9449 + CodeCache::mark_all_nmethods_for_deoptimization(&deopt_scope);
9450 + deopt_scope.deoptimize_marked();
9454 +// Disable the "fine grained" flags.
9455 +void DTrace::disable_dprobes(int probes) {
9456 + bool changed = false;
9457 + if (DTraceAllocProbes && (probes & DTRACE_ALLOC_PROBES)) {
9458 + set_bool_flag("DTraceAllocProbes", false);
9459 + changed = true;
9461 + if (DTraceMethodProbes && (probes & DTRACE_METHOD_PROBES)) {
9462 + set_bool_flag("DTraceMethodProbes", false);
9463 + changed = true;
9465 + if (DTraceMonitorProbes && (probes & DTRACE_MONITOR_PROBES)) {
9466 + set_bool_flag("DTraceMonitorProbes", false);
9467 + changed = true;
9469 + if (changed) {
9470 + // one or more flags changed, need to deoptimize
9471 + DeoptimizationScope deopt_scope;
9472 + CodeCache::mark_all_nmethods_for_deoptimization(&deopt_scope);
9473 + deopt_scope.deoptimize_marked();
9477 +// Do clean-up on "all door clients detached" event.
9478 +void DTrace::detach_all_clients() {
9479 + disable_dprobes(DTRACE_ALL_PROBES);
9482 +void DTrace::set_monitor_dprobes(bool flag) {
9483 + // explicit setting of DTraceMonitorProbes flag
9484 + set_bool_flag("DTraceMonitorProbes", flag);
9487 +#endif /* SOLARIS */
9488 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/share/utilities/debug.cpp jdk23u-jdk-23-36/src/hotspot/share/utilities/debug.cpp
9489 --- jdk23u-jdk-23-36.orig/src/hotspot/share/utilities/debug.cpp 2024-08-07 00:08:22.000000000 +0200
9490 +++ jdk23u-jdk-23-36/src/hotspot/share/utilities/debug.cpp 2024-08-17 19:50:33.095793994 +0200
9491 @@ -611,11 +611,12 @@
9492 tty->print_cr(" findm(intptr_t pc) - finds Method*");
9493 tty->print_cr(" find(intptr_t x) - finds & prints nmethod/stub/bytecode/oop based on pointer into it");
9494 tty->print_cr(" pns(void* sp, void* fp, void* pc) - print native (i.e. mixed) stack trace. E.g.");
9495 - tty->print_cr(" pns($sp, $rbp, $pc) on Linux/amd64 or");
9496 + tty->print_cr(" pns($sp, $rbp, $pc) on Linux/amd64 and Solaris/amd64 or");
9497 tty->print_cr(" pns($sp, $ebp, $pc) on Linux/x86 or");
9498 tty->print_cr(" pns($sp, $fp, $pc) on Linux/AArch64 or");
9499 tty->print_cr(" pns($sp, 0, $pc) on Linux/ppc64 or");
9500 tty->print_cr(" pns($sp, $s8, $pc) on Linux/mips or");
9501 + tty->print_cr(" pns($sp + 0x7ff, 0, $pc) on Solaris/SPARC");
9502 tty->print_cr(" - in gdb do 'set overload-resolution off' before calling pns()");
9503 tty->print_cr(" - in dbx do 'frame 1' before calling pns()");
9504 tty->print_cr("class metadata.");
9505 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/share/utilities/globalDefinitions_gcc.hpp jdk23u-jdk-23-36/src/hotspot/share/utilities/globalDefinitions_gcc.hpp
9506 --- jdk23u-jdk-23-36.orig/src/hotspot/share/utilities/globalDefinitions_gcc.hpp 2024-08-07 00:08:22.000000000 +0200
9507 +++ jdk23u-jdk-23-36/src/hotspot/share/utilities/globalDefinitions_gcc.hpp 2024-08-17 19:50:33.096598834 +0200
9508 @@ -50,15 +50,36 @@
9509 #endif
9510 #include <wchar.h>
9512 +#ifdef SOLARIS
9513 +#include <ieeefp.h>
9514 +#endif // SOLARIS
9516 #include <math.h>
9517 #include <time.h>
9518 #include <fcntl.h>
9519 #include <dlfcn.h>
9520 #include <pthread.h>
9522 +#ifdef SOLARIS
9523 +#include <thread.h>
9524 +#endif // SOLARIS
9526 #include <limits.h>
9527 #include <errno.h>
9529 +#ifdef SOLARIS
9530 +#include <sys/trap.h>
9531 +#include <sys/regset.h>
9532 +#include <sys/procset.h>
9533 +#include <ucontext.h>
9534 +#include <setjmp.h>
9535 +#include <inttypes.h>
9536 +#endif // SOLARIS
9538 +# ifdef SOLARIS_MUTATOR_LIBTHREAD
9539 +# include <sys/procfs.h>
9540 +# endif
9542 #if defined(LINUX) || defined(_ALLBSD_SOURCE) || defined(_AIX)
9543 #include <signal.h>
9544 #ifndef __OpenBSD__
9545 @@ -71,6 +92,34 @@
9546 #include <sys/time.h>
9547 #endif // LINUX || _ALLBSD_SOURCE
9549 +// 4810578: varargs unsafe on 32-bit integer/64-bit pointer architectures
9550 +// When __cplusplus is defined, NULL is defined as 0 (32-bit constant) in
9551 +// system header files. On 32-bit architectures, there is no problem.
9552 +// On 64-bit architectures, defining NULL as a 32-bit constant can cause
9553 +// problems with varargs functions: C++ integral promotion rules say for
9554 +// varargs, we pass the argument 0 as an int. So, if NULL was passed to a
9555 +// varargs function it will remain 32-bits. Depending on the calling
9556 +// convention of the machine, if the argument is passed on the stack then
9557 +// only 32-bits of the "NULL" pointer may be initialized to zero. The
9558 +// other 32-bits will be garbage. If the varargs function is expecting a
9559 +// pointer when it extracts the argument, then we have a problem.
9561 +// Solution: For 64-bit architectures, redefine NULL as 64-bit constant 0.
9563 +// Note: this fix doesn't work well on Linux because NULL will be overwritten
9564 +// whenever a system header file is included. Linux handles NULL correctly
9565 +// through a special type '__null'.
9566 +#ifdef SOLARIS
9567 + #ifdef _LP64
9568 + #undef NULL
9569 + #define NULL 0L
9570 + #else
9571 + #ifndef NULL
9572 + #define NULL 0
9573 + #endif
9574 + #endif
9575 +#endif
9577 // NULL vs NULL_WORD:
9578 // On Linux NULL is defined as a special type '__null'. Assigning __null to
9579 // integer variable will cause gcc warning. Use NULL_WORD in places where a
9580 @@ -89,8 +138,51 @@
9581 #define NULL_WORD NULL
9582 #endif
9584 +#ifdef SOLARIS
9585 +// ANSI C++ fixes
9586 +// NOTE:In the ANSI committee's continuing attempt to make each version
9587 +// of C++ incompatible with the previous version, you can no longer cast
9588 +// pointers to functions without specifying linkage unless you want to get
9589 +// warnings.
9591 +// This also means that pointers to functions can no longer be "hidden"
9592 +// in opaque types like void * because at the invocation point warnings
9593 +// will be generated. While this makes perfect sense from a type safety
9594 +// point of view it causes a lot of warnings on old code using C header
9595 +// files. Here are some typedefs to make the job of silencing warnings
9596 +// a bit easier.
9598 +// The final kick in the teeth is that you can only have extern "C" linkage
9599 +// specified at file scope. So these typedefs are here rather than in the
9600 +// .hpp for the class (os:Solaris usually) that needs them.
9602 +extern "C" {
9603 + typedef int (*int_fnP_thread_t_iP_uP_stack_tP_gregset_t)(thread_t, int*, unsigned *, stack_t*, gregset_t);
9604 + typedef int (*int_fnP_thread_t_i_gregset_t)(thread_t, int, gregset_t);
9605 + typedef int (*int_fnP_thread_t_i)(thread_t, int);
9606 + typedef int (*int_fnP_thread_t)(thread_t);
9608 + typedef int (*int_fnP_cond_tP_mutex_tP_timestruc_tP)(cond_t *cv, mutex_t *mx, timestruc_t *abst);
9609 + typedef int (*int_fnP_cond_tP_mutex_tP)(cond_t *cv, mutex_t *mx);
9611 + // typedef for missing API in libc
9612 + typedef int (*int_fnP_mutex_tP_i_vP)(mutex_t *, int, void *);
9613 + typedef int (*int_fnP_mutex_tP)(mutex_t *);
9614 + typedef int (*int_fnP_cond_tP_i_vP)(cond_t *cv, int scope, void *arg);
9615 + typedef int (*int_fnP_cond_tP)(cond_t *cv);
9617 +#endif // SOLARIS
9619 // checking for nanness
9620 -#if defined(__APPLE__)
9621 +#ifdef SOLARIS
9622 +#ifdef SPARC
9623 +inline int g_isnan(float f) { return isnanf(f); }
9624 +#else
9625 +// isnanf() broken on Intel Solaris use isnand()
9626 +inline int g_isnan(float f) { return isnand(f); }
9627 +#endif
9628 +inline int g_isnan(double f) { return isnand(f); }
9629 +#elif defined(__APPLE__)
9630 inline int g_isnan(double f) { return isnan(f); }
9631 #elif defined(LINUX) || defined(_ALLBSD_SOURCE) || defined(_AIX)
9632 inline int g_isnan(float f) { return isnan(f); }
9633 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/share/utilities/macros.hpp jdk23u-jdk-23-36/src/hotspot/share/utilities/macros.hpp
9634 --- jdk23u-jdk-23-36.orig/src/hotspot/share/utilities/macros.hpp 2024-08-07 00:08:22.000000000 +0200
9635 +++ jdk23u-jdk-23-36/src/hotspot/share/utilities/macros.hpp 2024-08-17 19:50:33.097261571 +0200
9636 @@ -401,6 +401,14 @@
9637 #define NOT_AIX(code) code
9638 #endif
9640 +#ifdef SOLARIS
9641 +#define SOLARIS_ONLY(code) code
9642 +#define NOT_SOLARIS(code)
9643 +#else
9644 +#define SOLARIS_ONLY(code)
9645 +#define NOT_SOLARIS(code) code
9646 +#endif
9648 #ifdef _WINDOWS
9649 #define WINDOWS_ONLY(code) code
9650 #define NOT_WINDOWS(code)
9651 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/share/utilities/ostream.cpp jdk23u-jdk-23-36/src/hotspot/share/utilities/ostream.cpp
9652 --- jdk23u-jdk-23-36.orig/src/hotspot/share/utilities/ostream.cpp 2024-08-07 00:08:22.000000000 +0200
9653 +++ jdk23u-jdk-23-36/src/hotspot/share/utilities/ostream.cpp 2024-08-17 19:50:33.097983260 +0200
9654 @@ -1064,7 +1064,7 @@
9656 #ifndef PRODUCT
9658 -#if defined(LINUX) || defined(AIX) || defined(_ALLBSD_SOURCE)
9659 +#if defined(SOLARIS) || defined(LINUX) || defined(AIX) || defined(_ALLBSD_SOURCE)
9660 #include <sys/types.h>
9661 #include <sys/socket.h>
9662 #include <netinet/in.h>
9663 diff -Nru jdk23u-jdk-23-36.orig/src/hotspot/share/utilities/vmError.cpp jdk23u-jdk-23-36/src/hotspot/share/utilities/vmError.cpp
9664 --- jdk23u-jdk-23-36.orig/src/hotspot/share/utilities/vmError.cpp 2024-08-07 00:08:22.000000000 +0200
9665 +++ jdk23u-jdk-23-36/src/hotspot/share/utilities/vmError.cpp 2024-08-17 19:50:33.099275086 +0200
9666 @@ -1914,6 +1914,8 @@
9667 out.print_raw ("# Executing ");
9668 #if defined(LINUX) || defined(_ALLBSD_SOURCE)
9669 out.print_raw ("/bin/sh -c ");
9670 +#elif defined(SOLARIS)
9671 + out.print_raw ("/usr/bin/sh -c ");
9672 #elif defined(_WINDOWS)
9673 out.print_raw ("cmd /C ");
9674 #endif
9675 @@ -1978,6 +1980,8 @@
9676 tty->print("# Executing ");
9677 #if defined(LINUX)
9678 tty->print ("/bin/sh -c ");
9679 +#elif defined(SOLARIS)
9680 + tty->print ("/usr/bin/sh -c ");
9681 #endif
9682 tty->print_cr("\"%s\"...", cmd);
9684 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/share/classes/sun/net/sdp/SdpSupport.java jdk23u-jdk-23-36/src/java.base/share/classes/sun/net/sdp/SdpSupport.java
9685 --- jdk23u-jdk-23-36.orig/src/java.base/share/classes/sun/net/sdp/SdpSupport.java 2024-08-07 00:08:22.000000000 +0200
9686 +++ jdk23u-jdk-23-36/src/java.base/share/classes/sun/net/sdp/SdpSupport.java 2024-08-17 19:50:33.100103395 +0200
9687 @@ -39,7 +39,7 @@
9690 public final class SdpSupport {
9691 - private static final boolean isSupported = OperatingSystem.isLinux();
9692 + private static final boolean isSupported = (OperatingSystem.isSolaris() || OperatingSystem.isLinux());
9693 private static final JavaIOFileDescriptorAccess fdAccess =
9694 SharedSecrets.getJavaIOFileDescriptorAccess();
9696 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/share/classes/sun/nio/ch/Net.java jdk23u-jdk-23-36/src/java.base/share/classes/sun/nio/ch/Net.java
9697 --- jdk23u-jdk-23-36.orig/src/java.base/share/classes/sun/nio/ch/Net.java 2024-08-07 00:08:22.000000000 +0200
9698 +++ jdk23u-jdk-23-36/src/java.base/share/classes/sun/nio/ch/Net.java 2024-08-17 19:50:33.100964141 +0200
9699 @@ -512,7 +512,7 @@
9700 private static native boolean isReusePortAvailable0();
9703 - * Returns 1 for Windows and -1 for Linux/Mac OS
9704 + * Returns 1 for Windows and -1 for Solaris/Linux/Mac OS
9706 private static native int isExclusiveBindAvailable();
9708 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/share/classes/sun/nio/ch/SocketOptionRegistry.java.template jdk23u-jdk-23-36/src/java.base/share/classes/sun/nio/ch/SocketOptionRegistry.java.template
9709 --- jdk23u-jdk-23-36.orig/src/java.base/share/classes/sun/nio/ch/SocketOptionRegistry.java.template 2024-08-07 00:08:22.000000000 +0200
9710 +++ jdk23u-jdk-23-36/src/java.base/share/classes/sun/nio/ch/SocketOptionRegistry.java.template 2024-08-17 19:50:33.101720954 +0200
9711 @@ -43,6 +43,8 @@
9712 #define SO_REUSEPORT 0
9713 #elif defined(__linux__)
9714 #define SO_REUSEPORT 15
9715 +#elif defined(__solaris__)
9716 +#define SO_REUSEPORT 0x100e
9717 #elif defined(AIX) || defined(MACOSX)
9718 #define SO_REUSEPORT 0x0200
9719 #else
9720 @@ -50,6 +52,10 @@
9721 #endif
9722 #endif
9724 +/* On Solaris, "sun" is defined as a macro. Undefine to make package
9725 + declaration valid */
9726 +#undef sun
9728 /* To be able to name the Java constants the same as the C constants without
9729 having the preprocessor rewrite those identifiers, add PREFIX_ to all
9730 identifiers matching a C constant. The PREFIX_ is filtered out in the
9731 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/share/conf/security/java.security jdk23u-jdk-23-36/src/java.base/share/conf/security/java.security
9732 --- jdk23u-jdk-23-36.orig/src/java.base/share/conf/security/java.security 2024-08-07 00:08:22.000000000 +0200
9733 +++ jdk23u-jdk-23-36/src/java.base/share/conf/security/java.security 2024-08-17 19:50:33.102436271 +0200
9734 @@ -83,7 +83,11 @@
9735 #ifdef macosx
9736 security.provider.tbd=Apple
9737 #endif
9738 +#ifdef solaris
9739 +security.provider.tbd=SunPKCS11 ${java.home}/conf/security/sunpkcs11-solaris.cfg
9740 +#else
9741 security.provider.tbd=SunPKCS11
9742 +#endif
9745 # A list of preferred providers for specific algorithms. These providers will
9746 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/share/native/libjli/jli_util.h jdk23u-jdk-23-36/src/java.base/share/native/libjli/jli_util.h
9747 --- jdk23u-jdk-23-36.orig/src/java.base/share/native/libjli/jli_util.h 2024-08-07 00:08:22.000000000 +0200
9748 +++ jdk23u-jdk-23-36/src/java.base/share/native/libjli/jli_util.h 2024-08-17 19:50:33.102846820 +0200
9749 @@ -100,7 +100,11 @@
9750 #define JLI_StrCaseCmp(p1, p2) strcasecmp((p1), (p2))
9751 #define JLI_StrNCaseCmp(p1, p2, p3) strncasecmp((p1), (p2), (p3))
9752 #define JLI_Open open
9753 +#ifdef __solaris__
9754 +#define JLI_Lseek llseek
9755 +#else
9756 #define JLI_Lseek lseek
9757 +#endif
9758 #endif /* _WIN32 */
9761 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/share/native/libnet/net_util.c jdk23u-jdk-23-36/src/java.base/share/native/libnet/net_util.c
9762 --- jdk23u-jdk-23-36.orig/src/java.base/share/native/libnet/net_util.c 2024-08-07 00:08:22.000000000 +0200
9763 +++ jdk23u-jdk-23-36/src/java.base/share/native/libnet/net_util.c 2024-08-17 19:50:33.103287637 +0200
9764 @@ -81,6 +81,7 @@
9766 /* check if SO_REUSEPORT is supported on this platform */
9767 REUSEPORT_available = reuseport_supported(IPv6_available);
9768 + parseExclusiveBindProperty(env);
9770 return JNI_VERSION_1_2;
9772 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/share/native/libnet/net_util.h jdk23u-jdk-23-36/src/java.base/share/native/libnet/net_util.h
9773 --- jdk23u-jdk-23-36.orig/src/java.base/share/native/libnet/net_util.h 2024-08-07 00:08:22.000000000 +0200
9774 +++ jdk23u-jdk-23-36/src/java.base/share/native/libnet/net_util.h 2024-08-17 19:50:33.103611071 +0200
9775 @@ -142,6 +142,8 @@
9776 JNIEXPORT jobject JNICALL
9777 NET_SockaddrToInetAddress(JNIEnv *env, SOCKETADDRESS *sa, int *port);
9779 +void parseExclusiveBindProperty(JNIEnv *env);
9781 JNIEXPORT jint JNICALL NET_GetPortFromSockaddr(SOCKETADDRESS *sa);
9783 JNIEXPORT jboolean JNICALL
9784 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/solaris/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java jdk23u-jdk-23-36/src/java.base/solaris/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java
9785 --- jdk23u-jdk-23-36.orig/src/java.base/solaris/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java 1970-01-01 01:00:00.000000000 +0100
9786 +++ jdk23u-jdk-23-36/src/java.base/solaris/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java 2024-08-17 19:50:33.151677109 +0200
9787 @@ -0,0 +1,47 @@
9789 + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
9790 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
9792 + * This code is free software; you can redistribute it and/or modify it
9793 + * under the terms of the GNU General Public License version 2 only, as
9794 + * published by the Free Software Foundation. Oracle designates this
9795 + * particular file as subject to the "Classpath" exception as provided
9796 + * by Oracle in the LICENSE file that accompanied this code.
9798 + * This code is distributed in the hope that it will be useful, but WITHOUT
9799 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
9800 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
9801 + * version 2 for more details (a copy is included in the LICENSE file that
9802 + * accompanied this code).
9804 + * You should have received a copy of the GNU General Public License version
9805 + * 2 along with this work; if not, write to the Free Software Foundation,
9806 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
9808 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
9809 + * or visit www.oracle.com if you need additional information or have any
9810 + * questions.
9811 + */
9813 +package sun.nio.ch;
9815 +import java.nio.channels.spi.AsynchronousChannelProvider;
9817 +/**
9818 + * Creates this platform's default AsynchronousChannelProvider
9819 + */
9821 +public class DefaultAsynchronousChannelProvider {
9823 + /**
9824 + * Prevent instantiation.
9825 + */
9826 + private DefaultAsynchronousChannelProvider() { }
9828 + /**
9829 + * Returns the default AsynchronousChannelProvider.
9830 + */
9831 + public static AsynchronousChannelProvider create() {
9832 + return new SolarisAsynchronousChannelProvider();
9835 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/solaris/classes/sun/nio/ch/DefaultSelectorProvider.java jdk23u-jdk-23-36/src/java.base/solaris/classes/sun/nio/ch/DefaultSelectorProvider.java
9836 --- jdk23u-jdk-23-36.orig/src/java.base/solaris/classes/sun/nio/ch/DefaultSelectorProvider.java 1970-01-01 01:00:00.000000000 +0100
9837 +++ jdk23u-jdk-23-36/src/java.base/solaris/classes/sun/nio/ch/DefaultSelectorProvider.java 2024-08-17 19:50:33.151978378 +0200
9838 @@ -0,0 +1,54 @@
9840 + * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
9841 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
9843 + * This code is free software; you can redistribute it and/or modify it
9844 + * under the terms of the GNU General Public License version 2 only, as
9845 + * published by the Free Software Foundation. Oracle designates this
9846 + * particular file as subject to the "Classpath" exception as provided
9847 + * by Oracle in the LICENSE file that accompanied this code.
9849 + * This code is distributed in the hope that it will be useful, but WITHOUT
9850 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
9851 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
9852 + * version 2 for more details (a copy is included in the LICENSE file that
9853 + * accompanied this code).
9855 + * You should have received a copy of the GNU General Public License version
9856 + * 2 along with this work; if not, write to the Free Software Foundation,
9857 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
9859 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
9860 + * or visit www.oracle.com if you need additional information or have any
9861 + * questions.
9862 + */
9864 +package sun.nio.ch;
9866 +import java.security.AccessController;
9867 +import java.security.PrivilegedAction;
9869 +/**
9870 + * Creates this platform's default SelectorProvider
9871 + */
9873 +@SuppressWarnings("removal")
9874 +public class DefaultSelectorProvider {
9875 + private static final SelectorProviderImpl INSTANCE;
9876 + static {
9877 + PrivilegedAction<SelectorProviderImpl> pa = DevPollSelectorProvider::new;
9878 + INSTANCE = AccessController.doPrivileged(pa);
9881 + /**
9882 + * Prevent instantiation.
9883 + */
9884 + private DefaultSelectorProvider() { }
9886 + /**
9887 + * Returns the default SelectorProvider implementation.
9888 + */
9889 + public static SelectorProviderImpl get() {
9890 + return INSTANCE;
9893 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java jdk23u-jdk-23-36/src/java.base/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java
9894 --- jdk23u-jdk-23-36.orig/src/java.base/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java 1970-01-01 01:00:00.000000000 +0100
9895 +++ jdk23u-jdk-23-36/src/java.base/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java 2024-08-17 19:50:33.152277983 +0200
9896 @@ -0,0 +1,127 @@
9898 + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
9899 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
9901 + * This code is free software; you can redistribute it and/or modify it
9902 + * under the terms of the GNU General Public License version 2 only, as
9903 + * published by the Free Software Foundation. Oracle designates this
9904 + * particular file as subject to the "Classpath" exception as provided
9905 + * by Oracle in the LICENSE file that accompanied this code.
9907 + * This code is distributed in the hope that it will be useful, but WITHOUT
9908 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
9909 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
9910 + * version 2 for more details (a copy is included in the LICENSE file that
9911 + * accompanied this code).
9913 + * You should have received a copy of the GNU General Public License version
9914 + * 2 along with this work; if not, write to the Free Software Foundation,
9915 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
9917 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
9918 + * or visit www.oracle.com if you need additional information or have any
9919 + * questions.
9920 + */
9922 +package sun.nio.ch;
9924 +import java.io.IOException;
9926 +/**
9927 + * Manipulates a native array of pollfd structs on Solaris:
9929 + * typedef struct pollfd {
9930 + * int fd;
9931 + * short events;
9932 + * short revents;
9933 + * } pollfd_t;
9935 + * @author Mike McCloskey
9936 + * @since 1.4
9937 + */
9939 +class DevPollArrayWrapper {
9941 + // special event to remove a file descriptor from the driver
9942 + static final short POLLREMOVE = 0x0800;
9944 + // struct pollfd constants
9945 + static final short SIZE_POLLFD = 8;
9946 + static final short FD_OFFSET = 0;
9947 + static final short EVENT_OFFSET = 4;
9948 + static final short REVENT_OFFSET = 6;
9950 + // maximum number of pollfd structure to poll or update at a time
9951 + // dpwrite/ioctl(DP_POLL) allows up to file descriptor limit minus 1
9952 + static final int NUM_POLLFDS = Math.min(IOUtil.fdLimit()-1, 1024);
9954 + // The pollfd array for results from devpoll driver
9955 + private final AllocatedNativeObject pollArray;
9957 + // Base address of the native pollArray
9958 + private final long pollArrayAddress;
9960 + // The fd of the devpoll driver
9961 + private int wfd;
9963 + DevPollArrayWrapper() throws IOException {
9964 + this.wfd = init();
9966 + int allocationSize = NUM_POLLFDS * SIZE_POLLFD;
9967 + this.pollArray = new AllocatedNativeObject(allocationSize, true);
9968 + this.pollArrayAddress = pollArray.address();
9971 + void close() throws IOException {
9972 + FileDispatcherImpl.closeIntFD(wfd);
9973 + pollArray.free();
9976 + void register(int fd, int ops) throws IOException {
9977 + register(wfd, fd, ops);
9980 + void registerMultiple(int numfds) throws IOException {
9981 + registerMultiple(wfd, pollArrayAddress, numfds);
9984 + int poll(long timeout) throws IOException {
9985 + return poll0(pollArrayAddress, NUM_POLLFDS, timeout, wfd);
9988 + int getDescriptor(int i) {
9989 + int offset = SIZE_POLLFD * i + FD_OFFSET;
9990 + return pollArray.getInt(offset);
9993 + short getEventOps(int i) {
9994 + int offset = SIZE_POLLFD * i + EVENT_OFFSET;
9995 + return pollArray.getShort(offset);
9998 + short getReventOps(int i) {
9999 + int offset = SIZE_POLLFD * i + REVENT_OFFSET;
10000 + return pollArray.getShort(offset);
10003 + /**
10004 + * Updates the pollfd structure at the given index
10005 + */
10006 + void putPollFD(int index, int fd, short event) {
10007 + int structIndex = SIZE_POLLFD * index;
10008 + pollArray.putInt(structIndex + FD_OFFSET, fd);
10009 + pollArray.putShort(structIndex + EVENT_OFFSET, event);
10010 + pollArray.putShort(structIndex + REVENT_OFFSET, (short)0);
10013 + private native int init() throws IOException;
10014 + private native void register(int wfd, int fd, int mask) throws IOException;
10015 + private native void registerMultiple(int wfd, long address, int len)
10016 + throws IOException;
10017 + private native int poll0(long pollAddress, int numfds, long timeout, int wfd)
10018 + throws IOException;
10020 + static {
10021 + IOUtil.load();
10024 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java jdk23u-jdk-23-36/src/java.base/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java
10025 --- jdk23u-jdk-23-36.orig/src/java.base/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java 1970-01-01 01:00:00.000000000 +0100
10026 +++ jdk23u-jdk-23-36/src/java.base/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java 2024-08-17 19:50:33.152630883 +0200
10027 @@ -0,0 +1,263 @@
10029 + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
10030 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
10032 + * This code is free software; you can redistribute it and/or modify it
10033 + * under the terms of the GNU General Public License version 2 only, as
10034 + * published by the Free Software Foundation. Oracle designates this
10035 + * particular file as subject to the "Classpath" exception as provided
10036 + * by Oracle in the LICENSE file that accompanied this code.
10038 + * This code is distributed in the hope that it will be useful, but WITHOUT
10039 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10040 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
10041 + * version 2 for more details (a copy is included in the LICENSE file that
10042 + * accompanied this code).
10044 + * You should have received a copy of the GNU General Public License version
10045 + * 2 along with this work; if not, write to the Free Software Foundation,
10046 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
10048 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
10049 + * or visit www.oracle.com if you need additional information or have any
10050 + * questions.
10051 + */
10053 +package sun.nio.ch;
10055 +import java.io.IOException;
10056 +import java.nio.channels.ClosedSelectorException;
10057 +import java.nio.channels.SelectionKey;
10058 +import java.nio.channels.Selector;
10059 +import java.nio.channels.spi.SelectorProvider;
10060 +import java.util.ArrayDeque;
10061 +import java.util.Deque;
10062 +import java.util.HashMap;
10063 +import java.util.Map;
10064 +import java.util.concurrent.TimeUnit;
10065 +import java.util.function.Consumer;
10067 +import static sun.nio.ch.DevPollArrayWrapper.NUM_POLLFDS;
10068 +import static sun.nio.ch.DevPollArrayWrapper.POLLREMOVE;
10070 +/**
10071 + * Solaris /dev/poll based Selector implementation
10072 + */
10074 +class DevPollSelectorImpl
10075 + extends SelectorImpl
10077 + // provides access to /dev/poll driver
10078 + private final DevPollArrayWrapper pollWrapper;
10080 + // file descriptors used for interrupt
10081 + private final int fd0;
10082 + private final int fd1;
10084 + // maps file descriptor to selection key, synchronize on selector
10085 + private final Map<Integer, SelectionKeyImpl> fdToKey = new HashMap<>();
10087 + // pending new registrations/updates, queued by setEventOps
10088 + private final Object updateLock = new Object();
10089 + private final Deque<SelectionKeyImpl> updateKeys = new ArrayDeque<>();
10091 + // interrupt triggering and clearing
10092 + private final Object interruptLock = new Object();
10093 + private boolean interruptTriggered;
10095 + DevPollSelectorImpl(SelectorProvider sp) throws IOException {
10096 + super(sp);
10097 + this.pollWrapper = new DevPollArrayWrapper();
10098 + try {
10099 + long fds = IOUtil.makePipe(false);
10100 + this.fd0 = (int) (fds >>> 32);
10101 + this.fd1 = (int) fds;
10102 + } catch (IOException ioe) {
10103 + pollWrapper.close();
10104 + throw ioe;
10107 + // register one end of the socket pair for wakeups
10108 + pollWrapper.register(fd0, Net.POLLIN);
10111 + private void ensureOpen() {
10112 + if (!isOpen())
10113 + throw new ClosedSelectorException();
10116 + @Override
10117 + protected int doSelect(Consumer<SelectionKey> action, long timeout)
10118 + throws IOException
10120 + assert Thread.holdsLock(this);
10122 + long to = timeout;
10123 + boolean blocking = (to != 0);
10124 + boolean timedPoll = (to > 0);
10126 + int numEntries;
10127 + processUpdateQueue();
10128 + processDeregisterQueue();
10129 + try {
10130 + begin(blocking);
10132 + do {
10133 + long startTime = timedPoll ? System.nanoTime() : 0;
10134 + numEntries = pollWrapper.poll(to);
10135 + if (numEntries == IOStatus.INTERRUPTED && timedPoll) {
10136 + // timed poll interrupted so need to adjust timeout
10137 + long adjust = System.nanoTime() - startTime;
10138 + to -= TimeUnit.MILLISECONDS.convert(adjust, TimeUnit.NANOSECONDS);
10139 + if (to <= 0) {
10140 + // timeout expired so no retry
10141 + numEntries = 0;
10144 + } while (numEntries == IOStatus.INTERRUPTED);
10145 + assert IOStatus.check(numEntries);
10147 + } finally {
10148 + end(blocking);
10150 + processDeregisterQueue();
10151 + return processEvents(numEntries, action);
10154 + /**
10155 + * Process changes to the interest ops.
10156 + */
10157 + private void processUpdateQueue() throws IOException {
10158 + assert Thread.holdsLock(this);
10160 + synchronized (updateLock) {
10161 + SelectionKeyImpl ski;
10163 + // Translate the queued updates to changes to the set of monitored
10164 + // file descriptors. The changes are written to the /dev/poll driver
10165 + // in bulk.
10166 + int index = 0;
10167 + while ((ski = updateKeys.pollFirst()) != null) {
10168 + if (ski.isValid()) {
10169 + int fd = ski.getFDVal();
10170 + // add to fdToKey if needed
10171 + SelectionKeyImpl previous = fdToKey.putIfAbsent(fd, ski);
10172 + assert (previous == null) || (previous == ski);
10174 + int newEvents = ski.translateInterestOps();
10175 + int registeredEvents = ski.registeredEvents();
10176 + if (newEvents != registeredEvents) {
10177 + if (registeredEvents != 0)
10178 + pollWrapper.putPollFD(index++, fd, POLLREMOVE);
10179 + if (newEvents != 0)
10180 + pollWrapper.putPollFD(index++, fd, (short)newEvents);
10181 + ski.registeredEvents(newEvents);
10183 + // write to /dev/poll
10184 + if (index > (NUM_POLLFDS-2)) {
10185 + pollWrapper.registerMultiple(index);
10186 + index = 0;
10192 + // write any remaining changes
10193 + if (index > 0)
10194 + pollWrapper.registerMultiple(index);
10198 + /**
10199 + * Process the polled events.
10200 + * If the interrupt fd has been selected, drain it and clear the interrupt.
10201 + */
10202 + private int processEvents(int numEntries, Consumer<SelectionKey> action)
10203 + throws IOException
10205 + assert Thread.holdsLock(this);
10207 + boolean interrupted = false;
10208 + int numKeysUpdated = 0;
10209 + for (int i=0; i<numEntries; i++) {
10210 + int fd = pollWrapper.getDescriptor(i);
10211 + if (fd == fd0) {
10212 + interrupted = true;
10213 + } else {
10214 + SelectionKeyImpl ski = fdToKey.get(fd);
10215 + if (ski != null) {
10216 + int rOps = pollWrapper.getReventOps(i);
10217 + numKeysUpdated += processReadyEvents(rOps, ski, action);
10222 + if (interrupted) {
10223 + clearInterrupt();
10226 + return numKeysUpdated;
10229 + @Override
10230 + protected void implClose() throws IOException {
10231 + assert !isOpen();
10232 + assert Thread.holdsLock(this);
10234 + // prevent further wakeup
10235 + synchronized (interruptLock) {
10236 + interruptTriggered = true;
10239 + pollWrapper.close();
10240 + FileDispatcherImpl.closeIntFD(fd0);
10241 + FileDispatcherImpl.closeIntFD(fd1);
10245 + @Override
10246 + protected void implDereg(SelectionKeyImpl ski) throws IOException {
10247 + assert !ski.isValid();
10248 + assert Thread.holdsLock(this);
10250 + int fd = ski.getFDVal();
10251 + if (fdToKey.remove(fd) != null) {
10252 + if (ski.registeredEvents() != 0) {
10253 + pollWrapper.register(fd, POLLREMOVE);
10254 + ski.registeredEvents(0);
10256 + } else {
10257 + assert ski.registeredEvents() == 0;
10261 + @Override
10262 + public void setEventOps(SelectionKeyImpl ski) {
10263 + ensureOpen();
10264 + synchronized (updateLock) {
10265 + updateKeys.addLast(ski);
10269 + @Override
10270 + public Selector wakeup() {
10271 + synchronized (interruptLock) {
10272 + if (!interruptTriggered) {
10273 + try {
10274 + IOUtil.write1(fd1, (byte)0);
10275 + } catch (IOException ioe) {
10276 + throw new InternalError(ioe);
10278 + interruptTriggered = true;
10281 + return this;
10284 + private void clearInterrupt() throws IOException {
10285 + synchronized (interruptLock) {
10286 + IOUtil.drain(fd0);
10287 + interruptTriggered = false;
10291 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/solaris/classes/sun/nio/ch/DevPollSelectorProvider.java jdk23u-jdk-23-36/src/java.base/solaris/classes/sun/nio/ch/DevPollSelectorProvider.java
10292 --- jdk23u-jdk-23-36.orig/src/java.base/solaris/classes/sun/nio/ch/DevPollSelectorProvider.java 1970-01-01 01:00:00.000000000 +0100
10293 +++ jdk23u-jdk-23-36/src/java.base/solaris/classes/sun/nio/ch/DevPollSelectorProvider.java 2024-08-17 19:50:33.152893624 +0200
10294 @@ -0,0 +1,42 @@
10296 + * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
10297 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
10299 + * This code is free software; you can redistribute it and/or modify it
10300 + * under the terms of the GNU General Public License version 2 only, as
10301 + * published by the Free Software Foundation. Oracle designates this
10302 + * particular file as subject to the "Classpath" exception as provided
10303 + * by Oracle in the LICENSE file that accompanied this code.
10305 + * This code is distributed in the hope that it will be useful, but WITHOUT
10306 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10307 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
10308 + * version 2 for more details (a copy is included in the LICENSE file that
10309 + * accompanied this code).
10311 + * You should have received a copy of the GNU General Public License version
10312 + * 2 along with this work; if not, write to the Free Software Foundation,
10313 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
10315 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
10316 + * or visit www.oracle.com if you need additional information or have any
10317 + * questions.
10318 + */
10320 +package sun.nio.ch;
10322 +import java.io.IOException;
10323 +import java.nio.channels.*;
10324 +import java.nio.channels.spi.*;
10326 +public class DevPollSelectorProvider
10327 + extends SelectorProviderImpl
10329 + public AbstractSelector openSelector() throws IOException {
10330 + return new DevPollSelectorImpl(this);
10333 + public Channel inheritedChannel() throws IOException {
10334 + return InheritedChannel.getChannel();
10337 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/solaris/classes/sun/nio/ch/EventPortSelectorImpl.java jdk23u-jdk-23-36/src/java.base/solaris/classes/sun/nio/ch/EventPortSelectorImpl.java
10338 --- jdk23u-jdk-23-36.orig/src/java.base/solaris/classes/sun/nio/ch/EventPortSelectorImpl.java 1970-01-01 01:00:00.000000000 +0100
10339 +++ jdk23u-jdk-23-36/src/java.base/solaris/classes/sun/nio/ch/EventPortSelectorImpl.java 2024-08-17 19:50:33.153278350 +0200
10340 @@ -0,0 +1,308 @@
10342 + * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
10343 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
10345 + * This code is free software; you can redistribute it and/or modify it
10346 + * under the terms of the GNU General Public License version 2 only, as
10347 + * published by the Free Software Foundation. Oracle designates this
10348 + * particular file as subject to the "Classpath" exception as provided
10349 + * by Oracle in the LICENSE file that accompanied this code.
10351 + * This code is distributed in the hope that it will be useful, but WITHOUT
10352 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10353 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
10354 + * version 2 for more details (a copy is included in the LICENSE file that
10355 + * accompanied this code).
10357 + * You should have received a copy of the GNU General Public License version
10358 + * 2 along with this work; if not, write to the Free Software Foundation,
10359 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
10361 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
10362 + * or visit www.oracle.com if you need additional information or have any
10363 + * questions.
10364 + */
10366 +package sun.nio.ch;
10368 +import java.io.IOException;
10369 +import java.nio.channels.ClosedSelectorException;
10370 +import java.nio.channels.SelectionKey;
10371 +import java.nio.channels.Selector;
10372 +import java.nio.channels.spi.SelectorProvider;
10373 +import java.util.ArrayDeque;
10374 +import java.util.Deque;
10375 +import java.util.HashMap;
10376 +import java.util.Map;
10377 +import java.util.concurrent.TimeUnit;
10378 +import java.util.function.Consumer;
10380 +import static sun.nio.ch.SolarisEventPort.PORT_SOURCE_FD;
10381 +import static sun.nio.ch.SolarisEventPort.PORT_SOURCE_USER;
10382 +import static sun.nio.ch.SolarisEventPort.SIZEOF_PORT_EVENT;
10383 +import static sun.nio.ch.SolarisEventPort.OFFSETOF_EVENTS;
10384 +import static sun.nio.ch.SolarisEventPort.OFFSETOF_SOURCE;
10385 +import static sun.nio.ch.SolarisEventPort.OFFSETOF_OBJECT;
10386 +import static sun.nio.ch.SolarisEventPort.port_create;
10387 +import static sun.nio.ch.SolarisEventPort.port_close;
10388 +import static sun.nio.ch.SolarisEventPort.port_associate;
10389 +import static sun.nio.ch.SolarisEventPort.port_dissociate;
10390 +import static sun.nio.ch.SolarisEventPort.port_getn;
10391 +import static sun.nio.ch.SolarisEventPort.port_send;
10393 +/**
10394 + * Selector implementation based on the Solaris event port mechanism.
10395 + */
10397 +class EventPortSelectorImpl
10398 + extends SelectorImpl
10400 + // maximum number of events to retrive in one call to port_getn
10401 + static final int MAX_EVENTS = Math.min(IOUtil.fdLimit()-1, 1024);
10403 + // port file descriptor
10404 + private final int pfd;
10406 + // the poll array (populated by port_getn)
10407 + private final long pollArrayAddress;
10408 + private final AllocatedNativeObject pollArray;
10410 + // maps file descriptor to selection key, synchronize on selector
10411 + private final Map<Integer, SelectionKeyImpl> fdToKey = new HashMap<>();
10413 + // the last update operation, incremented by processUpdateQueue
10414 + private int lastUpdate;
10416 + // pending new registrations/updates, queued by setEventOps and
10417 + // updateSelectedKeys
10418 + private final Object updateLock = new Object();
10419 + private final Deque<SelectionKeyImpl> updateKeys = new ArrayDeque<>();
10421 + // interrupt triggering and clearing
10422 + private final Object interruptLock = new Object();
10423 + private boolean interruptTriggered;
10425 + EventPortSelectorImpl(SelectorProvider sp) throws IOException {
10426 + super(sp);
10428 + this.pfd = port_create();
10430 + int allocationSize = MAX_EVENTS * SIZEOF_PORT_EVENT;
10431 + this.pollArray = new AllocatedNativeObject(allocationSize, false);
10432 + this.pollArrayAddress = pollArray.address();
10435 + private void ensureOpen() {
10436 + if (!isOpen())
10437 + throw new ClosedSelectorException();
10440 + @Override
10441 + protected int doSelect(Consumer<SelectionKey> action, long timeout)
10442 + throws IOException
10444 + assert Thread.holdsLock(this);
10446 + long to = timeout;
10447 + boolean blocking = (to != 0);
10448 + boolean timedPoll = (to > 0);
10450 + int numEvents;
10451 + processUpdateQueue();
10452 + processDeregisterQueue();
10453 + try {
10454 + begin(blocking);
10456 + do {
10457 + long startTime = timedPoll ? System.nanoTime() : 0;
10458 + numEvents = port_getn(pfd, pollArrayAddress, MAX_EVENTS, to);
10459 + if (numEvents == IOStatus.INTERRUPTED && timedPoll) {
10460 + // timed poll interrupted so need to adjust timeout
10461 + long adjust = System.nanoTime() - startTime;
10462 + to -= TimeUnit.MILLISECONDS.convert(adjust, TimeUnit.NANOSECONDS);
10463 + if (to <= 0) {
10464 + // timeout also expired so no retry
10465 + numEvents = 0;
10468 + } while (numEvents == IOStatus.INTERRUPTED);
10469 + assert IOStatus.check(numEvents);
10471 + } finally {
10472 + end(blocking);
10474 + processDeregisterQueue();
10475 + return processPortEvents(numEvents, action);
10478 + /**
10479 + * Process new registrations and changes to the interest ops.
10480 + */
10481 + private void processUpdateQueue() throws IOException {
10482 + assert Thread.holdsLock(this);
10484 + // bump lastUpdate to ensure that the interest ops are changed at most
10485 + // once per bulk update
10486 + lastUpdate++;
10488 + synchronized (updateLock) {
10489 + SelectionKeyImpl ski;
10490 + while ((ski = updateKeys.pollFirst()) != null) {
10491 + if (ski.isValid()) {
10492 + int fd = ski.getFDVal();
10493 + // add to fdToKey if needed
10494 + SelectionKeyImpl previous = fdToKey.putIfAbsent(fd, ski);
10495 + assert (previous == null) || (previous == ski);
10497 + int newEvents = ski.translateInterestOps();
10498 + if (newEvents != ski.registeredEvents()) {
10499 + if (newEvents == 0) {
10500 + port_dissociate(pfd, PORT_SOURCE_FD, fd);
10501 + } else {
10502 + port_associate(pfd, PORT_SOURCE_FD, fd, newEvents);
10504 + ski.registeredEvents(newEvents);
10511 + /**
10512 + * Process the polled events and re-queue the selected keys so the file
10513 + * descriptors are re-associated at the next select operation.
10514 + */
10515 + private int processPortEvents(int numEvents, Consumer<SelectionKey> action)
10516 + throws IOException
10518 + assert Thread.holdsLock(this);
10520 + int numKeysUpdated = 0;
10521 + boolean interrupted = false;
10523 + // Process the polled events while holding the update lock. This allows
10524 + // keys to be queued for ready file descriptors so they can be
10525 + // re-associated at the next select. The selected-key can be updated
10526 + // in this pass.
10527 + synchronized (updateLock) {
10528 + for (int i = 0; i < numEvents; i++) {
10529 + short source = getSource(i);
10530 + if (source == PORT_SOURCE_FD) {
10531 + int fd = getDescriptor(i);
10532 + SelectionKeyImpl ski = fdToKey.get(fd);
10533 + if (ski != null) {
10534 + ski.registeredEvents(0);
10535 + updateKeys.addLast(ski);
10537 + // update selected-key set if no action specified
10538 + if (action == null) {
10539 + int rOps = getEventOps(i);
10540 + numKeysUpdated += processReadyEvents(rOps, ski, null);
10544 + } else if (source == PORT_SOURCE_USER) {
10545 + interrupted = true;
10546 + } else {
10547 + assert false;
10552 + // if an action specified then iterate over the polled events again so
10553 + // that the action is performed without holding the update lock.
10554 + if (action != null) {
10555 + for (int i = 0; i < numEvents; i++) {
10556 + short source = getSource(i);
10557 + if (source == PORT_SOURCE_FD) {
10558 + int fd = getDescriptor(i);
10559 + SelectionKeyImpl ski = fdToKey.get(fd);
10560 + if (ski != null) {
10561 + int rOps = getEventOps(i);
10562 + numKeysUpdated += processReadyEvents(rOps, ski, action);
10568 + if (interrupted) {
10569 + clearInterrupt();
10571 + return numKeysUpdated;
10574 + @Override
10575 + protected void implClose() throws IOException {
10576 + assert !isOpen();
10577 + assert Thread.holdsLock(this);
10579 + // prevent further wakeup
10580 + synchronized (interruptLock) {
10581 + interruptTriggered = true;
10584 + port_close(pfd);
10585 + pollArray.free();
10588 + @Override
10589 + protected void implDereg(SelectionKeyImpl ski) throws IOException {
10590 + assert !ski.isValid();
10591 + assert Thread.holdsLock(this);
10593 + int fd = ski.getFDVal();
10594 + if (fdToKey.remove(fd) != null) {
10595 + if (ski.registeredEvents() != 0) {
10596 + port_dissociate(pfd, PORT_SOURCE_FD, fd);
10597 + ski.registeredEvents(0);
10599 + } else {
10600 + assert ski.registeredEvents() == 0;
10604 + @Override
10605 + public void setEventOps(SelectionKeyImpl ski) {
10606 + ensureOpen();
10607 + synchronized (updateLock) {
10608 + updateKeys.addLast(ski);
10612 + @Override
10613 + public Selector wakeup() {
10614 + synchronized (interruptLock) {
10615 + if (!interruptTriggered) {
10616 + try {
10617 + port_send(pfd, 0);
10618 + } catch (IOException ioe) {
10619 + throw new InternalError(ioe);
10621 + interruptTriggered = true;
10624 + return this;
10627 + private void clearInterrupt() throws IOException {
10628 + synchronized (interruptLock) {
10629 + interruptTriggered = false;
10633 + private short getSource(int i) {
10634 + int offset = SIZEOF_PORT_EVENT * i + OFFSETOF_SOURCE;
10635 + return pollArray.getShort(offset);
10638 + private int getEventOps(int i) {
10639 + int offset = SIZEOF_PORT_EVENT * i + OFFSETOF_EVENTS;
10640 + return pollArray.getInt(offset);
10643 + private int getDescriptor(int i) {
10644 + //assert Unsafe.getUnsafe().addressSize() == 8;
10645 + int offset = SIZEOF_PORT_EVENT * i + OFFSETOF_OBJECT;
10646 + return (int) pollArray.getLong(offset);
10649 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/solaris/classes/sun/nio/ch/EventPortSelectorProvider.java jdk23u-jdk-23-36/src/java.base/solaris/classes/sun/nio/ch/EventPortSelectorProvider.java
10650 --- jdk23u-jdk-23-36.orig/src/java.base/solaris/classes/sun/nio/ch/EventPortSelectorProvider.java 1970-01-01 01:00:00.000000000 +0100
10651 +++ jdk23u-jdk-23-36/src/java.base/solaris/classes/sun/nio/ch/EventPortSelectorProvider.java 2024-08-17 19:50:33.153553796 +0200
10652 @@ -0,0 +1,42 @@
10654 + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
10655 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
10657 + * This code is free software; you can redistribute it and/or modify it
10658 + * under the terms of the GNU General Public License version 2 only, as
10659 + * published by the Free Software Foundation. Oracle designates this
10660 + * particular file as subject to the "Classpath" exception as provided
10661 + * by Oracle in the LICENSE file that accompanied this code.
10663 + * This code is distributed in the hope that it will be useful, but WITHOUT
10664 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10665 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
10666 + * version 2 for more details (a copy is included in the LICENSE file that
10667 + * accompanied this code).
10669 + * You should have received a copy of the GNU General Public License version
10670 + * 2 along with this work; if not, write to the Free Software Foundation,
10671 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
10673 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
10674 + * or visit www.oracle.com if you need additional information or have any
10675 + * questions.
10676 + */
10678 +package sun.nio.ch;
10680 +import java.io.IOException;
10681 +import java.nio.channels.*;
10682 +import java.nio.channels.spi.*;
10684 +public class EventPortSelectorProvider
10685 + extends SelectorProviderImpl
10687 + public AbstractSelector openSelector() throws IOException {
10688 + return new EventPortSelectorImpl(this);
10691 + public Channel inheritedChannel() throws IOException {
10692 + return InheritedChannel.getChannel();
10695 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/solaris/classes/sun/nio/ch/SolarisAsynchronousChannelProvider.java jdk23u-jdk-23-36/src/java.base/solaris/classes/sun/nio/ch/SolarisAsynchronousChannelProvider.java
10696 --- jdk23u-jdk-23-36.orig/src/java.base/solaris/classes/sun/nio/ch/SolarisAsynchronousChannelProvider.java 1970-01-01 01:00:00.000000000 +0100
10697 +++ jdk23u-jdk-23-36/src/java.base/solaris/classes/sun/nio/ch/SolarisAsynchronousChannelProvider.java 2024-08-17 19:50:33.153878101 +0200
10698 @@ -0,0 +1,93 @@
10700 + * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
10701 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
10703 + * This code is free software; you can redistribute it and/or modify it
10704 + * under the terms of the GNU General Public License version 2 only, as
10705 + * published by the Free Software Foundation. Oracle designates this
10706 + * particular file as subject to the "Classpath" exception as provided
10707 + * by Oracle in the LICENSE file that accompanied this code.
10709 + * This code is distributed in the hope that it will be useful, but WITHOUT
10710 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10711 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
10712 + * version 2 for more details (a copy is included in the LICENSE file that
10713 + * accompanied this code).
10715 + * You should have received a copy of the GNU General Public License version
10716 + * 2 along with this work; if not, write to the Free Software Foundation,
10717 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
10719 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
10720 + * or visit www.oracle.com if you need additional information or have any
10721 + * questions.
10722 + */
10724 +package sun.nio.ch;
10726 +import java.nio.channels.*;
10727 +import java.nio.channels.spi.AsynchronousChannelProvider;
10728 +import java.util.concurrent.ExecutorService;
10729 +import java.util.concurrent.ThreadFactory;
10730 +import java.io.IOException;
10732 +public class SolarisAsynchronousChannelProvider
10733 + extends AsynchronousChannelProvider
10735 + private static volatile SolarisEventPort defaultEventPort;
10737 + private SolarisEventPort defaultEventPort() throws IOException {
10738 + if (defaultEventPort == null) {
10739 + synchronized (SolarisAsynchronousChannelProvider.class) {
10740 + if (defaultEventPort == null) {
10741 + defaultEventPort =
10742 + new SolarisEventPort(this, ThreadPool.getDefault()).start();
10746 + return defaultEventPort;
10749 + public SolarisAsynchronousChannelProvider() {
10752 + @Override
10753 + public AsynchronousChannelGroup openAsynchronousChannelGroup(int nThreads, ThreadFactory factory)
10754 + throws IOException
10756 + return new SolarisEventPort(this, ThreadPool.create(nThreads, factory)).start();
10759 + @Override
10760 + public AsynchronousChannelGroup openAsynchronousChannelGroup(ExecutorService executor, int initialSize)
10761 + throws IOException
10763 + return new SolarisEventPort(this, ThreadPool.wrap(executor, initialSize)).start();
10766 + private SolarisEventPort toEventPort(AsynchronousChannelGroup group)
10767 + throws IOException
10769 + if (group == null) {
10770 + return defaultEventPort();
10771 + } else {
10772 + if (!(group instanceof SolarisEventPort))
10773 + throw new IllegalChannelGroupException();
10774 + return (SolarisEventPort)group;
10778 + @Override
10779 + public AsynchronousServerSocketChannel openAsynchronousServerSocketChannel(AsynchronousChannelGroup group)
10780 + throws IOException
10782 + return new UnixAsynchronousServerSocketChannelImpl(toEventPort(group));
10785 + @Override
10786 + public AsynchronousSocketChannel openAsynchronousSocketChannel(AsynchronousChannelGroup group)
10787 + throws IOException
10789 + return new UnixAsynchronousSocketChannelImpl(toEventPort(group));
10792 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/solaris/classes/sun/nio/ch/SolarisEventPort.java jdk23u-jdk-23-36/src/java.base/solaris/classes/sun/nio/ch/SolarisEventPort.java
10793 --- jdk23u-jdk-23-36.orig/src/java.base/solaris/classes/sun/nio/ch/SolarisEventPort.java 1970-01-01 01:00:00.000000000 +0100
10794 +++ jdk23u-jdk-23-36/src/java.base/solaris/classes/sun/nio/ch/SolarisEventPort.java 2024-08-17 19:50:33.154267489 +0200
10795 @@ -0,0 +1,273 @@
10797 + * Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved.
10798 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
10800 + * This code is free software; you can redistribute it and/or modify it
10801 + * under the terms of the GNU General Public License version 2 only, as
10802 + * published by the Free Software Foundation. Oracle designates this
10803 + * particular file as subject to the "Classpath" exception as provided
10804 + * by Oracle in the LICENSE file that accompanied this code.
10806 + * This code is distributed in the hope that it will be useful, but WITHOUT
10807 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10808 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
10809 + * version 2 for more details (a copy is included in the LICENSE file that
10810 + * accompanied this code).
10812 + * You should have received a copy of the GNU General Public License version
10813 + * 2 along with this work; if not, write to the Free Software Foundation,
10814 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
10816 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
10817 + * or visit www.oracle.com if you need additional information or have any
10818 + * questions.
10819 + */
10821 +package sun.nio.ch;
10823 +import java.nio.channels.spi.AsynchronousChannelProvider;
10824 +import java.util.concurrent.RejectedExecutionException;
10825 +import java.io.IOException;
10826 +import jdk.internal.misc.Unsafe;
10828 +/**
10829 + * Provides an AsynchronousChannelGroup implementation based on the Solaris 10
10830 + * event port framework and also provides direct access to that framework.
10831 + */
10833 +class SolarisEventPort
10834 + extends Port
10836 + private static final Unsafe unsafe = Unsafe.getUnsafe();
10837 + private static final int addressSize = unsafe.addressSize();
10839 + private static int dependsArch(int value32, int value64) {
10840 + return (addressSize == 4) ? value32 : value64;
10843 + /*
10844 + * typedef struct port_event {
10845 + * int portev_events;
10846 + * ushort_t portev_source;
10847 + * ushort_t portev_pad;
10848 + * uintptr_t portev_object;
10849 + * void *portev_user;
10850 + * } port_event_t;
10851 + */
10852 + static final int SIZEOF_PORT_EVENT = dependsArch(16, 24);
10853 + static final int OFFSETOF_EVENTS = 0;
10854 + static final int OFFSETOF_SOURCE = 4;
10855 + static final int OFFSETOF_OBJECT = 8;
10857 + // port sources
10858 + static final short PORT_SOURCE_USER = 3;
10859 + static final short PORT_SOURCE_FD = 4;
10861 + // events (sys/poll.h)
10862 + static final int POLLIN = 0x0001;
10863 + static final int POLLOUT = 0x0004;
10865 + // file descriptor to event port.
10866 + private final int port;
10868 + // true when port is closed
10869 + private boolean closed;
10871 + SolarisEventPort(AsynchronousChannelProvider provider, ThreadPool pool)
10872 + throws IOException
10874 + super(provider, pool);
10876 + // create event port
10877 + this.port = port_create();
10880 + SolarisEventPort start() {
10881 + startThreads(new EventHandlerTask());
10882 + return this;
10885 + // releass resources
10886 + private void implClose() {
10887 + synchronized (this) {
10888 + if (closed)
10889 + return;
10890 + closed = true;
10892 + port_close(port);
10895 + private void wakeup() {
10896 + try {
10897 + port_send(port, 0);
10898 + } catch (IOException x) {
10899 + throw new AssertionError(x);
10903 + @Override
10904 + void executeOnHandlerTask(Runnable task) {
10905 + synchronized (this) {
10906 + if (closed)
10907 + throw new RejectedExecutionException();
10908 + offerTask(task);
10909 + wakeup();
10913 + @Override
10914 + void shutdownHandlerTasks() {
10915 + /*
10916 + * If no tasks are running then just release resources; otherwise
10917 + * write to the one end of the socketpair to wakeup any polling threads..
10918 + */
10919 + int nThreads = threadCount();
10920 + if (nThreads == 0) {
10921 + implClose();
10922 + } else {
10923 + // send user event to wakeup each thread
10924 + while (nThreads-- > 0) {
10925 + try {
10926 + port_send(port, 0);
10927 + } catch (IOException x) {
10928 + throw new AssertionError(x);
10934 + @Override
10935 + void startPoll(int fd, int events) {
10936 + // (re-)associate file descriptor
10937 + // no need to translate events
10938 + try {
10939 + port_associate(port, PORT_SOURCE_FD, fd, events);
10940 + } catch (IOException x) {
10941 + throw new AssertionError(); // should not happen
10945 + /*
10946 + * Task to read a single event from the port and dispatch it to the
10947 + * channel's onEvent handler.
10948 + */
10949 + private class EventHandlerTask implements Runnable {
10950 + public void run() {
10951 + Invoker.GroupAndInvokeCount myGroupAndInvokeCount =
10952 + Invoker.getGroupAndInvokeCount();
10953 + final boolean isPooledThread = (myGroupAndInvokeCount != null);
10954 + boolean replaceMe = false;
10955 + long address = unsafe.allocateMemory(SIZEOF_PORT_EVENT);
10956 + try {
10957 + for (;;) {
10958 + // reset invoke count
10959 + if (isPooledThread)
10960 + myGroupAndInvokeCount.resetInvokeCount();
10962 + // wait for I/O completion event
10963 + // A error here is fatal (thread will not be replaced)
10964 + replaceMe = false;
10965 + try {
10966 + int n;
10967 + do {
10968 + n = port_get(port, address);
10969 + } while (n == IOStatus.INTERRUPTED);
10970 + } catch (IOException x) {
10971 + x.printStackTrace();
10972 + return;
10975 + // event source
10976 + short source = unsafe.getShort(address + OFFSETOF_SOURCE);
10977 + if (source != PORT_SOURCE_FD) {
10978 + // user event is trigger to invoke task or shutdown
10979 + if (source == PORT_SOURCE_USER) {
10980 + Runnable task = pollTask();
10981 + if (task == null) {
10982 + // shutdown request
10983 + return;
10985 + // run task (may throw error/exception)
10986 + replaceMe = true;
10987 + task.run();
10989 + // ignore
10990 + continue;
10993 + // pe->portev_object is file descriptor
10994 + int fd = (int)unsafe.getAddress(address + OFFSETOF_OBJECT);
10995 + // pe->portev_events
10996 + int events = unsafe.getInt(address + OFFSETOF_EVENTS);
10998 + // lookup channel
10999 + PollableChannel ch;
11000 + fdToChannelLock.readLock().lock();
11001 + try {
11002 + ch = fdToChannel.get(fd);
11003 + } finally {
11004 + fdToChannelLock.readLock().unlock();
11007 + // notify channel
11008 + if (ch != null) {
11009 + replaceMe = true;
11010 + // no need to translate events
11011 + ch.onEvent(events, isPooledThread);
11014 + } finally {
11015 + // free per-thread resources
11016 + unsafe.freeMemory(address);
11017 + // last task to exit when shutdown release resources
11018 + int remaining = threadExit(this, replaceMe);
11019 + if (remaining == 0 && isShutdown())
11020 + implClose();
11025 + /**
11026 + * Creates an event port
11027 + */
11028 + static native int port_create() throws IOException;
11030 + /**
11031 + * Associates specific events of a given object with a port
11032 + */
11033 + static native boolean port_associate(int port, int source, long object, int events)
11034 + throws IOException;
11036 + /**
11037 + * Removes the association of an object with a port.
11038 + */
11039 + static native boolean port_dissociate(int port, int source, long object)
11040 + throws IOException;
11042 + /**
11043 + * Retrieves a single event from a port
11044 + */
11045 + static native int port_get(int port, long address) throws IOException;
11047 + /**
11048 + * Retrieves at most {@code max} events from a port. A time-out of {@code < 0} means
11049 + * never time-out.
11050 + */
11051 + static native int port_getn(int port, long address, int max, long timeout)
11052 + throws IOException;
11054 + /**
11055 + * Sends a user-defined eventto a specified port.
11056 + */
11057 + static native void port_send(int port, int events) throws IOException;
11059 + /**
11060 + * Closes a port.
11061 + */
11062 + static native void port_close(int port);
11065 + static {
11066 + IOUtil.load();
11069 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/solaris/classes/sun/nio/fs/DefaultFileSystemProvider.java jdk23u-jdk-23-36/src/java.base/solaris/classes/sun/nio/fs/DefaultFileSystemProvider.java
11070 --- jdk23u-jdk-23-36.orig/src/java.base/solaris/classes/sun/nio/fs/DefaultFileSystemProvider.java 1970-01-01 01:00:00.000000000 +0100
11071 +++ jdk23u-jdk-23-36/src/java.base/solaris/classes/sun/nio/fs/DefaultFileSystemProvider.java 2024-08-17 19:50:33.154618137 +0200
11072 @@ -0,0 +1,53 @@
11074 + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
11075 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
11077 + * This code is free software; you can redistribute it and/or modify it
11078 + * under the terms of the GNU General Public License version 2 only, as
11079 + * published by the Free Software Foundation. Oracle designates this
11080 + * particular file as subject to the "Classpath" exception as provided
11081 + * by Oracle in the LICENSE file that accompanied this code.
11083 + * This code is distributed in the hope that it will be useful, but WITHOUT
11084 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11085 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11086 + * version 2 for more details (a copy is included in the LICENSE file that
11087 + * accompanied this code).
11089 + * You should have received a copy of the GNU General Public License version
11090 + * 2 along with this work; if not, write to the Free Software Foundation,
11091 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
11093 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
11094 + * or visit www.oracle.com if you need additional information or have any
11095 + * questions.
11096 + */
11098 +package sun.nio.fs;
11100 +import java.nio.file.FileSystem;
11102 +/**
11103 + * Creates this platform's default FileSystemProvider.
11104 + */
11106 +public class DefaultFileSystemProvider {
11107 + private static final SolarisFileSystemProvider INSTANCE
11108 + = new SolarisFileSystemProvider();
11110 + private DefaultFileSystemProvider() { }
11112 + /**
11113 + * Returns the platform's default file system provider.
11114 + */
11115 + public static SolarisFileSystemProvider instance() {
11116 + return INSTANCE;
11119 + /**
11120 + * Returns the platform's default file system.
11121 + */
11122 + public static FileSystem theFileSystem() {
11123 + return INSTANCE.theFileSystem();
11126 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java jdk23u-jdk-23-36/src/java.base/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java
11127 --- jdk23u-jdk-23-36.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java 1970-01-01 01:00:00.000000000 +0100
11128 +++ jdk23u-jdk-23-36/src/java.base/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java 2024-08-17 19:50:33.155055037 +0200
11129 @@ -0,0 +1,414 @@
11131 + * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
11132 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
11134 + * This code is free software; you can redistribute it and/or modify it
11135 + * under the terms of the GNU General Public License version 2 only, as
11136 + * published by the Free Software Foundation. Oracle designates this
11137 + * particular file as subject to the "Classpath" exception as provided
11138 + * by Oracle in the LICENSE file that accompanied this code.
11140 + * This code is distributed in the hope that it will be useful, but WITHOUT
11141 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11142 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11143 + * version 2 for more details (a copy is included in the LICENSE file that
11144 + * accompanied this code).
11146 + * You should have received a copy of the GNU General Public License version
11147 + * 2 along with this work; if not, write to the Free Software Foundation,
11148 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
11150 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
11151 + * or visit www.oracle.com if you need additional information or have any
11152 + * questions.
11153 + */
11155 +package sun.nio.fs;
11157 +import java.nio.file.*;
11158 +import java.nio.file.attribute.*;
11159 +import java.util.*;
11160 +import java.io.IOException;
11161 +import jdk.internal.misc.Unsafe;
11163 +import static sun.nio.fs.UnixConstants.*;
11164 +import static sun.nio.fs.SolarisConstants.*;
11165 +import static sun.nio.fs.SolarisNativeDispatcher.*;
11168 +/**
11169 + * Solaris implementation of AclFileAttributeView with native support for
11170 + * NFSv4 ACLs on ZFS.
11171 + */
11173 +class SolarisAclFileAttributeView
11174 + extends AbstractAclFileAttributeView
11176 + private static final Unsafe unsafe = Unsafe.getUnsafe();
11178 + // Maximum number of entries allowed in an ACL
11179 + private static final int MAX_ACL_ENTRIES = 1024;
11181 + /**
11182 + * typedef struct ace {
11183 + * uid_t a_who;
11184 + * uint32_t a_access_mask;
11185 + * uint16_t a_flags;
11186 + * uint16_t a_type;
11187 + * } ace_t;
11188 + */
11189 + private static final short SIZEOF_ACE_T = 12;
11190 + private static final short OFFSETOF_UID = 0;
11191 + private static final short OFFSETOF_MASK = 4;
11192 + private static final short OFFSETOF_FLAGS = 8;
11193 + private static final short OFFSETOF_TYPE = 10;
11195 + private final UnixPath file;
11196 + private final boolean followLinks;
11198 + SolarisAclFileAttributeView(UnixPath file, boolean followLinks) {
11199 + this.file = file;
11200 + this.followLinks = followLinks;
11203 + /**
11204 + * Permission checks to access file
11205 + */
11206 + private void checkAccess(UnixPath file,
11207 + boolean checkRead,
11208 + boolean checkWrite)
11210 + @SuppressWarnings("removal")
11211 + SecurityManager sm = System.getSecurityManager();
11212 + if (sm != null) {
11213 + if (checkRead)
11214 + file.checkRead();
11215 + if (checkWrite)
11216 + file.checkWrite();
11217 + sm.checkPermission(new RuntimePermission("accessUserInformation"));
11221 + /**
11222 + * Encode the ACL to the given buffer
11223 + */
11224 + private static void encode(List<AclEntry> acl, long address) {
11225 + long offset = address;
11226 + for (AclEntry ace: acl) {
11227 + int flags = 0;
11229 + // map UserPrincipal to uid and flags
11230 + UserPrincipal who = ace.principal();
11231 + if (!(who instanceof UnixUserPrincipals.User))
11232 + throw new ProviderMismatchException();
11233 + UnixUserPrincipals.User user = (UnixUserPrincipals.User)who;
11234 + int uid;
11235 + if (user.isSpecial()) {
11236 + uid = -1;
11237 + if (who == UnixUserPrincipals.SPECIAL_OWNER)
11238 + flags |= ACE_OWNER;
11239 + else if (who == UnixUserPrincipals.SPECIAL_GROUP)
11240 + flags |= (ACE_GROUP | ACE_IDENTIFIER_GROUP);
11241 + else if (who == UnixUserPrincipals.SPECIAL_EVERYONE)
11242 + flags |= ACE_EVERYONE;
11243 + else
11244 + throw new AssertionError("Unable to map special identifier");
11245 + } else {
11246 + if (user instanceof UnixUserPrincipals.Group) {
11247 + uid = user.gid();
11248 + flags |= ACE_IDENTIFIER_GROUP;
11249 + } else {
11250 + uid = user.uid();
11254 + // map ACE type
11255 + int type;
11256 + switch (ace.type()) {
11257 + case ALLOW:
11258 + type = ACE_ACCESS_ALLOWED_ACE_TYPE;
11259 + break;
11260 + case DENY:
11261 + type = ACE_ACCESS_DENIED_ACE_TYPE;
11262 + break;
11263 + case AUDIT:
11264 + type = ACE_SYSTEM_AUDIT_ACE_TYPE;
11265 + break;
11266 + case ALARM:
11267 + type = ACE_SYSTEM_ALARM_ACE_TYPE;
11268 + break;
11269 + default:
11270 + throw new AssertionError("Unable to map ACE type");
11273 + // map permissions
11274 + Set<AclEntryPermission> aceMask = ace.permissions();
11275 + int mask = 0;
11276 + if (aceMask.contains(AclEntryPermission.READ_DATA))
11277 + mask |= ACE_READ_DATA;
11278 + if (aceMask.contains(AclEntryPermission.WRITE_DATA))
11279 + mask |= ACE_WRITE_DATA;
11280 + if (aceMask.contains(AclEntryPermission.APPEND_DATA))
11281 + mask |= ACE_APPEND_DATA;
11282 + if (aceMask.contains(AclEntryPermission.READ_NAMED_ATTRS))
11283 + mask |= ACE_READ_NAMED_ATTRS;
11284 + if (aceMask.contains(AclEntryPermission.WRITE_NAMED_ATTRS))
11285 + mask |= ACE_WRITE_NAMED_ATTRS;
11286 + if (aceMask.contains(AclEntryPermission.EXECUTE))
11287 + mask |= ACE_EXECUTE;
11288 + if (aceMask.contains(AclEntryPermission.DELETE_CHILD))
11289 + mask |= ACE_DELETE_CHILD;
11290 + if (aceMask.contains(AclEntryPermission.READ_ATTRIBUTES))
11291 + mask |= ACE_READ_ATTRIBUTES;
11292 + if (aceMask.contains(AclEntryPermission.WRITE_ATTRIBUTES))
11293 + mask |= ACE_WRITE_ATTRIBUTES;
11294 + if (aceMask.contains(AclEntryPermission.DELETE))
11295 + mask |= ACE_DELETE;
11296 + if (aceMask.contains(AclEntryPermission.READ_ACL))
11297 + mask |= ACE_READ_ACL;
11298 + if (aceMask.contains(AclEntryPermission.WRITE_ACL))
11299 + mask |= ACE_WRITE_ACL;
11300 + if (aceMask.contains(AclEntryPermission.WRITE_OWNER))
11301 + mask |= ACE_WRITE_OWNER;
11302 + if (aceMask.contains(AclEntryPermission.SYNCHRONIZE))
11303 + mask |= ACE_SYNCHRONIZE;
11305 + // FIXME - it would be desirable to know here if the file is a
11306 + // directory or not. Solaris returns EINVAL if an ACE has a directory
11307 + // -only flag and the file is not a directory.
11308 + Set<AclEntryFlag> aceFlags = ace.flags();
11309 + if (aceFlags.contains(AclEntryFlag.FILE_INHERIT))
11310 + flags |= ACE_FILE_INHERIT_ACE;
11311 + if (aceFlags.contains(AclEntryFlag.DIRECTORY_INHERIT))
11312 + flags |= ACE_DIRECTORY_INHERIT_ACE;
11313 + if (aceFlags.contains(AclEntryFlag.NO_PROPAGATE_INHERIT))
11314 + flags |= ACE_NO_PROPAGATE_INHERIT_ACE;
11315 + if (aceFlags.contains(AclEntryFlag.INHERIT_ONLY))
11316 + flags |= ACE_INHERIT_ONLY_ACE;
11318 + unsafe.putInt(offset + OFFSETOF_UID, uid);
11319 + unsafe.putInt(offset + OFFSETOF_MASK, mask);
11320 + unsafe.putShort(offset + OFFSETOF_FLAGS, (short)flags);
11321 + unsafe.putShort(offset + OFFSETOF_TYPE, (short)type);
11323 + offset += SIZEOF_ACE_T;
11327 + /**
11328 + * Decode the buffer, returning an ACL
11329 + */
11330 + private static List<AclEntry> decode(long address, int n) {
11331 + ArrayList<AclEntry> acl = new ArrayList<>(n);
11332 + for (int i=0; i<n; i++) {
11333 + long offset = address + i*SIZEOF_ACE_T;
11335 + int uid = unsafe.getInt(offset + OFFSETOF_UID);
11336 + int mask = unsafe.getInt(offset + OFFSETOF_MASK);
11337 + int flags = (int)unsafe.getShort(offset + OFFSETOF_FLAGS);
11338 + int type = (int)unsafe.getShort(offset + OFFSETOF_TYPE);
11340 + // map uid and flags to UserPrincipal
11341 + UnixUserPrincipals.User who = null;
11342 + if ((flags & ACE_OWNER) > 0) {
11343 + who = UnixUserPrincipals.SPECIAL_OWNER;
11344 + } else if ((flags & ACE_GROUP) > 0) {
11345 + who = UnixUserPrincipals.SPECIAL_GROUP;
11346 + } else if ((flags & ACE_EVERYONE) > 0) {
11347 + who = UnixUserPrincipals.SPECIAL_EVERYONE;
11348 + } else if ((flags & ACE_IDENTIFIER_GROUP) > 0) {
11349 + who = UnixUserPrincipals.fromGid(uid);
11350 + } else {
11351 + who = UnixUserPrincipals.fromUid(uid);
11354 + AclEntryType aceType = null;
11355 + switch (type) {
11356 + case ACE_ACCESS_ALLOWED_ACE_TYPE:
11357 + aceType = AclEntryType.ALLOW;
11358 + break;
11359 + case ACE_ACCESS_DENIED_ACE_TYPE:
11360 + aceType = AclEntryType.DENY;
11361 + break;
11362 + case ACE_SYSTEM_AUDIT_ACE_TYPE:
11363 + aceType = AclEntryType.AUDIT;
11364 + break;
11365 + case ACE_SYSTEM_ALARM_ACE_TYPE:
11366 + aceType = AclEntryType.ALARM;
11367 + break;
11368 + default:
11369 + assert false;
11372 + Set<AclEntryPermission> aceMask = EnumSet.noneOf(AclEntryPermission.class);
11373 + if ((mask & ACE_READ_DATA) > 0)
11374 + aceMask.add(AclEntryPermission.READ_DATA);
11375 + if ((mask & ACE_WRITE_DATA) > 0)
11376 + aceMask.add(AclEntryPermission.WRITE_DATA);
11377 + if ((mask & ACE_APPEND_DATA ) > 0)
11378 + aceMask.add(AclEntryPermission.APPEND_DATA);
11379 + if ((mask & ACE_READ_NAMED_ATTRS) > 0)
11380 + aceMask.add(AclEntryPermission.READ_NAMED_ATTRS);
11381 + if ((mask & ACE_WRITE_NAMED_ATTRS) > 0)
11382 + aceMask.add(AclEntryPermission.WRITE_NAMED_ATTRS);
11383 + if ((mask & ACE_EXECUTE) > 0)
11384 + aceMask.add(AclEntryPermission.EXECUTE);
11385 + if ((mask & ACE_DELETE_CHILD ) > 0)
11386 + aceMask.add(AclEntryPermission.DELETE_CHILD);
11387 + if ((mask & ACE_READ_ATTRIBUTES) > 0)
11388 + aceMask.add(AclEntryPermission.READ_ATTRIBUTES);
11389 + if ((mask & ACE_WRITE_ATTRIBUTES) > 0)
11390 + aceMask.add(AclEntryPermission.WRITE_ATTRIBUTES);
11391 + if ((mask & ACE_DELETE) > 0)
11392 + aceMask.add(AclEntryPermission.DELETE);
11393 + if ((mask & ACE_READ_ACL) > 0)
11394 + aceMask.add(AclEntryPermission.READ_ACL);
11395 + if ((mask & ACE_WRITE_ACL) > 0)
11396 + aceMask.add(AclEntryPermission.WRITE_ACL);
11397 + if ((mask & ACE_WRITE_OWNER) > 0)
11398 + aceMask.add(AclEntryPermission.WRITE_OWNER);
11399 + if ((mask & ACE_SYNCHRONIZE) > 0)
11400 + aceMask.add(AclEntryPermission.SYNCHRONIZE);
11402 + Set<AclEntryFlag> aceFlags = EnumSet.noneOf(AclEntryFlag.class);
11403 + if ((flags & ACE_FILE_INHERIT_ACE) > 0)
11404 + aceFlags.add(AclEntryFlag.FILE_INHERIT);
11405 + if ((flags & ACE_DIRECTORY_INHERIT_ACE) > 0)
11406 + aceFlags.add(AclEntryFlag.DIRECTORY_INHERIT);
11407 + if ((flags & ACE_NO_PROPAGATE_INHERIT_ACE) > 0)
11408 + aceFlags.add(AclEntryFlag.NO_PROPAGATE_INHERIT);
11409 + if ((flags & ACE_INHERIT_ONLY_ACE) > 0)
11410 + aceFlags.add(AclEntryFlag.INHERIT_ONLY);
11412 + // build the ACL entry and add it to the list
11413 + AclEntry ace = AclEntry.newBuilder()
11414 + .setType(aceType)
11415 + .setPrincipal(who)
11416 + .setPermissions(aceMask).setFlags(aceFlags).build();
11417 + acl.add(ace);
11420 + return acl;
11423 + // Returns true if NFSv4 ACLs not enabled on file system
11424 + private static boolean isAclsEnabled(int fd) {
11425 + try {
11426 + long enabled = fpathconf(fd, _PC_ACL_ENABLED);
11427 + if (enabled == _ACL_ACE_ENABLED)
11428 + return true;
11429 + } catch (UnixException x) {
11431 + return false;
11434 + @Override
11435 + public List<AclEntry> getAcl()
11436 + throws IOException
11438 + // permission check
11439 + checkAccess(file, true, false);
11441 + // open file (will fail if file is a link and not following links)
11442 + int fd = -1;
11443 + try {
11444 + fd = file.openForAttributeAccess(followLinks);
11445 + } catch (UnixException x) {
11446 + x.rethrowAsIOException(file);
11448 + try {
11449 + long address = unsafe.allocateMemory(SIZEOF_ACE_T * MAX_ACL_ENTRIES);
11450 + try {
11451 + // read ACL and decode it
11452 + int n = facl(fd, ACE_GETACL, MAX_ACL_ENTRIES, address);
11453 + assert n >= 0;
11454 + return decode(address, n);
11455 + } catch (UnixException x) {
11456 + if ((x.errno() == ENOSYS) || !isAclsEnabled(fd)) {
11457 + throw new FileSystemException(file.getPathForExceptionMessage(),
11458 + null, x.getMessage() + " (file system does not support NFSv4 ACLs)");
11460 + x.rethrowAsIOException(file);
11461 + return null; // keep compiler happy
11462 + } finally {
11463 + unsafe.freeMemory(address);
11465 + } finally {
11466 + close(fd, e -> null);
11470 + @Override
11471 + public void setAcl(List<AclEntry> acl) throws IOException {
11472 + // permission check
11473 + checkAccess(file, false, true);
11475 + // open file (will fail if file is a link and not following links)
11476 + int fd = -1;
11477 + try {
11478 + fd = file.openForAttributeAccess(followLinks);
11479 + } catch (UnixException x) {
11480 + x.rethrowAsIOException(file);
11482 + try {
11483 + // SECURITY: need to copy list as can change during processing
11484 + acl = new ArrayList<AclEntry>(acl);
11485 + int n = acl.size();
11487 + long address = unsafe.allocateMemory(SIZEOF_ACE_T * n);
11488 + try {
11489 + encode(acl, address);
11490 + facl(fd, ACE_SETACL, n, address);
11491 + } catch (UnixException x) {
11492 + if ((x.errno() == ENOSYS) || !isAclsEnabled(fd)) {
11493 + throw new FileSystemException(file.getPathForExceptionMessage(),
11494 + null, x.getMessage() + " (file system does not support NFSv4 ACLs)");
11496 + if (x.errno() == EINVAL && (n < 3))
11497 + throw new IOException("ACL must contain at least 3 entries");
11498 + x.rethrowAsIOException(file);
11499 + } finally {
11500 + unsafe.freeMemory(address);
11502 + } finally {
11503 + close(fd, e -> null);
11507 + @Override
11508 + public UserPrincipal getOwner()
11509 + throws IOException
11511 + checkAccess(file, true, false);
11513 + try {
11514 + UnixFileAttributes attrs =
11515 + UnixFileAttributes.get(file, followLinks);
11516 + return UnixUserPrincipals.fromUid(attrs.uid());
11517 + } catch (UnixException x) {
11518 + x.rethrowAsIOException(file);
11519 + return null; // keep compile happy
11523 + @Override
11524 + public void setOwner(UserPrincipal owner) throws IOException {
11525 + checkAccess(file, true, false);
11527 + if (!(owner instanceof UnixUserPrincipals.User))
11528 + throw new ProviderMismatchException();
11529 + if (owner instanceof UnixUserPrincipals.Group)
11530 + throw new IOException("'owner' parameter is a group");
11531 + int uid = ((UnixUserPrincipals.User)owner).uid();
11533 + try {
11534 + if (followLinks) {
11535 + lchown(file, uid, -1);
11536 + } else {
11537 + chown(file, uid, -1);
11539 + } catch (UnixException x) {
11540 + x.rethrowAsIOException(file);
11544 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisConstants.java.template jdk23u-jdk-23-36/src/java.base/solaris/classes/sun/nio/fs/SolarisConstants.java.template
11545 --- jdk23u-jdk-23-36.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisConstants.java.template 1970-01-01 01:00:00.000000000 +0100
11546 +++ jdk23u-jdk-23-36/src/java.base/solaris/classes/sun/nio/fs/SolarisConstants.java.template 2024-08-17 19:50:33.155365952 +0200
11547 @@ -0,0 +1,89 @@
11549 + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
11551 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
11553 + * This code is free software; you can redistribute it and/or modify it
11554 + * under the terms of the GNU General Public License version 2 only, as
11555 + * published by the Free Software Foundation. Oracle designates this
11556 + * particular file as subject to the "Classpath" exception as provided
11557 + * by Oracle in the LICENSE file that accompanied this code.
11559 + * This code is distributed in the hope that it will be useful, but WITHOUT
11560 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11561 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11562 + * version 2 for more details (a copy is included in the LICENSE file that
11563 + * accompanied this code).
11565 + * You should have received a copy of the GNU General Public License version
11566 + * 2 along with this work; if not, write to the Free Software Foundation,
11567 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
11569 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
11570 + * or visit www.oracle.com if you need additional information or have any
11571 + * questions.
11572 + */
11574 +@@END_COPYRIGHT@@
11576 +#include <stdio.h>
11577 +#include <errno.h>
11578 +#include <unistd.h>
11579 +#include <sys/acl.h>
11580 +#include <fcntl.h>
11581 +#include <sys/stat.h>
11583 +/* On Solaris, "sun" is defined as a macro. Undefine to make package
11584 + declaration valid */
11585 +#undef sun
11587 +/* To be able to name the Java constants the same as the C constants without
11588 + having the preprocessor rewrite those identifiers, add PREFIX_ to all
11589 + identifiers matching a C constant. The PREFIX_ is filtered out in the
11590 + makefile. */
11592 +@@START_HERE@@
11594 +package sun.nio.fs;
11595 +class SolarisConstants {
11597 + private SolarisConstants() { }
11599 + static final int PREFIX_O_XATTR = O_XATTR;
11600 + static final int PREFIX__PC_XATTR_ENABLED = _PC_XATTR_ENABLED;
11601 + static final int PREFIX__PC_ACL_ENABLED = _PC_ACL_ENABLED;
11602 + static final int PREFIX__ACL_ACE_ENABLED = _ACL_ACE_ENABLED;
11603 + static final int PREFIX_ACE_GETACL = ACE_GETACL;
11604 + static final int PREFIX_ACE_SETACL = ACE_SETACL;
11605 + static final int PREFIX_ACE_ACCESS_ALLOWED_ACE_TYPE = ACE_ACCESS_ALLOWED_ACE_TYPE;
11606 + static final int PREFIX_ACE_ACCESS_DENIED_ACE_TYPE = ACE_ACCESS_DENIED_ACE_TYPE;
11607 + static final int PREFIX_ACE_SYSTEM_AUDIT_ACE_TYPE = ACE_SYSTEM_AUDIT_ACE_TYPE;
11608 + static final int PREFIX_ACE_SYSTEM_ALARM_ACE_TYPE = ACE_SYSTEM_ALARM_ACE_TYPE;
11609 + static final int PREFIX_ACE_READ_DATA = ACE_READ_DATA;
11610 + static final int PREFIX_ACE_LIST_DIRECTORY = ACE_LIST_DIRECTORY;
11611 + static final int PREFIX_ACE_WRITE_DATA = ACE_WRITE_DATA;
11612 + static final int PREFIX_ACE_ADD_FILE = ACE_ADD_FILE;
11613 + static final int PREFIX_ACE_APPEND_DATA = ACE_APPEND_DATA;
11614 + static final int PREFIX_ACE_ADD_SUBDIRECTORY = ACE_ADD_SUBDIRECTORY;
11615 + static final int PREFIX_ACE_READ_NAMED_ATTRS = ACE_READ_NAMED_ATTRS;
11616 + static final int PREFIX_ACE_WRITE_NAMED_ATTRS = ACE_WRITE_NAMED_ATTRS;
11617 + static final int PREFIX_ACE_EXECUTE = ACE_EXECUTE;
11618 + static final int PREFIX_ACE_DELETE_CHILD = ACE_DELETE_CHILD;
11619 + static final int PREFIX_ACE_READ_ATTRIBUTES = ACE_READ_ATTRIBUTES;
11620 + static final int PREFIX_ACE_WRITE_ATTRIBUTES = ACE_WRITE_ATTRIBUTES;
11621 + static final int PREFIX_ACE_DELETE = ACE_DELETE;
11622 + static final int PREFIX_ACE_READ_ACL = ACE_READ_ACL;
11623 + static final int PREFIX_ACE_WRITE_ACL = ACE_WRITE_ACL;
11624 + static final int PREFIX_ACE_WRITE_OWNER = ACE_WRITE_OWNER;
11625 + static final int PREFIX_ACE_SYNCHRONIZE = ACE_SYNCHRONIZE;
11626 + static final int PREFIX_ACE_FILE_INHERIT_ACE = ACE_FILE_INHERIT_ACE;
11627 + static final int PREFIX_ACE_DIRECTORY_INHERIT_ACE = ACE_DIRECTORY_INHERIT_ACE;
11628 + static final int PREFIX_ACE_NO_PROPAGATE_INHERIT_ACE = ACE_NO_PROPAGATE_INHERIT_ACE;
11629 + static final int PREFIX_ACE_INHERIT_ONLY_ACE = ACE_INHERIT_ONLY_ACE;
11630 + static final int PREFIX_ACE_SUCCESSFUL_ACCESS_ACE_FLAG = ACE_SUCCESSFUL_ACCESS_ACE_FLAG;
11631 + static final int PREFIX_ACE_FAILED_ACCESS_ACE_FLAG = ACE_FAILED_ACCESS_ACE_FLAG;
11632 + static final int PREFIX_ACE_IDENTIFIER_GROUP = ACE_IDENTIFIER_GROUP;
11633 + static final int PREFIX_ACE_OWNER = ACE_OWNER;
11634 + static final int PREFIX_ACE_GROUP = ACE_GROUP;
11635 + static final int PREFIX_ACE_EVERYONE = ACE_EVERYONE;
11637 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisFileStore.java jdk23u-jdk-23-36/src/java.base/solaris/classes/sun/nio/fs/SolarisFileStore.java
11638 --- jdk23u-jdk-23-36.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisFileStore.java 1970-01-01 01:00:00.000000000 +0100
11639 +++ jdk23u-jdk-23-36/src/java.base/solaris/classes/sun/nio/fs/SolarisFileStore.java 2024-08-17 19:50:33.155645144 +0200
11640 @@ -0,0 +1,111 @@
11642 + * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
11643 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
11645 + * This code is free software; you can redistribute it and/or modify it
11646 + * under the terms of the GNU General Public License version 2 only, as
11647 + * published by the Free Software Foundation. Oracle designates this
11648 + * particular file as subject to the "Classpath" exception as provided
11649 + * by Oracle in the LICENSE file that accompanied this code.
11651 + * This code is distributed in the hope that it will be useful, but WITHOUT
11652 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11653 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11654 + * version 2 for more details (a copy is included in the LICENSE file that
11655 + * accompanied this code).
11657 + * You should have received a copy of the GNU General Public License version
11658 + * 2 along with this work; if not, write to the Free Software Foundation,
11659 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
11661 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
11662 + * or visit www.oracle.com if you need additional information or have any
11663 + * questions.
11664 + */
11666 +package sun.nio.fs;
11668 +import java.nio.file.attribute.*;
11669 +import java.io.IOException;
11671 +import static sun.nio.fs.UnixNativeDispatcher.*;
11672 +import static sun.nio.fs.SolarisConstants.*;
11674 +/**
11675 + * Solaris implementation of FileStore
11676 + */
11678 +class SolarisFileStore
11679 + extends UnixFileStore
11681 + private final boolean xattrEnabled;
11683 + SolarisFileStore(UnixPath file) throws IOException {
11684 + super(file);
11685 + this.xattrEnabled = xattrEnabled();
11688 + SolarisFileStore(UnixFileSystem fs, UnixMountEntry entry) throws IOException {
11689 + super(fs, entry);
11690 + this.xattrEnabled = xattrEnabled();
11693 + // returns true if extended attributes enabled
11694 + private boolean xattrEnabled() {
11695 + long res = 0L;
11696 + try {
11697 + res = pathconf(file(), _PC_XATTR_ENABLED);
11698 + } catch (UnixException x) {
11699 + // ignore
11701 + return (res != 0L);
11704 + @Override
11705 + UnixMountEntry findMountEntry() throws IOException {
11706 + // On Solaris iterate over the entries in the mount table to find device
11707 + for (UnixMountEntry entry: file().getFileSystem().getMountEntries()) {
11708 + if (entry.dev() == dev()) {
11709 + return entry;
11712 + throw new IOException("Device not found in mnttab");
11715 + @Override
11716 + public boolean supportsFileAttributeView(Class<? extends FileAttributeView> type) {
11717 + if (type == AclFileAttributeView.class) {
11718 + // lookup fstypes.properties
11719 + FeatureStatus status = checkIfFeaturePresent("nfsv4acl");
11720 + switch (status) {
11721 + case PRESENT : return true;
11722 + case NOT_PRESENT : return false;
11723 + default :
11724 + // AclFileAttributeView available on ZFS
11725 + return (type().equals("zfs"));
11728 + if (type == UserDefinedFileAttributeView.class) {
11729 + // lookup fstypes.properties
11730 + FeatureStatus status = checkIfFeaturePresent("xattr");
11731 + switch (status) {
11732 + case PRESENT : return true;
11733 + case NOT_PRESENT : return false;
11734 + default :
11735 + // UserDefinedFileAttributeView available if extended
11736 + // attributes supported
11737 + return xattrEnabled;
11740 + return super.supportsFileAttributeView(type);
11743 + @Override
11744 + public boolean supportsFileAttributeView(String name) {
11745 + if (name.equals("acl"))
11746 + return supportsFileAttributeView(AclFileAttributeView.class);
11747 + if (name.equals("user"))
11748 + return supportsFileAttributeView(UserDefinedFileAttributeView.class);
11749 + return super.supportsFileAttributeView(name);
11752 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystem.java jdk23u-jdk-23-36/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystem.java
11753 --- jdk23u-jdk-23-36.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystem.java 1970-01-01 01:00:00.000000000 +0100
11754 +++ jdk23u-jdk-23-36/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystem.java 2024-08-17 19:50:33.155970084 +0200
11755 @@ -0,0 +1,127 @@
11757 + * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
11758 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
11760 + * This code is free software; you can redistribute it and/or modify it
11761 + * under the terms of the GNU General Public License version 2 only, as
11762 + * published by the Free Software Foundation. Oracle designates this
11763 + * particular file as subject to the "Classpath" exception as provided
11764 + * by Oracle in the LICENSE file that accompanied this code.
11766 + * This code is distributed in the hope that it will be useful, but WITHOUT
11767 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11768 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11769 + * version 2 for more details (a copy is included in the LICENSE file that
11770 + * accompanied this code).
11772 + * You should have received a copy of the GNU General Public License version
11773 + * 2 along with this work; if not, write to the Free Software Foundation,
11774 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
11776 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
11777 + * or visit www.oracle.com if you need additional information or have any
11778 + * questions.
11779 + */
11781 +package sun.nio.fs;
11783 +import java.nio.file.*;
11784 +import java.io.IOException;
11785 +import java.util.*;
11786 +import sun.security.action.GetPropertyAction;
11787 +import static sun.nio.fs.SolarisNativeDispatcher.*;
11789 +/**
11790 + * Solaris implementation of FileSystem
11791 + */
11793 +class SolarisFileSystem extends UnixFileSystem {
11794 + private final boolean hasSolaris11Features;
11796 + SolarisFileSystem(UnixFileSystemProvider provider, String dir) {
11797 + super(provider, dir);
11799 + // check os.version
11800 + String osversion = GetPropertyAction.privilegedGetProperty("os.version");
11801 + String[] vers = Util.split(osversion, '.');
11802 + assert vers.length >= 2;
11803 + int majorVersion = Integer.parseInt(vers[0]);
11804 + int minorVersion = Integer.parseInt(vers[1]);
11805 + this.hasSolaris11Features =
11806 + (majorVersion > 5 || (majorVersion == 5 && minorVersion >= 11));
11809 + @Override
11810 + boolean isSolaris() {
11811 + return true;
11814 + @Override
11815 + public WatchService newWatchService()
11816 + throws IOException
11818 + // FEN available since Solaris 11
11819 + if (hasSolaris11Features) {
11820 + return new SolarisWatchService(this);
11821 + } else {
11822 + return new PollingWatchService();
11827 + // lazy initialization of the list of supported attribute views
11828 + private static class SupportedFileFileAttributeViewsHolder {
11829 + static final Set<String> supportedFileAttributeViews =
11830 + supportedFileAttributeViews();
11831 + private static Set<String> supportedFileAttributeViews() {
11832 + Set<String> result = new HashSet<>();
11833 + result.addAll(standardFileAttributeViews());
11834 + // additional Solaris-specific views
11835 + result.add("acl");
11836 + result.add("user");
11837 + return Collections.unmodifiableSet(result);
11841 + @Override
11842 + public Set<String> supportedFileAttributeViews() {
11843 + return SupportedFileFileAttributeViewsHolder.supportedFileAttributeViews;
11846 + @Override
11847 + void copyNonPosixAttributes(int ofd, int nfd) {
11848 + SolarisUserDefinedFileAttributeView.copyExtendedAttributes(ofd, nfd);
11849 + // TDB: copy ACL from source to target
11852 + /**
11853 + * Returns object to iterate over entries in /etc/mnttab
11854 + */
11855 + @Override
11856 + Iterable<UnixMountEntry> getMountEntries() {
11857 + ArrayList<UnixMountEntry> entries = new ArrayList<>();
11858 + try {
11859 + UnixPath mnttab = new UnixPath(this, "/etc/mnttab");
11860 + long fp = fopen(mnttab, "r");
11861 + try {
11862 + for (;;) {
11863 + UnixMountEntry entry = new UnixMountEntry();
11864 + int res = getextmntent(fp, entry);
11865 + if (res < 0)
11866 + break;
11867 + entries.add(entry);
11869 + } finally {
11870 + fclose(fp);
11872 + } catch (UnixException x) {
11873 + // nothing we can do
11875 + return entries;
11878 + @Override
11879 + FileStore getFileStore(UnixMountEntry entry) throws IOException {
11880 + return new SolarisFileStore(this, entry);
11883 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java jdk23u-jdk-23-36/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java
11884 --- jdk23u-jdk-23-36.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java 1970-01-01 01:00:00.000000000 +0100
11885 +++ jdk23u-jdk-23-36/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java 2024-08-17 19:50:33.156274189 +0200
11886 @@ -0,0 +1,94 @@
11888 + * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
11889 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
11891 + * This code is free software; you can redistribute it and/or modify it
11892 + * under the terms of the GNU General Public License version 2 only, as
11893 + * published by the Free Software Foundation. Oracle designates this
11894 + * particular file as subject to the "Classpath" exception as provided
11895 + * by Oracle in the LICENSE file that accompanied this code.
11897 + * This code is distributed in the hope that it will be useful, but WITHOUT
11898 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11899 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11900 + * version 2 for more details (a copy is included in the LICENSE file that
11901 + * accompanied this code).
11903 + * You should have received a copy of the GNU General Public License version
11904 + * 2 along with this work; if not, write to the Free Software Foundation,
11905 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
11907 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
11908 + * or visit www.oracle.com if you need additional information or have any
11909 + * questions.
11910 + */
11912 +package sun.nio.fs;
11914 +import java.nio.file.*;
11915 +import java.nio.file.attribute.*;
11916 +import java.nio.file.spi.FileTypeDetector;
11917 +import java.io.IOException;
11918 +import jdk.internal.util.StaticProperty;
11919 +import sun.security.action.GetPropertyAction;
11921 +/**
11922 + * Solaris implementation of FileSystemProvider
11923 + */
11925 +class SolarisFileSystemProvider extends UnixFileSystemProvider {
11926 + public SolarisFileSystemProvider() {
11927 + super();
11930 + @Override
11931 + SolarisFileSystem newFileSystem(String dir) {
11932 + return new SolarisFileSystem(this, dir);
11935 + @Override
11936 + SolarisFileStore getFileStore(UnixPath path) throws IOException {
11937 + return new SolarisFileStore(path);
11941 + @Override
11942 + @SuppressWarnings("unchecked")
11943 + public <V extends FileAttributeView> V getFileAttributeView(Path obj,
11944 + Class<V> type,
11945 + LinkOption... options)
11947 + if (type == AclFileAttributeView.class) {
11948 + return (V) new SolarisAclFileAttributeView(UnixPath.toUnixPath(obj),
11949 + Util.followLinks(options));
11951 + if (type == UserDefinedFileAttributeView.class) {
11952 + return(V) new SolarisUserDefinedFileAttributeView(UnixPath.toUnixPath(obj),
11953 + Util.followLinks(options));
11955 + return super.getFileAttributeView(obj, type, options);
11958 + @Override
11959 + public DynamicFileAttributeView getFileAttributeView(Path obj,
11960 + String name,
11961 + LinkOption... options)
11963 + if (name.equals("acl"))
11964 + return new SolarisAclFileAttributeView(UnixPath.toUnixPath(obj),
11965 + Util.followLinks(options));
11966 + if (name.equals("user"))
11967 + return new SolarisUserDefinedFileAttributeView(UnixPath.toUnixPath(obj),
11968 + Util.followLinks(options));
11969 + return super.getFileAttributeView(obj, name, options);
11972 + @Override
11973 + FileTypeDetector getFileTypeDetector() {
11974 + Path userMimeTypes = Path.of(StaticProperty.userHome(), ".mime.types");
11975 + Path etcMimeTypes = Path.of("/etc/mime.types");
11977 + return chain(new MimeTypesFileTypeDetector(userMimeTypes),
11978 + new MimeTypesFileTypeDetector(etcMimeTypes));
11981 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisNativeDispatcher.java jdk23u-jdk-23-36/src/java.base/solaris/classes/sun/nio/fs/SolarisNativeDispatcher.java
11982 --- jdk23u-jdk-23-36.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisNativeDispatcher.java 1970-01-01 01:00:00.000000000 +0100
11983 +++ jdk23u-jdk-23-36/src/java.base/solaris/classes/sun/nio/fs/SolarisNativeDispatcher.java 2024-08-17 19:50:33.156528216 +0200
11984 @@ -0,0 +1,55 @@
11986 + * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
11987 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
11989 + * This code is free software; you can redistribute it and/or modify it
11990 + * under the terms of the GNU General Public License version 2 only, as
11991 + * published by the Free Software Foundation. Oracle designates this
11992 + * particular file as subject to the "Classpath" exception as provided
11993 + * by Oracle in the LICENSE file that accompanied this code.
11995 + * This code is distributed in the hope that it will be useful, but WITHOUT
11996 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11997 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11998 + * version 2 for more details (a copy is included in the LICENSE file that
11999 + * accompanied this code).
12001 + * You should have received a copy of the GNU General Public License version
12002 + * 2 along with this work; if not, write to the Free Software Foundation,
12003 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
12005 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
12006 + * or visit www.oracle.com if you need additional information or have any
12007 + * questions.
12008 + */
12010 +package sun.nio.fs;
12012 +/**
12013 + * Solaris specific system calls.
12014 + */
12016 +class SolarisNativeDispatcher extends UnixNativeDispatcher {
12017 + private SolarisNativeDispatcher() { }
12019 + /**
12020 + * int getextmntent(FILE *fp, struct extmnttab *mp, int len);
12021 + */
12022 + static native int getextmntent(long fp, UnixMountEntry entry)
12023 + throws UnixException;
12025 + /**
12026 + * int facl(int filedes, int cmd, int nentries, void aclbufp)
12027 + */
12028 + static native int facl(int fd, int cmd, int nentries, long aclbufp)
12029 + throws UnixException;
12032 + // initialize
12033 + private static native void init();
12035 + static {
12036 + jdk.internal.loader.BootLoader.loadLibrary("nio");
12037 + init();
12040 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisUserDefinedFileAttributeView.java jdk23u-jdk-23-36/src/java.base/solaris/classes/sun/nio/fs/SolarisUserDefinedFileAttributeView.java
12041 --- jdk23u-jdk-23-36.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisUserDefinedFileAttributeView.java 1970-01-01 01:00:00.000000000 +0100
12042 +++ jdk23u-jdk-23-36/src/java.base/solaris/classes/sun/nio/fs/SolarisUserDefinedFileAttributeView.java 2024-08-17 19:50:33.156796225 +0200
12043 @@ -0,0 +1,41 @@
12045 + * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
12046 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
12048 + * This code is free software; you can redistribute it and/or modify it
12049 + * under the terms of the GNU General Public License version 2 only, as
12050 + * published by the Free Software Foundation. Oracle designates this
12051 + * particular file as subject to the "Classpath" exception as provided
12052 + * by Oracle in the LICENSE file that accompanied this code.
12054 + * This code is distributed in the hope that it will be useful, but WITHOUT
12055 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12056 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12057 + * version 2 for more details (a copy is included in the LICENSE file that
12058 + * accompanied this code).
12060 + * You should have received a copy of the GNU General Public License version
12061 + * 2 along with this work; if not, write to the Free Software Foundation,
12062 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
12064 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
12065 + * or visit www.oracle.com if you need additional information or have any
12066 + * questions.
12067 + */
12069 +package sun.nio.fs;
12071 +class SolarisUserDefinedFileAttributeView
12072 + extends UnixUserDefinedFileAttributeView
12075 + SolarisUserDefinedFileAttributeView(UnixPath file, boolean followLinks) {
12076 + super(file, followLinks);
12079 + @Override
12080 + protected int maxNameLength() {
12081 + return 255;
12085 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisWatchService.java jdk23u-jdk-23-36/src/java.base/solaris/classes/sun/nio/fs/SolarisWatchService.java
12086 --- jdk23u-jdk-23-36.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisWatchService.java 1970-01-01 01:00:00.000000000 +0100
12087 +++ jdk23u-jdk-23-36/src/java.base/solaris/classes/sun/nio/fs/SolarisWatchService.java 2024-08-17 19:50:33.157410202 +0200
12088 @@ -0,0 +1,821 @@
12090 + * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
12091 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
12093 + * This code is free software; you can redistribute it and/or modify it
12094 + * under the terms of the GNU General Public License version 2 only, as
12095 + * published by the Free Software Foundation. Oracle designates this
12096 + * particular file as subject to the "Classpath" exception as provided
12097 + * by Oracle in the LICENSE file that accompanied this code.
12099 + * This code is distributed in the hope that it will be useful, but WITHOUT
12100 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12101 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12102 + * version 2 for more details (a copy is included in the LICENSE file that
12103 + * accompanied this code).
12105 + * You should have received a copy of the GNU General Public License version
12106 + * 2 along with this work; if not, write to the Free Software Foundation,
12107 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
12109 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
12110 + * or visit www.oracle.com if you need additional information or have any
12111 + * questions.
12112 + */
12114 +package sun.nio.fs;
12116 +import java.nio.file.*;
12117 +import java.util.*;
12118 +import java.io.IOException;
12119 +import jdk.internal.misc.Unsafe;
12121 +import static sun.nio.fs.UnixConstants.*;
12123 +/**
12124 + * Solaris implementation of WatchService based on file events notification
12125 + * facility.
12126 + */
12128 +class SolarisWatchService
12129 + extends AbstractWatchService
12131 + private static final Unsafe unsafe = Unsafe.getUnsafe();
12132 + private static int addressSize = unsafe.addressSize();
12134 + private static int dependsArch(int value32, int value64) {
12135 + return (addressSize == 4) ? value32 : value64;
12138 + /*
12139 + * typedef struct port_event {
12140 + * int portev_events;
12141 + * ushort_t portev_source;
12142 + * ushort_t portev_pad;
12143 + * uintptr_t portev_object;
12144 + * void *portev_user;
12145 + * } port_event_t;
12146 + */
12147 + private static final int SIZEOF_PORT_EVENT = dependsArch(16, 24);
12148 + private static final int OFFSETOF_EVENTS = 0;
12149 + private static final int OFFSETOF_SOURCE = 4;
12150 + private static final int OFFSETOF_OBJECT = 8;
12152 + /*
12153 + * typedef struct file_obj {
12154 + * timestruc_t fo_atime;
12155 + * timestruc_t fo_mtime;
12156 + * timestruc_t fo_ctime;
12157 + * uintptr_t fo_pad[3];
12158 + * char *fo_name;
12159 + * } file_obj_t;
12160 + */
12161 + private static final int SIZEOF_FILEOBJ = dependsArch(40, 80);
12162 + private static final int OFFSET_FO_NAME = dependsArch(36, 72);
12164 + // port sources
12165 + private static final short PORT_SOURCE_USER = 3;
12166 + private static final short PORT_SOURCE_FILE = 7;
12168 + // user-watchable events
12169 + private static final int FILE_MODIFIED = 0x00000002;
12170 + private static final int FILE_ATTRIB = 0x00000004;
12171 + private static final int FILE_NOFOLLOW = 0x10000000;
12173 + // exception events
12174 + private static final int FILE_DELETE = 0x00000010;
12175 + private static final int FILE_RENAME_TO = 0x00000020;
12176 + private static final int FILE_RENAME_FROM = 0x00000040;
12177 + private static final int UNMOUNTED = 0x20000000;
12178 + private static final int MOUNTEDOVER = 0x40000000;
12180 + // background thread to read change events
12181 + private final Poller poller;
12183 + SolarisWatchService(UnixFileSystem fs) throws IOException {
12184 + int port = -1;
12185 + try {
12186 + port = portCreate();
12187 + } catch (UnixException x) {
12188 + throw new IOException(x.errorString());
12191 + this.poller = new Poller(fs, this, port);
12192 + this.poller.start();
12195 + @Override
12196 + WatchKey register(Path dir,
12197 + WatchEvent.Kind<?>[] events,
12198 + WatchEvent.Modifier... modifiers)
12199 + throws IOException
12201 + // delegate to poller
12202 + return poller.register(dir, events, modifiers);
12205 + @Override
12206 + void implClose() throws IOException {
12207 + // delegate to poller
12208 + poller.close();
12211 + /**
12212 + * WatchKey implementation
12213 + */
12214 + private class SolarisWatchKey extends AbstractWatchKey
12215 + implements DirectoryNode
12217 + private final UnixFileKey fileKey;
12219 + // pointer to native file_obj object
12220 + private final long object;
12222 + // events (may be changed). set to null when watch key is invalid
12223 + private volatile Set<? extends WatchEvent.Kind<?>> events;
12225 + // map of entries in directory; created lazily; accessed only by
12226 + // poller thread.
12227 + private Map<Path,EntryNode> children = new HashMap<>();
12229 + SolarisWatchKey(SolarisWatchService watcher,
12230 + UnixPath dir,
12231 + UnixFileKey fileKey,
12232 + long object,
12233 + Set<? extends WatchEvent.Kind<?>> events)
12235 + super(dir, watcher);
12236 + this.fileKey = fileKey;
12237 + this.object = object;
12238 + this.events = events;
12241 + UnixPath getDirectory() {
12242 + return (UnixPath)watchable();
12245 + UnixFileKey getFileKey() {
12246 + return fileKey;
12249 + @Override
12250 + public long object() {
12251 + return object;
12254 + void invalidate() {
12255 + events = null;
12258 + Set<? extends WatchEvent.Kind<?>> events() {
12259 + return events;
12262 + void setEvents(Set<? extends WatchEvent.Kind<?>> events) {
12263 + this.events = events;
12266 + Map<Path,EntryNode> children() {
12267 + return children;
12270 + @Override
12271 + public boolean isValid() {
12272 + return events != null;
12275 + @Override
12276 + public void cancel() {
12277 + if (isValid()) {
12278 + // delegate to poller
12279 + poller.cancel(this);
12283 + @Override
12284 + public void addChild(Path name, EntryNode node) {
12285 + children.put(name, node);
12288 + @Override
12289 + public void removeChild(Path name) {
12290 + children.remove(name);
12293 + @Override
12294 + public EntryNode getChild(Path name) {
12295 + return children.get(name);
12299 + /**
12300 + * Background thread to read from port
12301 + */
12302 + private class Poller extends AbstractPoller {
12304 + // maximum number of events to read per call to port_getn
12305 + private static final int MAX_EVENT_COUNT = 128;
12307 + // events that map to ENTRY_DELETE
12308 + private static final int FILE_REMOVED =
12309 + (FILE_DELETE|FILE_RENAME_TO|FILE_RENAME_FROM);
12311 + // events that tell us not to re-associate the object
12312 + private static final int FILE_EXCEPTION =
12313 + (FILE_REMOVED|UNMOUNTED|MOUNTEDOVER);
12315 + // address of event buffers (used to receive events with port_getn)
12316 + private final long bufferAddress;
12318 + private final SolarisWatchService watcher;
12320 + // the I/O port
12321 + private final int port;
12323 + // maps file key (dev/inode) to WatchKey
12324 + private final Map<UnixFileKey,SolarisWatchKey> fileKey2WatchKey;
12326 + // maps file_obj object to Node
12327 + private final Map<Long,Node> object2Node;
12329 + /**
12330 + * Create a new instance
12331 + */
12332 + Poller(UnixFileSystem fs, SolarisWatchService watcher, int port) {
12333 + this.watcher = watcher;
12334 + this.port = port;
12335 + this.bufferAddress =
12336 + unsafe.allocateMemory(SIZEOF_PORT_EVENT * MAX_EVENT_COUNT);
12337 + this.fileKey2WatchKey = new HashMap<UnixFileKey,SolarisWatchKey>();
12338 + this.object2Node = new HashMap<Long,Node>();
12341 + @Override
12342 + void wakeup() throws IOException {
12343 + // write to port to wakeup polling thread
12344 + try {
12345 + portSend(port, 0);
12346 + } catch (UnixException x) {
12347 + throw new IOException(x.errorString());
12351 + @Override
12352 + Object implRegister(Path obj,
12353 + Set<? extends WatchEvent.Kind<?>> events,
12354 + WatchEvent.Modifier... modifiers)
12356 + // no modifiers supported at this time
12357 + if (modifiers.length > 0) {
12358 + for (WatchEvent.Modifier modifier: modifiers) {
12359 + if (modifier == null)
12360 + return new NullPointerException();
12361 + if (!ExtendedOptions.SENSITIVITY_HIGH.matches(modifier) &&
12362 + !ExtendedOptions.SENSITIVITY_MEDIUM.matches(modifier) &&
12363 + !ExtendedOptions.SENSITIVITY_LOW.matches(modifier)) {
12364 + return new UnsupportedOperationException("Modifier not supported");
12369 + UnixPath dir = (UnixPath)obj;
12371 + // check file is directory
12372 + UnixFileAttributes attrs = null;
12373 + try {
12374 + attrs = UnixFileAttributes.get(dir, true);
12375 + } catch (UnixException x) {
12376 + return x.asIOException(dir);
12378 + if (!attrs.isDirectory()) {
12379 + return new NotDirectoryException(dir.getPathForExceptionMessage());
12382 + // if already registered then update the events and return existing key
12383 + UnixFileKey fileKey = attrs.fileKey();
12384 + SolarisWatchKey watchKey = fileKey2WatchKey.get(fileKey);
12385 + if (watchKey != null) {
12386 + try {
12387 + updateEvents(watchKey, events);
12388 + } catch (UnixException x) {
12389 + return x.asIOException(dir);
12391 + return watchKey;
12394 + // register directory
12395 + long object = 0L;
12396 + try {
12397 + object = registerImpl(dir, (FILE_MODIFIED | FILE_ATTRIB));
12398 + } catch (UnixException x) {
12399 + return x.asIOException(dir);
12402 + // create watch key and insert it into maps
12403 + watchKey = new SolarisWatchKey(watcher, dir, fileKey, object, events);
12404 + object2Node.put(object, watchKey);
12405 + fileKey2WatchKey.put(fileKey, watchKey);
12407 + // register all entries in directory
12408 + registerChildren(dir, watchKey, false, false);
12410 + return watchKey;
12413 + // release resources for single entry
12414 + void releaseChild(EntryNode node) {
12415 + long object = node.object();
12416 + if (object != 0L) {
12417 + object2Node.remove(object);
12418 + releaseObject(object, true);
12419 + node.setObject(0L);
12423 + // release resources for entries in directory
12424 + void releaseChildren(SolarisWatchKey key) {
12425 + for (EntryNode node: key.children().values()) {
12426 + releaseChild(node);
12430 + // cancel single key
12431 + @Override
12432 + void implCancelKey(WatchKey obj) {
12433 + SolarisWatchKey key = (SolarisWatchKey)obj;
12434 + if (key.isValid()) {
12435 + fileKey2WatchKey.remove(key.getFileKey());
12437 + // release resources for entries
12438 + releaseChildren(key);
12440 + // release resources for directory
12441 + long object = key.object();
12442 + object2Node.remove(object);
12443 + releaseObject(object, true);
12445 + // and finally invalidate the key
12446 + key.invalidate();
12450 + // close watch service
12451 + @Override
12452 + void implCloseAll() {
12453 + // release all native resources
12454 + for (Long object: object2Node.keySet()) {
12455 + releaseObject(object, true);
12458 + // invalidate all keys
12459 + for (Map.Entry<UnixFileKey,SolarisWatchKey> entry: fileKey2WatchKey.entrySet()) {
12460 + entry.getValue().invalidate();
12463 + // clean-up
12464 + object2Node.clear();
12465 + fileKey2WatchKey.clear();
12467 + // free global resources
12468 + unsafe.freeMemory(bufferAddress);
12469 + UnixNativeDispatcher.close(port, e -> null);
12472 + /**
12473 + * Poller main loop. Blocks on port_getn waiting for events and then
12474 + * processes them.
12475 + */
12476 + @Override
12477 + public void run() {
12478 + try {
12479 + for (;;) {
12480 + int n = portGetn(port, bufferAddress, MAX_EVENT_COUNT);
12481 + assert n > 0;
12483 + long address = bufferAddress;
12484 + for (int i=0; i<n; i++) {
12485 + boolean shutdown = processEvent(address);
12486 + if (shutdown)
12487 + return;
12488 + address += SIZEOF_PORT_EVENT;
12491 + } catch (UnixException x) {
12492 + x.printStackTrace();
12496 + /**
12497 + * Process a single port_event
12499 + * Returns true if poller thread is requested to shutdown.
12500 + */
12501 + boolean processEvent(long address) {
12502 + // pe->portev_source
12503 + short source = unsafe.getShort(address + OFFSETOF_SOURCE);
12504 + // pe->portev_object
12505 + long object = unsafe.getAddress(address + OFFSETOF_OBJECT);
12506 + // pe->portev_events
12507 + int events = unsafe.getInt(address + OFFSETOF_EVENTS);
12509 + // user event is trigger to process pending requests
12510 + if (source != PORT_SOURCE_FILE) {
12511 + if (source == PORT_SOURCE_USER) {
12512 + // process any pending requests
12513 + boolean shutdown = processRequests();
12514 + if (shutdown)
12515 + return true;
12517 + return false;
12520 + // lookup object to get Node
12521 + Node node = object2Node.get(object);
12522 + if (node == null) {
12523 + // should not happen
12524 + return false;
12527 + // As a workaround for 6642290 and 6636438/6636412 we don't use
12528 + // FILE_EXCEPTION events to tell use not to register the file.
12529 + // boolean reregister = (events & FILE_EXCEPTION) == 0;
12530 + boolean reregister = true;
12532 + // If node is EntryNode then event relates to entry in directory
12533 + // If node is a SolarisWatchKey (DirectoryNode) then event relates
12534 + // to a watched directory.
12535 + boolean isDirectory = (node instanceof SolarisWatchKey);
12536 + if (isDirectory) {
12537 + processDirectoryEvents((SolarisWatchKey)node, events);
12538 + } else {
12539 + boolean ignore = processEntryEvents((EntryNode)node, events);
12540 + if (ignore)
12541 + reregister = false;
12544 + // need to re-associate to get further events
12545 + if (reregister) {
12546 + try {
12547 + events = FILE_MODIFIED | FILE_ATTRIB;
12548 + if (!isDirectory) events |= FILE_NOFOLLOW;
12549 + portAssociate(port,
12550 + PORT_SOURCE_FILE,
12551 + object,
12552 + events);
12553 + } catch (UnixException x) {
12554 + // unable to re-register
12555 + reregister = false;
12559 + // object is not re-registered so release resources. If
12560 + // object is a watched directory then signal key
12561 + if (!reregister) {
12562 + // release resources
12563 + object2Node.remove(object);
12564 + releaseObject(object, false);
12566 + // if watch key then signal it
12567 + if (isDirectory) {
12568 + SolarisWatchKey key = (SolarisWatchKey)node;
12569 + fileKey2WatchKey.remove( key.getFileKey() );
12570 + key.invalidate();
12571 + key.signal();
12572 + } else {
12573 + // if entry then remove it from parent
12574 + EntryNode entry = (EntryNode)node;
12575 + SolarisWatchKey key = (SolarisWatchKey)entry.parent();
12576 + key.removeChild(entry.name());
12580 + return false;
12583 + /**
12584 + * Process directory events. If directory is modified then re-scan
12585 + * directory to register any new entries
12586 + */
12587 + void processDirectoryEvents(SolarisWatchKey key, int mask) {
12588 + if ((mask & (FILE_MODIFIED | FILE_ATTRIB)) != 0) {
12589 + registerChildren(key.getDirectory(), key,
12590 + key.events().contains(StandardWatchEventKinds.ENTRY_CREATE),
12591 + key.events().contains(StandardWatchEventKinds.ENTRY_DELETE));
12595 + /**
12596 + * Process events for entries in registered directories. Returns {@code
12597 + * true} if events are ignored because the watch key has been cancelled.
12598 + */
12599 + boolean processEntryEvents(EntryNode node, int mask) {
12600 + SolarisWatchKey key = (SolarisWatchKey)node.parent();
12601 + Set<? extends WatchEvent.Kind<?>> events = key.events();
12602 + if (events == null) {
12603 + // key has been cancelled so ignore event
12604 + return true;
12607 + // entry modified
12608 + if (((mask & (FILE_MODIFIED | FILE_ATTRIB)) != 0) &&
12609 + events.contains(StandardWatchEventKinds.ENTRY_MODIFY))
12611 + key.signalEvent(StandardWatchEventKinds.ENTRY_MODIFY, node.name());
12615 + return false;
12618 + /**
12619 + * Registers all entries in the given directory
12621 + * The {@code sendCreateEvents} and {@code sendDeleteEvents} parameters
12622 + * indicates if ENTRY_CREATE and ENTRY_DELETE events should be queued
12623 + * when new entries are found. When initially registering a directory
12624 + * they will always be false. When re-scanning a directory then it
12625 + * depends on if the events are enabled or not.
12626 + */
12627 + void registerChildren(UnixPath dir,
12628 + SolarisWatchKey parent,
12629 + boolean sendCreateEvents,
12630 + boolean sendDeleteEvents)
12632 + boolean isModifyEnabled =
12633 + parent.events().contains(StandardWatchEventKinds.ENTRY_MODIFY) ;
12635 + // reset visited flag on entries so that we can detect file deletes
12636 + for (EntryNode node: parent.children().values()) {
12637 + node.setVisited(false);
12640 + try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
12641 + for (Path entry: stream) {
12642 + Path name = entry.getFileName();
12644 + // skip entry if already registered
12645 + EntryNode node = parent.getChild(name);
12646 + if (node != null) {
12647 + node.setVisited(true);
12648 + continue;
12651 + // new entry found
12653 + long object = 0L;
12654 + int errno = 0;
12655 + boolean addNode = false;
12657 + // if ENTRY_MODIFY enabled then we register the entry for events
12658 + if (isModifyEnabled) {
12659 + try {
12660 + UnixPath path = (UnixPath)entry;
12661 + int events = (FILE_NOFOLLOW | FILE_MODIFIED | FILE_ATTRIB);
12662 + object = registerImpl(path, events);
12663 + addNode = true;
12664 + } catch (UnixException x) {
12665 + errno = x.errno();
12667 + } else {
12668 + addNode = true;
12671 + if (addNode) {
12672 + // create node
12673 + node = new EntryNode(object, (UnixPath)entry.getFileName(), parent);
12674 + node.setVisited(true);
12675 + // tell the parent about it
12676 + parent.addChild(entry.getFileName(), node);
12677 + if (object != 0L)
12678 + object2Node.put(object, node);
12681 + // send ENTRY_CREATE event for the new file
12682 + // send ENTRY_DELETE event for files that were deleted immediately
12683 + boolean deleted = (errno == ENOENT);
12684 + if (sendCreateEvents && (addNode || deleted))
12685 + parent.signalEvent(StandardWatchEventKinds.ENTRY_CREATE, name);
12686 + if (sendDeleteEvents && deleted)
12687 + parent.signalEvent(StandardWatchEventKinds.ENTRY_DELETE, name);
12690 + } catch (DirectoryIteratorException | IOException x) {
12691 + // queue OVERFLOW event so that user knows to re-scan directory
12692 + parent.signalEvent(StandardWatchEventKinds.OVERFLOW, null);
12693 + return;
12696 + // clean-up and send ENTRY_DELETE events for any entries that were
12697 + // not found
12698 + Iterator<Map.Entry<Path,EntryNode>> iterator =
12699 + parent.children().entrySet().iterator();
12700 + while (iterator.hasNext()) {
12701 + Map.Entry<Path,EntryNode> entry = iterator.next();
12702 + EntryNode node = entry.getValue();
12703 + if (!node.isVisited()) {
12704 + long object = node.object();
12705 + if (object != 0L) {
12706 + object2Node.remove(object);
12707 + releaseObject(object, true);
12709 + if (sendDeleteEvents)
12710 + parent.signalEvent(StandardWatchEventKinds.ENTRY_DELETE, node.name());
12711 + iterator.remove();
12716 + /**
12717 + * Update watch key's events. If ENTRY_MODIFY changes to be enabled
12718 + * then register each file in the directory; If ENTRY_MODIFY changed to
12719 + * be disabled then unregister each file.
12720 + */
12721 + void updateEvents(SolarisWatchKey key, Set<? extends WatchEvent.Kind<?>> events)
12722 + throws UnixException
12725 + // update events, remembering if ENTRY_MODIFY was previously
12726 + // enabled or disabled.
12727 + boolean oldModifyEnabled = key.events()
12728 + .contains(StandardWatchEventKinds.ENTRY_MODIFY);
12729 + key.setEvents(events);
12731 + // check if ENTRY_MODIFY has changed
12732 + boolean newModifyEnabled = events
12733 + .contains(StandardWatchEventKinds.ENTRY_MODIFY);
12734 + if (newModifyEnabled != oldModifyEnabled) {
12735 + UnixException ex = null;
12736 + for (EntryNode node: key.children().values()) {
12737 + if (newModifyEnabled) {
12738 + // register
12739 + UnixPath path = key.getDirectory().resolve(node.name());
12740 + int ev = (FILE_NOFOLLOW | FILE_MODIFIED | FILE_ATTRIB);
12741 + try {
12742 + long object = registerImpl(path, ev);
12743 + object2Node.put(object, node);
12744 + node.setObject(object);
12745 + } catch (UnixException x) {
12746 + // if file has been deleted then it will be detected
12747 + // as a FILE_MODIFIED event on the directory
12748 + if (x.errno() != ENOENT) {
12749 + ex = x;
12750 + break;
12753 + } else {
12754 + // unregister
12755 + releaseChild(node);
12759 + // an error occurred
12760 + if (ex != null) {
12761 + releaseChildren(key);
12762 + throw ex;
12767 + /**
12768 + * Calls port_associate to register the given path.
12769 + * Returns pointer to fileobj structure that is allocated for
12770 + * the registration.
12771 + */
12772 + long registerImpl(UnixPath dir, int events)
12773 + throws UnixException
12775 + // allocate memory for the path (file_obj->fo_name field)
12776 + byte[] path = dir.getByteArrayForSysCalls();
12777 + int len = path.length;
12778 + long name = unsafe.allocateMemory(len+1);
12779 + unsafe.copyMemory(path, Unsafe.ARRAY_BYTE_BASE_OFFSET, null,
12780 + name, (long)len);
12781 + unsafe.putByte(name + len, (byte)0);
12783 + // allocate memory for filedatanode structure - this is the object
12784 + // to port_associate
12785 + long object = unsafe.allocateMemory(SIZEOF_FILEOBJ);
12786 + unsafe.setMemory(null, object, SIZEOF_FILEOBJ, (byte)0);
12787 + unsafe.putAddress(object + OFFSET_FO_NAME, name);
12789 + // associate the object with the port
12790 + try {
12791 + portAssociate(port,
12792 + PORT_SOURCE_FILE,
12793 + object,
12794 + events);
12795 + } catch (UnixException x) {
12796 + // debugging
12797 + if (x.errno() == EAGAIN) {
12798 + System.err.println("The maximum number of objects associated "+
12799 + "with the port has been reached");
12802 + unsafe.freeMemory(name);
12803 + unsafe.freeMemory(object);
12804 + throw x;
12806 + return object;
12809 + /**
12810 + * Frees all resources for an file_obj object; optionally remove
12811 + * association from port
12812 + */
12813 + void releaseObject(long object, boolean dissociate) {
12814 + // remove association
12815 + if (dissociate) {
12816 + try {
12817 + portDissociate(port, PORT_SOURCE_FILE, object);
12818 + } catch (UnixException x) {
12819 + // ignore
12823 + // free native memory
12824 + long name = unsafe.getAddress(object + OFFSET_FO_NAME);
12825 + unsafe.freeMemory(name);
12826 + unsafe.freeMemory(object);
12830 + /**
12831 + * A node with native (file_obj) resources
12832 + */
12833 + private static interface Node {
12834 + long object();
12837 + /**
12838 + * A directory node with a map of the entries in the directory
12839 + */
12840 + private static interface DirectoryNode extends Node {
12841 + void addChild(Path name, EntryNode node);
12842 + void removeChild(Path name);
12843 + EntryNode getChild(Path name);
12846 + /**
12847 + * An implementation of a node that is an entry in a directory.
12848 + */
12849 + private static class EntryNode implements Node {
12850 + private long object;
12851 + private final UnixPath name;
12852 + private final DirectoryNode parent;
12853 + private boolean visited;
12855 + EntryNode(long object, UnixPath name, DirectoryNode parent) {
12856 + this.object = object;
12857 + this.name = name;
12858 + this.parent = parent;
12861 + @Override
12862 + public long object() {
12863 + return object;
12866 + void setObject(long ptr) {
12867 + this.object = ptr;
12870 + UnixPath name() {
12871 + return name;
12874 + DirectoryNode parent() {
12875 + return parent;
12878 + boolean isVisited() {
12879 + return visited;
12882 + void setVisited(boolean v) {
12883 + this.visited = v;
12887 + // -- native methods --
12889 + private static native void init();
12891 + private static native int portCreate() throws UnixException;
12893 + private static native void portAssociate(int port, int source, long object, int events)
12894 + throws UnixException;
12896 + private static native void portDissociate(int port, int source, long object)
12897 + throws UnixException;
12899 + private static native void portSend(int port, int events)
12900 + throws UnixException;
12902 + private static native int portGetn(int port, long address, int max)
12903 + throws UnixException;
12905 + static {
12906 + jdk.internal.loader.BootLoader.loadLibrary("nio");
12907 + init();
12910 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/solaris/native/libjava/ProcessHandleImpl_solaris.c jdk23u-jdk-23-36/src/java.base/solaris/native/libjava/ProcessHandleImpl_solaris.c
12911 --- jdk23u-jdk-23-36.orig/src/java.base/solaris/native/libjava/ProcessHandleImpl_solaris.c 1970-01-01 01:00:00.000000000 +0100
12912 +++ jdk23u-jdk-23-36/src/java.base/solaris/native/libjava/ProcessHandleImpl_solaris.c 2024-08-17 19:50:33.157760465 +0200
12913 @@ -0,0 +1,51 @@
12915 + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
12916 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
12918 + * This code is free software; you can redistribute it and/or modify it
12919 + * under the terms of the GNU General Public License version 2 only, as
12920 + * published by the Free Software Foundation. Oracle designates this
12921 + * particular file as subject to the "Classpath" exception as provided
12922 + * by Oracle in the LICENSE file that accompanied this code.
12924 + * This code is distributed in the hope that it will be useful, but WITHOUT
12925 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12926 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12927 + * version 2 for more details (a copy is included in the LICENSE file that
12928 + * accompanied this code).
12930 + * You should have received a copy of the GNU General Public License version
12931 + * 2 along with this work; if not, write to the Free Software Foundation,
12932 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
12934 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
12935 + * or visit www.oracle.com if you need additional information or have any
12936 + * questions.
12937 + */
12939 +#include "jni.h"
12941 +#include "ProcessHandleImpl_unix.h"
12943 +#include <procfs.h>
12946 + * Implementation of native ProcessHandleImpl functions for Solaris.
12947 + * See ProcessHandleImpl_unix.c for more details.
12948 + */
12950 +void os_initNative(JNIEnv *env, jclass clazz) {}
12952 +jint os_getChildren(JNIEnv *env, jlong jpid, jlongArray jarray,
12953 + jlongArray jparentArray, jlongArray jstimesArray) {
12954 + return unix_getChildren(env, jpid, jarray, jparentArray, jstimesArray);
12957 +pid_t os_getParentPidAndTimings(JNIEnv *env, pid_t pid, jlong *total, jlong *start) {
12958 + return unix_getParentPidAndTimings(env, pid, total, start);
12961 +void os_getCmdlineAndUserInfo(JNIEnv *env, jobject jinfo, pid_t pid) {
12962 + unix_getCmdlineAndUserInfo(env, jinfo, pid);
12965 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/solaris/native/libjvm_db/libjvm_db.c jdk23u-jdk-23-36/src/java.base/solaris/native/libjvm_db/libjvm_db.c
12966 --- jdk23u-jdk-23-36.orig/src/java.base/solaris/native/libjvm_db/libjvm_db.c 1970-01-01 01:00:00.000000000 +0100
12967 +++ jdk23u-jdk-23-36/src/java.base/solaris/native/libjvm_db/libjvm_db.c 2024-08-17 19:50:33.158686204 +0200
12968 @@ -0,0 +1,1552 @@
12970 + * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
12971 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
12973 + * This code is free software; you can redistribute it and/or modify it
12974 + * under the terms of the GNU General Public License version 2 only, as
12975 + * published by the Free Software Foundation.
12977 + * This code is distributed in the hope that it will be useful, but WITHOUT
12978 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12979 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12980 + * version 2 for more details (a copy is included in the LICENSE file that
12981 + * accompanied this code).
12983 + * You should have received a copy of the GNU General Public License version
12984 + * 2 along with this work; if not, write to the Free Software Foundation,
12985 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
12987 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
12988 + * or visit www.oracle.com if you need additional information or have any
12989 + * questions.
12991 + */
12993 +#include <stdio.h>
12994 +#include <stdlib.h>
12995 +#include <string.h>
12996 +#include <errno.h>
12997 +#include <gelf.h>
12999 +#include "libjvm_db.h"
13000 +#include "JvmOffsets.h"
13002 +#define LIBJVM_SO "libjvm.so"
13004 +#if defined(i386) || defined(__i386) || defined(__amd64)
13005 +#ifdef COMPILER2
13006 +#define X86_COMPILER2
13007 +#endif /* COMPILER2 */
13008 +#endif /* i386 */
13010 +typedef struct {
13011 + short vf_cnt; /* number of recognized java vframes */
13012 + short bci; /* current frame method byte code index */
13013 + int line; /* current frame method source line */
13014 + uint64_t new_fp; /* fp for the next frame */
13015 + uint64_t new_pc; /* pc for the next frame */
13016 + uint64_t new_sp; /* "raw" sp for the next frame (includes extension by interpreter/adapter */
13017 + char locinf; /* indicates there is valid location info */
13018 +} Jframe_t;
13020 +int Jlookup_by_regs(jvm_agent_t* J, const prgregset_t regs, char *name,
13021 + size_t size, Jframe_t *jframe);
13023 +int main(int arg) { return arg; }
13025 +static int debug = 0;
13027 +static void failed(int err, const char * file, int line) {
13028 + if (debug) {
13029 + fprintf(stderr, "failed %d at %s:%d\n", err, file, line);
13033 +static void warn(const char * file, int line, const char * msg) {
13034 + if (debug) {
13035 + fprintf(stderr, "warning: %s at %s:%d\n", msg, file, line);
13039 +static void warn1(const char * file, int line, const char * msg, intptr_t arg1) {
13040 + if (debug) {
13041 + fprintf(stderr, "warning: ");
13042 + fprintf(stderr, msg, arg1);
13043 + fprintf(stderr, " at %s:%d\n", file, line);
13047 +#define CHECK_FAIL(err) \
13048 + if (err != PS_OK) { failed(err, __FILE__, __LINE__); goto fail; }
13049 +#define WARN(msg) warn(__FILE__, __LINE__, msg)
13050 +#define WARN1(msg, arg1) warn1(__FILE__, __LINE__, msg, arg1)
13052 +typedef struct VMStructEntry {
13053 + const char * typeName; /* The type name containing the given field (example: "Klass") */
13054 + const char * fieldName; /* The field name within the type (example: "_name") */
13055 + uint64_t address; /* Address of field; only used for static fields */
13056 + /* ("offset" can not be reused because of apparent solstudio compiler bug */
13057 + /* in generation of initializer data) */
13058 +} VMStructEntry;
13060 +/* Prototyping inlined methods */
13062 +int sprintf(char *s, const char *format, ...);
13064 +#define SZ16 sizeof(int16_t)
13065 +#define SZ32 sizeof(int32_t)
13067 +#define COMP_METHOD_SIGN '*'
13069 +#define MAX_VFRAMES_CNT 256
13071 +typedef struct vframe {
13072 + uint64_t method;
13073 + int32_t sender_decode_offset;
13074 + int32_t methodIdx;
13075 + int32_t bci;
13076 + int32_t line;
13077 +} Vframe_t;
13079 +typedef struct frame {
13080 + uintptr_t fp;
13081 + uintptr_t pc;
13082 + uintptr_t sp;
13083 + uintptr_t sender_sp; // The unextended sp of the caller
13084 +} Frame_t;
13086 +typedef struct Nmethod_t {
13087 + struct jvm_agent* J;
13088 + Jframe_t *jframe;
13090 + uint64_t nm; /* _nmethod */
13091 + uint64_t pc;
13092 + uint64_t pc_desc;
13094 + int32_t orig_pc_offset; /* _orig_pc_offset */
13095 + uint64_t instrs_beg; /* _code_offset */
13096 + uint64_t instrs_end;
13097 + uint64_t deopt_beg; /* _deoptimize_offset */
13098 + uint64_t scopes_data_beg; /* _scopes_data_begin */
13099 + int32_t scopes_data_end;
13100 + int32_t metadata_beg; /* _metadata_offset */
13101 + int32_t metadata_end;
13102 + int32_t scopes_pcs_beg; /* _scopes_pcs_offset */
13103 + int32_t scopes_pcs_end;
13105 + int vf_cnt;
13106 + Vframe_t vframes[MAX_VFRAMES_CNT];
13107 +} Nmethod_t;
13109 +struct jvm_agent {
13110 + struct ps_prochandle* P;
13112 + uint64_t nmethod_vtbl;
13113 + uint64_t CodeBlob_vtbl;
13114 + uint64_t BufferBlob_vtbl;
13115 + uint64_t RuntimeStub_vtbl;
13116 + uint64_t Method_vtbl;
13118 + uint64_t Use_Compressed_Oops_address;
13119 + uint64_t Universe_narrow_oop_base_address;
13120 + uint64_t Universe_narrow_oop_shift_address;
13121 + uint64_t CodeCache_heaps_address;
13123 + /* Volatiles */
13124 + uint8_t Use_Compressed_Oops;
13125 + uint64_t Universe_narrow_oop_base;
13126 + uint32_t Universe_narrow_oop_shift;
13127 + // Code cache heaps
13128 + int32_t Number_of_heaps;
13129 + uint64_t* Heap_low;
13130 + uint64_t* Heap_high;
13131 + uint64_t* Heap_segmap_low;
13132 + uint64_t* Heap_segmap_high;
13134 + int32_t SIZE_CodeCache_log2_segment;
13136 + uint64_t methodPtr;
13137 + uint64_t bcp;
13139 + Nmethod_t *N; /*Inlined methods support */
13140 + Frame_t prev_fr;
13141 + Frame_t curr_fr;
13144 +static int
13145 +read_string(struct ps_prochandle *P,
13146 + char *buf, /* caller's buffer */
13147 + size_t size, /* upper limit on bytes to read */
13148 + uintptr_t addr) /* address in process */
13150 + int err = PS_OK;
13151 + while (size-- > 1 && err == PS_OK) {
13152 + err = ps_pread(P, addr, buf, 1);
13153 + if (*buf == '\0') {
13154 + return PS_OK;
13156 + addr += 1;
13157 + buf += 1;
13159 + return -1;
13162 +static int read_compressed_pointer(jvm_agent_t* J, uint64_t base, uint32_t *ptr) {
13163 + int err = -1;
13164 + uint32_t ptr32;
13165 + err = ps_pread(J->P, base, &ptr32, sizeof(uint32_t));
13166 + *ptr = ptr32;
13167 + return err;
13170 +static int read_pointer(jvm_agent_t* J, uint64_t base, uint64_t* ptr) {
13171 + int err = -1;
13172 + uint32_t ptr32;
13174 + switch (DATA_MODEL) {
13175 + case PR_MODEL_LP64:
13176 + err = ps_pread(J->P, base, ptr, sizeof(uint64_t));
13177 + break;
13178 + case PR_MODEL_ILP32:
13179 + err = ps_pread(J->P, base, &ptr32, sizeof(uint32_t));
13180 + *ptr = ptr32;
13181 + break;
13184 + return err;
13187 +static int read_string_pointer(jvm_agent_t* J, uint64_t base, const char ** stringp) {
13188 + uint64_t ptr;
13189 + int err;
13190 + char buffer[1024];
13192 + *stringp = NULL;
13193 + err = read_pointer(J, base, &ptr);
13194 + CHECK_FAIL(err);
13195 + if (ptr != 0) {
13196 + err = read_string(J->P, buffer, sizeof(buffer), ptr);
13197 + CHECK_FAIL(err);
13198 + *stringp = strdup(buffer);
13200 + return PS_OK;
13202 + fail:
13203 + return err;
13206 +static int parse_vmstruct_entry(jvm_agent_t* J, uint64_t base, VMStructEntry* vmp) {
13207 + uint64_t ptr;
13208 + int err;
13210 + err = read_string_pointer(J, base + OFFSET_VMStructEntrytypeName, &vmp->typeName);
13211 + CHECK_FAIL(err);
13212 + err = read_string_pointer(J, base + OFFSET_VMStructEntryfieldName, &vmp->fieldName);
13213 + CHECK_FAIL(err);
13214 + err = read_pointer(J, base + OFFSET_VMStructEntryaddress, &vmp->address);
13215 + CHECK_FAIL(err);
13217 + return PS_OK;
13219 + fail:
13220 + if (vmp->typeName != NULL) free((void*)vmp->typeName);
13221 + if (vmp->fieldName != NULL) free((void*)vmp->fieldName);
13222 + return err;
13225 +static int parse_vmstructs(jvm_agent_t* J) {
13226 + VMStructEntry vmVar;
13227 + VMStructEntry* vmp = &vmVar;
13228 + uint64_t gHotSpotVMStructs;
13229 + psaddr_t sym_addr;
13230 + uint64_t base;
13231 + int err;
13233 + /* Clear *vmp now in case we jump to fail: */
13234 + memset(vmp, 0, sizeof(VMStructEntry));
13236 + err = ps_pglobal_lookup(J->P, LIBJVM_SO, "gHotSpotVMStructs", &sym_addr);
13237 + CHECK_FAIL(err);
13238 + err = read_pointer(J, sym_addr, &gHotSpotVMStructs);
13239 + CHECK_FAIL(err);
13240 + base = gHotSpotVMStructs;
13242 + err = PS_OK;
13243 + while (err == PS_OK) {
13244 + memset(vmp, 0, sizeof(VMStructEntry));
13245 + err = parse_vmstruct_entry(J, base, vmp);
13246 + if (err != PS_OK || vmp->typeName == NULL) {
13247 + break;
13250 + if (vmp->typeName[0] == 'C' && strcmp("CodeCache", vmp->typeName) == 0) {
13251 + /* Read _heaps field of type GrowableArray<CodeHeaps*>* */
13252 + if (strcmp("_heaps", vmp->fieldName) == 0) {
13253 + err = read_pointer(J, vmp->address, &J->CodeCache_heaps_address);
13255 + } else if (vmp->typeName[0] == 'U' && strcmp("Universe", vmp->typeName) == 0) {
13256 + if (strcmp("_narrow_oop._base", vmp->fieldName) == 0) {
13257 + J->Universe_narrow_oop_base_address = vmp->address;
13259 + if (strcmp("_narrow_oop._shift", vmp->fieldName) == 0) {
13260 + J->Universe_narrow_oop_shift_address = vmp->address;
13263 + CHECK_FAIL(err);
13265 + base += SIZE_VMStructEntry;
13266 + if (vmp->typeName != NULL) free((void*)vmp->typeName);
13267 + if (vmp->fieldName != NULL) free((void*)vmp->fieldName);
13270 + return PS_OK;
13272 + fail:
13273 + if (vmp->typeName != NULL) free((void*)vmp->typeName);
13274 + if (vmp->fieldName != NULL) free((void*)vmp->fieldName);
13275 + return -1;
13278 +static int find_symbol(jvm_agent_t* J, const char *name, uint64_t* valuep) {
13279 + psaddr_t sym_addr;
13280 + int err;
13282 + err = ps_pglobal_lookup(J->P, LIBJVM_SO, name, &sym_addr);
13283 + if (err != PS_OK) goto fail;
13284 + *valuep = sym_addr;
13285 + return PS_OK;
13287 + fail:
13288 + return err;
13291 +static int read_volatiles(jvm_agent_t* J) {
13292 + int i;
13293 + uint64_t array_data;
13294 + uint64_t code_heap_address;
13295 + int err;
13297 + err = find_symbol(J, "UseCompressedOops", &J->Use_Compressed_Oops_address);
13298 + if (err == PS_OK) {
13299 + err = ps_pread(J->P, J->Use_Compressed_Oops_address, &J->Use_Compressed_Oops, sizeof(uint8_t));
13300 + CHECK_FAIL(err);
13301 + } else {
13302 + J->Use_Compressed_Oops = 0;
13305 + err = read_pointer(J, J->Universe_narrow_oop_base_address, &J->Universe_narrow_oop_base);
13306 + CHECK_FAIL(err);
13307 + err = ps_pread(J->P, J->Universe_narrow_oop_shift_address, &J->Universe_narrow_oop_shift, sizeof(uint32_t));
13308 + CHECK_FAIL(err);
13310 + /* CodeCache_heaps_address points to GrowableArray<CodeHeaps*>, read _data field
13311 + pointing to the first entry of type CodeCache* in the array */
13312 + err = read_pointer(J, J->CodeCache_heaps_address + OFFSET_GrowableArray_CodeHeap_data, &array_data);
13313 + /* Read _len field containing the number of code heaps */
13314 + err = ps_pread(J->P, J->CodeCache_heaps_address + OFFSET_GrowableArray_CodeHeap_len,
13315 + &J->Number_of_heaps, sizeof(J->Number_of_heaps));
13317 + /* Allocate memory for heap configurations */
13318 + J->Heap_low = (uint64_t*)calloc(J->Number_of_heaps, sizeof(uint64_t));
13319 + J->Heap_high = (uint64_t*)calloc(J->Number_of_heaps, sizeof(uint64_t));
13320 + J->Heap_segmap_low = (uint64_t*)calloc(J->Number_of_heaps, sizeof(uint64_t));
13321 + J->Heap_segmap_high = (uint64_t*)calloc(J->Number_of_heaps, sizeof(uint64_t));
13323 + /* Read code heap configurations */
13324 + for (i = 0; i < J->Number_of_heaps; ++i) {
13325 + /* Read address of heap */
13326 + err = read_pointer(J, array_data, &code_heap_address);
13327 + CHECK_FAIL(err);
13329 + err = read_pointer(J, code_heap_address + OFFSET_CodeHeap_memory +
13330 + OFFSET_VirtualSpace_low, &J->Heap_low[i]);
13331 + CHECK_FAIL(err);
13332 + err = read_pointer(J, code_heap_address + OFFSET_CodeHeap_memory +
13333 + OFFSET_VirtualSpace_high, &J->Heap_high[i]);
13334 + CHECK_FAIL(err);
13335 + err = read_pointer(J, code_heap_address + OFFSET_CodeHeap_segmap +
13336 + OFFSET_VirtualSpace_low, &J->Heap_segmap_low[i]);
13337 + CHECK_FAIL(err);
13338 + err = read_pointer(J, code_heap_address + OFFSET_CodeHeap_segmap +
13339 + OFFSET_VirtualSpace_high, &J->Heap_segmap_high[i]);
13340 + CHECK_FAIL(err);
13342 + /* Increment pointer to next entry */
13343 + array_data = array_data + POINTER_SIZE;
13346 + err = ps_pread(J->P, code_heap_address + OFFSET_CodeHeap_log2_segment_size,
13347 + &J->SIZE_CodeCache_log2_segment, sizeof(J->SIZE_CodeCache_log2_segment));
13348 + CHECK_FAIL(err);
13350 + return PS_OK;
13352 + fail:
13353 + return err;
13356 +static int codeheap_contains(int heap_num, jvm_agent_t* J, uint64_t ptr) {
13357 + return (J->Heap_low[heap_num] <= ptr && ptr < J->Heap_high[heap_num]);
13360 +static int codecache_contains(jvm_agent_t* J, uint64_t ptr) {
13361 + int i;
13362 + for (i = 0; i < J->Number_of_heaps; ++i) {
13363 + if (codeheap_contains(i, J, ptr)) {
13364 + return 1;
13367 + return 0;
13370 +static uint64_t segment_for(int heap_num, jvm_agent_t* J, uint64_t p) {
13371 + return (p - J->Heap_low[heap_num]) >> J->SIZE_CodeCache_log2_segment;
13374 +static uint64_t block_at(int heap_num, jvm_agent_t* J, int i) {
13375 + return J->Heap_low[heap_num] + (i << J->SIZE_CodeCache_log2_segment);
13378 +static int find_start(jvm_agent_t* J, uint64_t ptr, uint64_t *startp) {
13379 + int err;
13380 + int i;
13382 + for (i = 0; i < J->Number_of_heaps; ++i) {
13383 + *startp = 0;
13384 + if (codeheap_contains(i, J, ptr)) {
13385 + int32_t used;
13386 + uint64_t segment = segment_for(i, J, ptr);
13387 + uint64_t block = J->Heap_segmap_low[i];
13388 + uint8_t tag;
13389 + err = ps_pread(J->P, block + segment, &tag, sizeof(tag));
13390 + CHECK_FAIL(err);
13391 + if (tag == 0xff)
13392 + return PS_OK;
13393 + while (tag > 0) {
13394 + err = ps_pread(J->P, block + segment, &tag, sizeof(tag));
13395 + CHECK_FAIL(err);
13396 + segment -= tag;
13398 + block = block_at(i, J, segment);
13399 + err = ps_pread(J->P, block + OFFSET_HeapBlockHeader_used, &used, sizeof(used));
13400 + CHECK_FAIL(err);
13401 + if (used) {
13402 + *startp = block + SIZE_HeapBlockHeader;
13405 + return PS_OK;
13408 + fail:
13409 + return -1;
13412 +static int find_jlong_constant(jvm_agent_t* J, const char *name, uint64_t* valuep) {
13413 + psaddr_t sym_addr;
13414 + int err = ps_pglobal_lookup(J->P, LIBJVM_SO, name, &sym_addr);
13415 + if (err == PS_OK) {
13416 + err = ps_pread(J->P, sym_addr, valuep, sizeof(uint64_t));
13417 + return err;
13419 + *valuep = -1;
13420 + return -1;
13423 +jvm_agent_t *Jagent_create(struct ps_prochandle *P, int vers) {
13424 + jvm_agent_t* J;
13425 + int err;
13427 + if (vers != JVM_DB_VERSION) {
13428 + errno = ENOTSUP;
13429 + return NULL;
13432 + J = (jvm_agent_t*)calloc(sizeof(struct jvm_agent), 1);
13434 + debug = getenv("LIBJVMDB_DEBUG") != NULL;
13435 + if (debug) debug = 3;
13437 + if (debug) {
13438 + fprintf(stderr, "Jagent_create: debug=%d\n", debug);
13439 +#ifdef X86_COMPILER2
13440 + fprintf(stderr, "Jagent_create: R_SP=%d, R_FP=%d, POINTER_SIZE=%d\n", R_SP, R_FP, POINTER_SIZE);
13441 +#endif /* X86_COMPILER2 */
13444 + J->P = P;
13446 + // Initialize the initial previous frame
13448 + J->prev_fr.fp = 0;
13449 + J->prev_fr.pc = 0;
13450 + J->prev_fr.sp = 0;
13451 + J->prev_fr.sender_sp = 0;
13453 + err = find_symbol(J, "__1cHnmethodG__vtbl_", &J->nmethod_vtbl);
13454 + CHECK_FAIL(err);
13455 + err = find_symbol(J, "__1cKBufferBlobG__vtbl_", &J->BufferBlob_vtbl);
13456 + if (err != PS_OK) J->BufferBlob_vtbl = 0;
13457 + err = find_symbol(J, "__1cICodeBlobG__vtbl_", &J->CodeBlob_vtbl);
13458 + CHECK_FAIL(err);
13459 + err = find_symbol(J, "__1cLRuntimeStubG__vtbl_", &J->RuntimeStub_vtbl);
13460 + CHECK_FAIL(err);
13461 + err = find_symbol(J, "__1cGMethodG__vtbl_", &J->Method_vtbl);
13462 + CHECK_FAIL(err);
13464 + err = parse_vmstructs(J);
13465 + CHECK_FAIL(err);
13466 + err = read_volatiles(J);
13467 + CHECK_FAIL(err);
13469 + return J;
13471 + fail:
13472 + Jagent_destroy(J);
13473 + return NULL;
13476 +void Jagent_destroy(jvm_agent_t *J) {
13477 + if (J != NULL) {
13478 + free(J);
13482 +static int is_method(jvm_agent_t* J, uint64_t methodPtr) {
13483 + uint64_t klass;
13484 + int err = read_pointer(J, methodPtr, &klass);
13485 + if (err != PS_OK) goto fail;
13486 + return klass == J->Method_vtbl;
13488 + fail:
13489 + return 0;
13492 +static int
13493 +name_for_methodPtr(jvm_agent_t* J, uint64_t methodPtr, char * result, size_t size)
13495 + short nameIndex;
13496 + short signatureIndex;
13497 + uint64_t constantPool;
13498 + uint64_t constMethod;
13499 + uint64_t nameSymbol;
13500 + uint64_t signatureSymbol;
13501 + uint64_t klassPtr;
13502 + uint64_t klassSymbol;
13503 + short klassSymbolLength;
13504 + short nameSymbolLength;
13505 + short signatureSymbolLength;
13506 + char * nameString = NULL;
13507 + char * klassString = NULL;
13508 + char * signatureString = NULL;
13509 + int err;
13511 + err = read_pointer(J, methodPtr + OFFSET_Method_constMethod, &constMethod);
13512 + CHECK_FAIL(err);
13513 + err = read_pointer(J, constMethod + OFFSET_ConstMethod_constants, &constantPool);
13514 + CHECK_FAIL(err);
13516 + /* To get name string */
13517 + err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_name_index, &nameIndex, 2);
13518 + CHECK_FAIL(err);
13519 + err = read_pointer(J, constantPool + nameIndex * POINTER_SIZE + SIZE_ConstantPool, &nameSymbol);
13520 + CHECK_FAIL(err);
13521 + // The symbol is a CPSlot and has lower bit set to indicate metadata
13522 + nameSymbol &= (~1); // remove metadata lsb
13523 + err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_length, &nameSymbolLength, 2);
13524 + CHECK_FAIL(err);
13525 + nameString = (char*)calloc(nameSymbolLength + 1, 1);
13526 + err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_body, nameString, nameSymbolLength);
13527 + CHECK_FAIL(err);
13529 + /* To get signature string */
13530 + err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_signature_index, &signatureIndex, 2);
13531 + CHECK_FAIL(err);
13532 + err = read_pointer(J, constantPool + signatureIndex * POINTER_SIZE + SIZE_ConstantPool, &signatureSymbol);
13533 + CHECK_FAIL(err);
13534 + signatureSymbol &= (~1); // remove metadata lsb
13535 + err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_length, &signatureSymbolLength, 2);
13536 + CHECK_FAIL(err);
13537 + signatureString = (char*)calloc(signatureSymbolLength + 1, 1);
13538 + err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_body, signatureString, signatureSymbolLength);
13539 + CHECK_FAIL(err);
13541 + /* To get klass string */
13542 + err = read_pointer(J, constantPool + OFFSET_ConstantPool_pool_holder, &klassPtr);
13543 + CHECK_FAIL(err);
13544 + err = read_pointer(J, klassPtr + OFFSET_Klass_name, &klassSymbol);
13545 + CHECK_FAIL(err);
13546 + err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_length, &klassSymbolLength, 2);
13547 + CHECK_FAIL(err);
13548 + klassString = (char*)calloc(klassSymbolLength + 1, 1);
13549 + err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_body, klassString, klassSymbolLength);
13550 + CHECK_FAIL(err);
13552 + result[0] = '\0';
13553 + if (snprintf(result, size,
13554 + "%s.%s%s",
13555 + klassString,
13556 + nameString,
13557 + signatureString) >= size) {
13558 + // truncation
13559 + goto fail;
13562 + if (nameString != NULL) free(nameString);
13563 + if (klassString != NULL) free(klassString);
13564 + if (signatureString != NULL) free(signatureString);
13566 + return PS_OK;
13568 + fail:
13569 + if (debug) {
13570 + fprintf(stderr, "name_for_methodPtr: FAIL \n\n");
13572 + if (nameString != NULL) free(nameString);
13573 + if (klassString != NULL) free(klassString);
13574 + if (signatureString != NULL) free(signatureString);
13575 + return -1;
13578 +static int nmethod_info(Nmethod_t *N)
13580 + jvm_agent_t *J = N->J;
13581 + uint64_t nm = N->nm;
13582 + int32_t err;
13584 + if (debug > 2 )
13585 + fprintf(stderr, "\t nmethod_info: BEGIN \n");
13587 + /* Instructions */
13588 + err = read_pointer(J, nm + OFFSET_CodeBlob_code_begin, &N->instrs_beg);
13589 + CHECK_FAIL(err);
13590 + err = read_pointer(J, nm + OFFSET_CodeBlob_code_end, &N->instrs_end);
13591 + CHECK_FAIL(err);
13592 + err = read_pointer(J, nm + OFFSET_nmethod_deopt_handler_begin, &N->deopt_beg);
13593 + CHECK_FAIL(err);
13594 + err = ps_pread(J->P, nm + OFFSET_nmethod_orig_pc_offset, &N->orig_pc_offset, SZ32);
13595 + CHECK_FAIL(err);
13597 + /* Metadata */
13598 + err = ps_pread(J->P, nm + OFFSET_nmethod_metadata_offset, &N->metadata_beg, SZ32);
13599 + CHECK_FAIL(err);
13600 + err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_data_begin, &N->metadata_end, SZ32);
13601 + CHECK_FAIL(err);
13603 + /* scopes_pcs */
13604 + err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_pcs_offset, &N->scopes_pcs_beg, SZ32);
13605 + CHECK_FAIL(err);
13606 + err = ps_pread(J->P, nm + OFFSET_nmethod_dependencies_offset, &N->scopes_pcs_end, SZ32);
13607 + CHECK_FAIL(err);
13609 + /* scopes_data */
13610 + err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_data_begin, &N->scopes_data_beg, POINTER_SIZE);
13611 + CHECK_FAIL(err);
13613 + if (debug > 2 ) {
13614 + N->scopes_data_end = N->scopes_pcs_beg;
13616 + fprintf(stderr, "\t nmethod_info: instrs_beg: %#x, instrs_end: %#x\n",
13617 + N->instrs_beg, N->instrs_end);
13619 + fprintf(stderr, "\t nmethod_info: deopt_beg: %#x \n",
13620 + N->deopt_beg);
13622 + fprintf(stderr, "\t nmethod_info: orig_pc_offset: %#x \n",
13623 + N->orig_pc_offset);
13625 + fprintf(stderr, "\t nmethod_info: metadata_beg: %#x, metadata_end: %#x\n",
13626 + N->metadata_beg, N->metadata_end);
13628 + fprintf(stderr, "\t nmethod_info: scopes_data_beg: %#x, scopes_data_end: %#x\n",
13629 + N->scopes_data_beg, N->scopes_data_end);
13631 + fprintf(stderr, "\t nmethod_info: scopes_pcs_beg: %#x, scopes_pcs_end: %#x\n",
13632 + N->scopes_pcs_beg, N->scopes_pcs_end);
13634 + fprintf(stderr, "\t nmethod_info: END \n\n");
13636 + return PS_OK;
13638 + fail:
13639 + return err;
13642 +static int
13643 +raw_read_int(jvm_agent_t* J, uint64_t *buffer, int32_t *val)
13645 + int shift = 0;
13646 + int value = 0;
13647 + uint8_t ch = 0;
13648 + int32_t err;
13649 + int32_t sum;
13650 + // Constants for UNSIGNED5 coding of Pack200
13651 + // see compressedStream.hpp
13652 + enum {
13653 + lg_H = 6,
13654 + H = 1<<lg_H,
13655 + BitsPerByte = 8,
13656 + L = (1<<BitsPerByte)-H,
13657 + };
13658 + int i;
13660 + err = ps_pread(J->P, (*buffer)++, &ch, sizeof(uint8_t));
13661 + CHECK_FAIL(err);
13662 + if (debug > 2)
13663 + fprintf(stderr, "\t\t\t raw_read_int: *buffer: %#llx, ch: %#x\n", *buffer, ch);
13665 + sum = ch;
13666 + if ( sum >= L ) {
13667 + int32_t lg_H_i = lg_H;
13668 + // Read maximum of 5 total bytes (we've already read 1).
13669 + // See CompressedReadStream::read_int_mb
13670 + for ( i = 0; i < 4; i++) {
13671 + err = ps_pread(J->P, (*buffer)++, &ch, sizeof(uint8_t));
13672 + CHECK_FAIL(err);
13673 + sum += ch << lg_H_i;
13674 + if (ch < L ) {
13675 + *val = sum;
13676 + return PS_OK;
13678 + lg_H_i += lg_H;
13681 + *val = sum;
13682 + return PS_OK;
13684 + fail:
13685 + return err;
13688 +static int
13689 +read_pair(jvm_agent_t* J, uint64_t *buffer, int32_t *bci, int32_t *line)
13691 + uint8_t next = 0;
13692 + int32_t bci_delta;
13693 + int32_t line_delta;
13694 + int32_t err;
13696 + if (debug > 2)
13697 + fprintf(stderr, "\t\t read_pair: BEGIN\n");
13699 + err = ps_pread(J->P, (*buffer)++, &next, sizeof(uint8_t));
13700 + CHECK_FAIL(err);
13702 + if (next == 0) {
13703 + if (debug > 2)
13704 + fprintf(stderr, "\t\t read_pair: END: next == 0\n");
13705 + return 1; /* stream terminated */
13707 + if (next == 0xFF) {
13708 + if (debug > 2)
13709 + fprintf(stderr, "\t\t read_pair: END: next == 0xFF\n");
13711 + /* Escape character, regular compression used */
13713 + err = raw_read_int(J, buffer, &bci_delta);
13714 + CHECK_FAIL(err);
13716 + err = raw_read_int(J, buffer, &line_delta);
13717 + CHECK_FAIL(err);
13719 + *bci += bci_delta;
13720 + *line += line_delta;
13722 + if (debug > 2) {
13723 + fprintf(stderr, "\t\t read_pair: delta = (line %d: %d)\n",
13724 + line_delta, bci_delta);
13725 + fprintf(stderr, "\t\t read_pair: unpack= (line %d: %d)\n",
13726 + *line, *bci);
13728 + } else {
13729 + /* Single byte compression used */
13730 + *bci += next >> 3;
13731 + *line += next & 0x7;
13732 + if (debug > 2) {
13733 + fprintf(stderr, "\t\t read_pair: delta = (line %d: %d)\n",
13734 + next & 0x7, next >> 3);
13735 + fprintf(stderr, "\t\t read_pair: unpack= (line %d: %d)\n",
13736 + *line, *bci);
13739 + if (debug > 2)
13740 + fprintf(stderr, "\t\t read_pair: END\n");
13741 + return PS_OK;
13743 + fail:
13744 + if (debug)
13745 + fprintf(stderr, "\t\t read_pair: FAIL\n");
13746 + return err;
13749 +static int
13750 +line_number_from_bci(jvm_agent_t* J, Vframe_t *vf)
13752 + uint64_t buffer;
13753 + uint16_t code_size;
13754 + uint64_t code_end_delta;
13755 + uint64_t constMethod;
13756 + int8_t access_flags;
13757 + int32_t best_bci = 0;
13758 + int32_t stream_bci = 0;
13759 + int32_t stream_line = 0;
13760 + int32_t err;
13762 + if (debug > 2) {
13763 + char name[256];
13764 + err = name_for_methodPtr(J, vf->method, name, 256);
13765 + CHECK_FAIL(err);
13766 + fprintf(stderr, "\t line_number_from_bci: BEGIN, method name: %s, targ bci: %d\n",
13767 + name, vf->bci);
13770 + err = read_pointer(J, vf->method + OFFSET_Method_constMethod, &constMethod);
13771 + CHECK_FAIL(err);
13773 + vf->line = 0;
13774 + err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_flags, &access_flags, sizeof(int8_t));
13775 + CHECK_FAIL(err);
13777 + if (!(access_flags & ConstMethod_has_linenumber_table)) {
13778 + if (debug > 2)
13779 + fprintf(stderr, "\t line_number_from_bci: END: !HAS_LINE_NUMBER_TABLE \n\n");
13780 + return PS_OK;
13783 + /* The line numbers are a short array of 2-tuples [start_pc, line_number].
13784 + * Not necessarily sorted and not necessarily one-to-one.
13785 + */
13787 + err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_code_size, &code_size, SZ16);
13788 + CHECK_FAIL(err);
13790 + /* inlined_table_start() */
13791 + code_end_delta = (uint64_t) (access_flags & AccessFlags_NATIVE) ? 2*POINTER_SIZE : 0;
13792 + buffer = constMethod + (uint64_t) SIZE_ConstMethod + (uint64_t) code_size + code_end_delta;
13794 + if (debug > 2) {
13795 + fprintf(stderr, "\t\t line_number_from_bci: method: %#llx, native: %d\n",
13796 + vf->method, (access_flags & AccessFlags_NATIVE));
13797 + fprintf(stderr, "\t\t line_number_from_bci: buffer: %#llx, code_size: %d\n",
13798 + buffer, (int) code_size);
13801 + while (read_pair(J, &buffer, &stream_bci, &stream_line) == 0) {
13802 + if (stream_bci == vf->bci) {
13803 + /* perfect match */
13804 + if (debug > 2)
13805 + fprintf(stderr, "\t line_number_from_bci: END: exact line: %d \n\n", vf->line);
13806 + vf->line = stream_line;
13807 + return PS_OK;
13808 + } else {
13809 + /* update best_bci/line */
13810 + if (stream_bci < vf->bci && stream_bci >= best_bci) {
13811 + best_bci = stream_bci;
13812 + vf->line = stream_line;
13813 + if (debug > 2) {
13814 + fprintf(stderr, "\t line_number_from_bci: best_bci: %d, best_line: %d\n",
13815 + best_bci, vf->line);
13820 + if (debug > 2)
13821 + fprintf(stderr, "\t line_number_from_bci: END: line: %d \n\n", vf->line);
13822 + return PS_OK;
13824 + fail:
13825 + if (debug)
13826 + fprintf(stderr, "\t line_number_from_bci: FAIL\n");
13827 + return err;
13830 +static int
13831 +get_real_pc(Nmethod_t *N, uint64_t pc_desc, uint64_t *real_pc)
13833 + int32_t pc_offset;
13834 + int32_t err;
13836 + err = ps_pread(N->J->P, pc_desc + OFFSET_PcDesc_pc_offset, &pc_offset, SZ32);
13837 + CHECK_FAIL(err);
13839 + *real_pc = N->instrs_beg + pc_offset;
13840 + if (debug > 2) {
13841 + fprintf(stderr, "\t\t get_real_pc: pc_offset: %lx, real_pc: %llx\n",
13842 + pc_offset, *real_pc);
13844 + return PS_OK;
13846 + fail:
13847 + return err;
13850 +/* Finds a PcDesc with real-pc equal to N->pc */
13851 +static int pc_desc_at(Nmethod_t *N)
13853 + uint64_t pc_diff = 999;
13854 + int32_t offs;
13855 + int32_t err;
13857 + if (debug > 2)
13858 + fprintf(stderr, "\t pc_desc_at: BEGIN\n");
13860 + N->vf_cnt = 0;
13861 + N->pc_desc = 0;
13863 + for (offs = N->scopes_pcs_beg; offs < N->scopes_pcs_end; offs += SIZE_PcDesc) {
13864 + uint64_t pd;
13865 + uint64_t best_pc_diff = 16; /* some approximation */
13866 + uint64_t real_pc = 0;
13868 + pd = N->nm + offs;
13869 + err = get_real_pc(N, pd, &real_pc);
13870 + CHECK_FAIL(err);
13872 + pc_diff = real_pc - N->pc;
13874 + /* In general, this fragment should work */
13875 + if (pc_diff == 0) {
13876 + N->pc_desc = pd;
13877 + if (debug) {
13878 + fprintf(stderr, "\t pc_desc_at: END: pc_desc: FOUND: %#lx \n\n", pd);
13880 + return PS_OK;
13882 + /* This fragment is to be able to find out an appropriate
13883 + * pc_desc entry even if pc_desc info is inaccurate.
13884 + */
13885 + if (best_pc_diff > pc_diff && pc_diff > 0) {
13886 + best_pc_diff = pc_diff;
13887 + N->pc_desc = pd;
13890 + if (debug) {
13891 + fprintf(stderr, "\t pc_desc_at: END: pc_desc NOT FOUND");
13892 + if (pc_diff < 20)
13893 + fprintf(stderr, ", best pc_diff: %d\n\n", pc_diff);
13894 + else
13895 + fprintf(stderr, "\n\n");
13897 + return PS_OK;
13899 + fail:
13900 + return err;
13903 +static int
13904 +scope_desc_at(Nmethod_t *N, int32_t decode_offset, Vframe_t *vf)
13906 + uint64_t buffer;
13907 + int32_t err;
13909 + if (debug > 2) {
13910 + fprintf(stderr, "\t\t scope_desc_at: BEGIN \n");
13913 + buffer = N->scopes_data_beg + decode_offset;
13915 + err = raw_read_int(N->J, &buffer, &vf->sender_decode_offset);
13916 + CHECK_FAIL(err);
13918 + err = raw_read_int(N->J, &buffer, &vf->methodIdx);
13919 + CHECK_FAIL(err);
13921 + err = raw_read_int(N->J, &buffer, &vf->bci);
13922 + CHECK_FAIL(err);
13924 + if (debug > 2) {
13925 + fprintf(stderr, "\t\t scope_desc_at: sender_decode_offset: %#x\n",
13926 + vf->sender_decode_offset);
13927 + fprintf(stderr, "\t\t scope_desc_at: methodIdx: %d\n", vf->methodIdx);
13928 + fprintf(stderr, "\t\t scope_desc_at: bci: %d\n", vf->bci);
13930 + fprintf(stderr, "\t\t scope_desc_at: END \n\n");
13932 + return PS_OK;
13934 + fail:
13935 + return err;
13938 +static int scopeDesc_chain(Nmethod_t *N) {
13939 + int32_t decode_offset = 0;
13940 + int32_t err;
13942 + if (debug > 2) {
13943 + fprintf(stderr, "\t scopeDesc_chain: BEGIN\n");
13946 + err = ps_pread(N->J->P, N->pc_desc + OFFSET_PcDesc_scope_decode_offset,
13947 + &decode_offset, SZ32);
13948 + CHECK_FAIL(err);
13950 + while (decode_offset > 0) {
13951 + Vframe_t *vf = &N->vframes[N->vf_cnt];
13953 + if (debug > 2) {
13954 + fprintf(stderr, "\t scopeDesc_chain: decode_offset: %#x\n", decode_offset);
13957 + err = scope_desc_at(N, decode_offset, vf);
13958 + CHECK_FAIL(err);
13960 + if (vf->methodIdx > ((N->metadata_end - N->metadata_beg) / POINTER_SIZE)) {
13961 + fprintf(stderr, "\t scopeDesc_chain: (methodIdx > metadata length) !\n");
13962 + return -1;
13964 + err = read_pointer(N->J, N->nm + N->metadata_beg + (vf->methodIdx-1)*POINTER_SIZE,
13965 + &vf->method);
13966 + CHECK_FAIL(err);
13968 + if (vf->method) {
13969 + N->vf_cnt++;
13970 + err = line_number_from_bci(N->J, vf);
13971 + CHECK_FAIL(err);
13972 + if (debug > 2) {
13973 + fprintf(stderr, "\t scopeDesc_chain: method: %#8llx, line: %d\n",
13974 + vf->method, vf->line);
13977 + decode_offset = vf->sender_decode_offset;
13979 + if (debug > 2) {
13980 + fprintf(stderr, "\t scopeDesc_chain: END \n\n");
13982 + return PS_OK;
13984 + fail:
13985 + if (debug) {
13986 + fprintf(stderr, "\t scopeDesc_chain: FAIL \n\n");
13988 + return err;
13992 +static int
13993 +name_for_nmethod(jvm_agent_t* J,
13994 + uint64_t nm,
13995 + uint64_t pc,
13996 + uint64_t method,
13997 + char *result,
13998 + size_t size,
13999 + Jframe_t *jframe
14000 +) {
14001 + Nmethod_t *N;
14002 + Vframe_t *vf;
14003 + int32_t err;
14004 + int deoptimized = 0;
14006 + if (debug) {
14007 + fprintf(stderr, "name_for_nmethod: BEGIN: nmethod: %#llx, pc: %#llx\n", nm, pc);
14009 + if (J->N == NULL) {
14010 + J->N = (Nmethod_t *) malloc(sizeof(Nmethod_t));
14012 + memset(J->N, 0, sizeof(Nmethod_t)); /* Initial stat: all values are zeros */
14013 + N = J->N;
14014 + N->J = J;
14015 + N->nm = nm;
14016 + N->pc = pc;
14017 + N->jframe = jframe;
14019 + err = nmethod_info(N);
14020 + CHECK_FAIL(err);
14021 + if (debug) {
14022 + fprintf(stderr, "name_for_nmethod: pc: %#llx, deopt_pc: %#llx\n",
14023 + pc, N->deopt_beg);
14026 + /* check for a deoptimized frame */
14027 + if ( pc == N->deopt_beg) {
14028 + uint64_t base;
14029 + if (debug) {
14030 + fprintf(stderr, "name_for_nmethod: found deoptimized frame\n");
14032 + if (J->prev_fr.sender_sp != 0) {
14033 + base = J->prev_fr.sender_sp + N->orig_pc_offset;
14034 + } else {
14035 + base = J->curr_fr.sp + N->orig_pc_offset;
14037 + err = read_pointer(J, base, &N->pc);
14038 + CHECK_FAIL(err);
14039 + if (debug) {
14040 + fprintf(stderr, "name_for_nmethod: found deoptimized frame converting pc from %#8llx to %#8llx\n",
14041 + pc, N->pc);
14043 + deoptimized = 1;
14046 + err = pc_desc_at(N);
14047 + CHECK_FAIL(err);
14049 + if (N->pc_desc > 0) {
14050 + jframe->locinf = 1;
14051 + err = scopeDesc_chain(N);
14052 + CHECK_FAIL(err);
14054 + result[0] = COMP_METHOD_SIGN;
14055 + vf = &N->vframes[0];
14056 + if (N->vf_cnt > 0) {
14057 + jframe->vf_cnt = N->vf_cnt;
14058 + jframe->bci = vf->bci;
14059 + jframe->line = vf->line;
14060 + err = name_for_methodPtr(J, N->vframes[0].method, result+1, size-1);
14061 + CHECK_FAIL(err);
14062 + } else {
14063 + err = name_for_methodPtr(J, method, result+1, size-1);
14064 + CHECK_FAIL(err);
14066 + if (deoptimized) {
14067 + strncat(result, " [deoptimized frame]; ", size - strlen(result) - 1);
14068 + } else {
14069 + strncat(result, " [compiled] ", size - strlen(result) - 1);
14071 + if (debug)
14072 + fprintf(stderr, "name_for_nmethod: END: method name: %s, vf_cnt: %d\n\n",
14073 + result, N->vf_cnt);
14074 + return PS_OK;
14076 + fail:
14077 + if (debug)
14078 + fprintf(stderr, "name_for_nmethod: FAIL \n\n");
14079 + return err;
14082 +static int
14083 +name_for_imethod(jvm_agent_t* J,
14084 + uint64_t bcp,
14085 + uint64_t method,
14086 + char *result,
14087 + size_t size,
14088 + Jframe_t *jframe
14089 +) {
14090 + uint64_t bci;
14091 + uint64_t constMethod;
14092 + Vframe_t vframe = {0};
14093 + Vframe_t *vf = &vframe;
14094 + int32_t err;
14096 + err = read_pointer(J, method + OFFSET_Method_constMethod, &constMethod);
14097 + CHECK_FAIL(err);
14099 + bci = bcp - (constMethod + (uint64_t) SIZE_ConstMethod);
14101 + if (debug)
14102 + fprintf(stderr, "\t name_for_imethod: BEGIN: method: %#llx\n", method);
14104 + err = name_for_methodPtr(J, method, result, size);
14105 + CHECK_FAIL(err);
14106 + if (debug)
14107 + fprintf(stderr, "\t name_for_imethod: method name: %s\n", result);
14109 + if (bci > 0) {
14110 + vf->method = method;
14111 + vf->bci = bci;
14112 + err = line_number_from_bci(J, vf);
14113 + CHECK_FAIL(err);
14115 + jframe->bci = vf->bci;
14116 + jframe->line = vf->line;
14117 + jframe->locinf = 1;
14119 + if (debug) {
14120 + fprintf(stderr, "\t name_for_imethod: END: bci: %d, line: %d\n\n",
14121 + vf->bci, vf->line);
14123 + return PS_OK;
14125 + fail:
14126 + if (debug)
14127 + fprintf(stderr, "\t name_for_imethod: FAIL\n");
14128 + return err;
14131 +static int
14132 +name_for_codecache(jvm_agent_t* J, uint64_t fp, uint64_t pc, char * result,
14133 + size_t size, Jframe_t *jframe, int* is_interpreted)
14135 + uint64_t start;
14136 + uint64_t vtbl;
14137 + int32_t err;
14138 + *is_interpreted = 0;
14140 + result[0] = '\0';
14142 + err = find_start(J, pc, &start);
14143 + CHECK_FAIL(err);
14145 + err = read_pointer(J, start, &vtbl);
14146 + CHECK_FAIL(err);
14148 + if (vtbl == J->nmethod_vtbl) {
14149 + uint64_t method;
14151 + err = read_pointer(J, start + OFFSET_nmethod_method, &method);
14152 + CHECK_FAIL(err);
14154 + if (debug) {
14155 + fprintf(stderr, "name_for_codecache: start: %#8llx, pc: %#8llx, method: %#8llx \n",
14156 + start, pc, method);
14158 + err = name_for_nmethod(J, start, pc, method, result, size, jframe);
14159 + CHECK_FAIL(err);
14160 + } else if (vtbl == J->BufferBlob_vtbl) {
14161 + const char * name;
14163 + err = read_string_pointer(J, start + OFFSET_CodeBlob_name, &name);
14165 + /*
14166 + * Temporary usage of string "Interpreter".
14167 + * We need some other way to distinguish "StubRoutines"
14168 + * and regular interpreted frames.
14169 + */
14170 + if (err == PS_OK && strncmp(name, "Interpreter", 11) == 0) {
14171 + *is_interpreted = 1;
14172 + if (is_method(J, J->methodPtr)) {
14173 + return name_for_imethod(J, J->bcp, J->methodPtr, result, size, jframe);
14177 + if (err == PS_OK) {
14178 + strncpy(result, name, size);
14179 + free((void*)name);
14180 + } else {
14181 + strncpy(result, "<unknown BufferBlob>", size);
14183 + /* return PS_OK; */
14184 + } else {
14185 + const char * name;
14187 + err = read_string_pointer(J, start + OFFSET_CodeBlob_name, &name);
14188 + if (err == PS_OK) {
14189 + strncpy(result, name, size);
14190 + free((void*)name);
14191 + } else {
14192 + strncpy(result, "<unknown CodeBlob>", size);
14193 + WARN1("unknown CodeBlob: vtbl = 0x%x", vtbl);
14196 + result[size-1] = '\0';
14198 +#ifdef X86_COMPILER2
14199 + if (vtbl != J->RuntimeStub_vtbl) {
14200 + uint64_t trial_pc;
14201 + int frame_size;
14202 + err = ps_pread(J->P, start + OFFSET_CodeBlob_frame_size,
14203 + &frame_size, SZ32);
14204 + CHECK_FAIL(err);
14206 + // frame_size is in words, we want bytes.
14207 + frame_size *= POINTER_SIZE; /* word => byte conversion */
14209 + /*
14210 + Because c2 doesn't use FP as a framepointer the value of sp/fp we receive
14211 + in the initial entry to a set of stack frames containing server frames
14212 + will pretty much be nonsense. We can detect that nonsense by looking to
14213 + see if the PC we received is correct if we look at the expected storage
14214 + location in relation to the FP (ie. POINTER_SIZE(FP) )
14215 + */
14217 + err = read_pointer(J, fp + POINTER_SIZE , &trial_pc);
14218 + if ( (err != PS_OK || trial_pc != pc) && frame_size > 0 ) {
14219 + // Either we couldn't even read at the "fp" or the pc didn't match
14220 + // both are sure clues that the fp is bogus. We no search the stack
14221 + // for a reasonable number of words trying to find the bogus fp
14222 + // and the current pc in adjacent words. The we will be able to
14223 + // deduce an approximation of the frame pointer and actually get
14224 + // the correct stack pointer. Which we can then unwind for the
14225 + // next frame.
14226 + int i;
14227 + uint64_t check;
14228 + uint64_t base = J->curr_fr.sp;
14229 + uint64_t prev_fp = 0;
14230 + for ( i = 0; i < frame_size * 5 ; i++, base += POINTER_SIZE ) {
14231 + err = read_pointer(J, base , &check);
14232 + CHECK_FAIL(err);
14233 + if (check == fp) {
14234 + base += POINTER_SIZE;
14235 + err = read_pointer(J, base , &check);
14236 + CHECK_FAIL(err);
14237 + if (check == pc) {
14238 + if (debug) {
14239 + fprintf(stderr, "name_for_codecache: found matching fp/pc combo at 0x%llx\n", base - POINTER_SIZE);
14241 + prev_fp = base - 2 * POINTER_SIZE;
14242 + break;
14246 + if ( prev_fp != 0 ) {
14247 + // real_sp is the sp we should have received for this frame
14248 + uint64_t real_sp = prev_fp + 2 * POINTER_SIZE;
14249 + // +POINTER_SIZE because callee owns the return address so caller's sp is +1 word
14250 + jframe->new_sp = real_sp + frame_size + POINTER_SIZE;
14251 + err = read_pointer(J, jframe->new_sp - POINTER_SIZE , &jframe->new_pc);
14252 + CHECK_FAIL(err);
14253 + err = read_pointer(J, jframe->new_sp - 2*POINTER_SIZE, &jframe->new_fp);
14254 + CHECK_FAIL(err);
14255 + return PS_OK;
14259 + /* A prototype to workaround FP absence */
14260 + /*
14261 + * frame_size can be 0 for StubRoutines (1) frame.
14262 + * In this case it should work with fp as usual.
14263 + */
14264 + if (frame_size > 0) {
14265 + jframe->new_fp = J->prev_fr.fp + frame_size;
14266 + jframe->new_sp = jframe->new_fp + 2 * POINTER_SIZE;
14267 + } else {
14268 + memset(&J->curr_fr, 0, sizeof(Frame_t));
14269 + err = read_pointer(J, fp, &jframe->new_fp);
14270 + CHECK_FAIL(err);
14272 + err = read_pointer(J, jframe->new_fp + POINTER_SIZE, &jframe->new_pc);
14273 + CHECK_FAIL(err);
14275 + if (debug) {
14276 + fprintf(stderr, "name_for_codecache: %s, frame_size=%#lx\n",
14277 + result, frame_size);
14278 + fprintf(stderr, "name_for_codecache: prev_fr.fp=%#lx, fp=%#lx\n",
14279 + J->prev_fr.fp, jframe->new_fp);
14282 +#endif /* X86_COMPILER2 */
14284 + return PS_OK;
14286 + fail:
14287 + return err;
14290 +int Jget_vframe(jvm_agent_t* J, int vframe_no,
14291 + char *name, size_t size, Jframe_t *jframe)
14293 + Nmethod_t *N = J->N;
14294 + Vframe_t *vf;
14295 + int32_t err;
14297 + if (vframe_no >= N->vf_cnt) {
14298 + (void) sprintf(name, "Wrong inlinedMethod%1d()", vframe_no);
14299 + return -1;
14301 + vf = N->vframes + vframe_no;
14302 + name[0] = COMP_METHOD_SIGN;
14303 + err = name_for_methodPtr(J, vf->method, name + 1, size);
14304 + CHECK_FAIL(err);
14306 + jframe->bci = vf->bci;
14307 + jframe->line = vf->line;
14308 + if (debug) {
14309 + fprintf(stderr, "\t Jget_vframe: method name: %s, line: %d\n",
14310 + name, vf->line);
14312 + return PS_OK;
14314 + fail:
14315 + if (debug) {
14316 + fprintf(stderr, "\t Jget_vframe: FAIL\n");
14318 + return err;
14321 +#define MAX_SYM_SIZE 256
14323 +int Jlookup_by_regs(jvm_agent_t* J, const prgregset_t regs, char *name,
14324 + size_t size, Jframe_t *jframe) {
14325 + uintptr_t fp;
14326 + uintptr_t pc;
14327 + /* arguments given to read_pointer need to be worst case sized */
14328 + uint64_t methodPtr = 0;
14329 + uint64_t sender_sp;
14330 + uint64_t bcp = 0;
14331 + int is_interpreted = 0;
14332 + int result = PS_OK;
14333 + int err = PS_OK;
14335 + if (J == NULL) {
14336 + return -1;
14339 + jframe->vf_cnt = 1;
14340 + jframe->new_fp = 0;
14341 + jframe->new_pc = 0;
14342 + jframe->line = 0;
14343 + jframe->bci = 0;
14344 + jframe->locinf = 0;
14346 + read_volatiles(J);
14347 + pc = (uintptr_t) regs[R_PC];
14348 + J->curr_fr.pc = pc;
14349 + J->curr_fr.fp = regs[R_FP];
14350 + J->curr_fr.sp = regs[R_SP];
14352 + if (debug)
14353 + fprintf(stderr, "Jlookup_by_regs: BEGINs: fp=%#lx, pc=%#lx\n", regs[R_FP], pc);
14355 +#if defined(i386) || defined(__i386) || defined(__amd64)
14357 + fp = (uintptr_t) regs[R_FP];
14358 + if (J->prev_fr.fp == 0) {
14359 +#ifdef X86_COMPILER2
14360 + /* A workaround for top java frames */
14361 + J->prev_fr.fp = (uintptr_t)(regs[R_SP] - 2 * POINTER_SIZE);
14362 +#else
14363 + J->prev_fr.fp = (uintptr_t)(regs[R_SP] - POINTER_SIZE);
14364 +#endif /* COMPILER2 */
14366 + if (debug > 2) {
14367 + printf("Jlookup_by_regs: J->prev_fr.fp = %#lx\n", J->prev_fr.fp);
14370 + if (read_pointer(J, fp + OFFSET_interpreter_frame_method, &methodPtr) != PS_OK) {
14371 + methodPtr = 0;
14373 + if (read_pointer(J, fp + OFFSET_interpreter_frame_sender_sp, &sender_sp) != PS_OK) {
14374 + sender_sp = 0;
14376 + if (read_pointer(J, fp + OFFSET_interpreter_frame_bcp_offset, &bcp) != PS_OK) {
14377 + bcp = 0;
14379 +#endif /* i386 */
14381 + J->methodPtr = methodPtr;
14382 + J->bcp = bcp;
14384 + /* On x86 with C2 JVM: native frame may have wrong regs[R_FP]
14385 + * For example: JVM_SuspendThread frame poins to the top interpreted frame.
14386 + * If we call is_method(J, methodPtr) before codecache_contains(J, pc)
14387 + * then we go over and omit both: nmethod and I2CAdapter frames.
14388 + * Note, that regs[R_PC] is always correct if frame defined correctly.
14389 + * So it is better to call codecache_contains(J, pc) from the beginning.
14390 + */
14391 +#ifndef X86_COMPILER2
14392 + if (is_method(J, J->methodPtr)) {
14393 + result = name_for_imethod(J, bcp, J->methodPtr, name, size, jframe);
14394 + /* If the methodPtr is a method then this is highly likely to be
14395 + an interpreter frame */
14396 + if (result >= 0) {
14397 + is_interpreted = 1;
14399 + } else
14400 +#endif /* ! X86_COMPILER2 */
14402 + if (codecache_contains(J, pc)) {
14403 + result = name_for_codecache(J, fp, pc, name, size, jframe, &is_interpreted);
14405 +#ifdef X86_COMPILER2
14406 + else if (is_method(J, J->methodPtr)) {
14407 + result = name_for_imethod(J, bcp, J->methodPtr, name, size, jframe);
14408 + /* If the methodPtr is a method then this is highly likely to be
14409 + an interpreter frame */
14410 + if (result >= 0) {
14411 + is_interpreted = 1;
14414 +#endif /* X86_COMPILER2 */
14415 + else {
14416 + if (debug) {
14417 + fprintf(stderr, "Jlookup_by_regs: END with -1\n\n");
14419 + result = -1;
14421 + if (!is_interpreted) {
14422 + sender_sp = 0;
14424 + J->curr_fr.sender_sp = sender_sp;
14426 +#ifdef X86_COMPILER2
14427 + if (!J->curr_fr.fp) {
14428 + J->curr_fr.fp = (jframe->new_fp) ? jframe->new_fp : (uintptr_t)regs[R_FP];
14430 + if (!jframe->new_pc && jframe->new_fp) {
14431 + // This seems dubious
14432 + read_pointer(J, jframe->new_fp + POINTER_SIZE, &jframe->new_pc);
14433 + CHECK_FAIL(err);
14434 + if (debug > 2) {
14435 + printf("Jlookup_by_regs: (update pc) jframe->new_fp: %#llx, jframe->new_pc: %#llx\n",
14436 + jframe->new_fp, jframe->new_pc);
14440 +#endif /* X86_COMPILER2 */
14441 + J->prev_fr = J->curr_fr;
14443 + if (debug)
14444 + fprintf(stderr, "Jlookup_by_regs: END\n\n");
14446 + return result;
14448 + fail:
14449 + return err;
14452 +void update_gregs(prgregset_t gregs, Jframe_t jframe) {
14453 +#ifdef X86_COMPILER2
14454 + if (debug > 0) {
14455 + 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]);
14457 + /*
14458 + * A workaround for java C2 frames with unconventional FP.
14459 + * may have to modify regset with new values for FP/PC/SP when needed.
14460 + */
14461 + if (jframe.new_sp) {
14462 + *((uintptr_t *) &gregs[R_SP]) = (uintptr_t) jframe.new_sp;
14463 + } else {
14464 + // *((uintptr_t *) &gregs[R_SP]) = (uintptr_t) gregs[R_FP] + 2 * POINTER_SIZE;
14467 + if (jframe.new_fp) {
14468 + *((uintptr_t *) &gregs[R_FP]) = (uintptr_t) jframe.new_fp;
14470 + if (jframe.new_pc) {
14471 + *((uintptr_t *) &gregs[R_PC]) = (uintptr_t) jframe.new_pc;
14473 + if (debug > 0) {
14474 + 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]);
14476 +#endif /* X86_COMPILER2 */
14480 + * Iterates over java frames at current location given by 'gregs'.
14482 + * Returns -1 if no java frames are present or if an error is encountered.
14483 + * Returns the result of calling 'func' if the return value is non-zero.
14484 + * Returns 0 otherwise.
14485 + */
14486 +int Jframe_iter(jvm_agent_t *J, prgregset_t gregs, java_stack_f *func, void* cld) {
14487 + char buf[MAX_SYM_SIZE + 1];
14488 + Jframe_t jframe;
14489 + int i = 0, res;
14490 +#ifdef X86_COMPILER2
14491 + if (debug > 0) {
14492 + fprintf(stderr, "Jframe_iter: Entry sp = 0x%llx, fp = 0x%llx, pc = 0x%llx\n", gregs[R_SP], gregs[R_FP], gregs[R_PC]);
14494 +#endif /* X86_COMPILER2 */
14496 + memset(&jframe, 0, sizeof(Jframe_t));
14497 + memset(buf, 0, sizeof(buf));
14498 + res = Jlookup_by_regs(J, gregs, buf, sizeof(buf), &jframe);
14499 + if (res != PS_OK)
14500 + return (-1);
14503 + res = func(cld, gregs, buf, (jframe.locinf)? jframe.bci : -1,
14504 + jframe.line, NULL);
14505 + if (res != 0) {
14506 + update_gregs(gregs, jframe);
14507 + return (res);
14509 + for (i = 1; i < jframe.vf_cnt; i++) {
14510 + Jget_vframe(J, i, buf, sizeof(buf), &jframe);
14511 + res = func(cld, gregs, buf, (jframe.locinf)? jframe.bci : -1,
14512 + jframe.line, NULL);
14513 + if (res != 0) {
14514 + update_gregs(gregs, jframe);
14515 + return (res);
14518 + update_gregs(gregs, jframe);
14519 + return (0);
14521 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/solaris/native/libjvm_db/libjvm_db.h jdk23u-jdk-23-36/src/java.base/solaris/native/libjvm_db/libjvm_db.h
14522 --- jdk23u-jdk-23-36.orig/src/java.base/solaris/native/libjvm_db/libjvm_db.h 1970-01-01 01:00:00.000000000 +0100
14523 +++ jdk23u-jdk-23-36/src/java.base/solaris/native/libjvm_db/libjvm_db.h 2024-08-17 19:50:33.158977868 +0200
14524 @@ -0,0 +1,69 @@
14526 + * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
14527 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
14529 + * This code is free software; you can redistribute it and/or modify it
14530 + * under the terms of the GNU General Public License version 2 only, as
14531 + * published by the Free Software Foundation.
14533 + * This code is distributed in the hope that it will be useful, but WITHOUT
14534 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14535 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14536 + * version 2 for more details (a copy is included in the LICENSE file that
14537 + * accompanied this code).
14539 + * You should have received a copy of the GNU General Public License version
14540 + * 2 along with this work; if not, write to the Free Software Foundation,
14541 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
14543 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
14544 + * or visit www.oracle.com if you need additional information or have any
14545 + * questions.
14547 + */
14549 +#ifndef OS_SOLARIS_DTRACE_LIBJVM_DB_H
14550 +#define OS_SOLARIS_DTRACE_LIBJVM_DB_H
14552 +#include <proc_service.h>
14553 +#include "jni.h"
14555 +#ifdef __cplusplus
14556 +extern "C" {
14557 +#endif
14559 +typedef struct jvm_agent jvm_agent_t;
14561 +#define JVM_DB_VERSION 1
14563 +JNIEXPORT jvm_agent_t *Jagent_create(struct ps_prochandle *P, int vers);
14566 + * Called from Jframe_iter() for each java frame. If it returns 0, then
14567 + * Jframe_iter() proceeds to the next frame. Otherwise, the return value is
14568 + * immediately returned to the caller of Jframe_iter().
14570 + * Parameters:
14571 + * 'cld' is client supplied data (to maintain iterator state, if any).
14572 + * 'name' is java method name.
14573 + * 'bci' is byte code index. it will be -1 if not available.
14574 + * 'line' is java source line number. it will be 0 if not available.
14575 + * 'handle' is an abstract client handle, reserved for future expansions
14576 + */
14578 +typedef int java_stack_f(void *cld, const prgregset_t regs, const char* name, int bci, int line, void *handle);
14581 + * Iterates over the java frames at the current location. Returns -1 if no java
14582 + * frames were found, or if there was some unrecoverable error. Otherwise,
14583 + * returns the last value returned from 'func'.
14584 + */
14585 +JNIEXPORT int Jframe_iter(jvm_agent_t *agent, prgregset_t gregs, java_stack_f *func, void* cld);
14587 +JNIEXPORT void Jagent_destroy(jvm_agent_t *J);
14589 +#ifdef __cplusplus
14590 +} /* extern "C" */
14591 +#endif /* __cplusplus */
14593 +#endif // OS_SOLARIS_DTRACE_LIBJVM_DB_H
14594 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/solaris/native/libjvm_dtrace/jvm_dtrace.c jdk23u-jdk-23-36/src/java.base/solaris/native/libjvm_dtrace/jvm_dtrace.c
14595 --- jdk23u-jdk-23-36.orig/src/java.base/solaris/native/libjvm_dtrace/jvm_dtrace.c 1970-01-01 01:00:00.000000000 +0100
14596 +++ jdk23u-jdk-23-36/src/java.base/solaris/native/libjvm_dtrace/jvm_dtrace.c 2024-08-17 19:50:33.159474454 +0200
14597 @@ -0,0 +1,562 @@
14599 + * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
14600 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
14602 + * This code is free software; you can redistribute it and/or modify it
14603 + * under the terms of the GNU General Public License version 2 only, as
14604 + * published by the Free Software Foundation.
14606 + * This code is distributed in the hope that it will be useful, but WITHOUT
14607 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14608 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14609 + * version 2 for more details (a copy is included in the LICENSE file that
14610 + * accompanied this code).
14612 + * You should have received a copy of the GNU General Public License version
14613 + * 2 along with this work; if not, write to the Free Software Foundation,
14614 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
14616 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
14617 + * or visit www.oracle.com if you need additional information or have any
14618 + * questions.
14620 + */
14622 +#include <door.h>
14623 +#include <errno.h>
14624 +#include <fcntl.h>
14625 +#include <limits.h>
14626 +#include <poll.h>
14627 +#include <signal.h>
14628 +#include <stdarg.h>
14629 +#include <stdio.h>
14630 +#include <stdlib.h>
14631 +#include <string.h>
14632 +#include <sys/types.h>
14633 +#include <sys/stat.h>
14634 +#include <thread.h>
14635 +#include <unistd.h>
14636 +#include "jvm_dtrace.h"
14638 +// NOTE: These constants are used in JVM code as well.
14639 +// KEEP JVM CODE IN SYNC if you are going to change these...
14641 +#define DTRACE_ALLOC_PROBES 0x1
14642 +#define DTRACE_METHOD_PROBES 0x2
14643 +#define DTRACE_MONITOR_PROBES 0x4
14644 +#define DTRACE_ALL_PROBES -1
14646 +// generic error messages
14647 +#define JVM_ERR_OUT_OF_MEMORY "out of memory (native heap)"
14648 +#define JVM_ERR_INVALID_PARAM "invalid input parameter(s)"
14649 +#define JVM_ERR_NULL_PARAM "input paramater is NULL"
14651 +// error messages for attach
14652 +#define JVM_ERR_CANT_OPEN_DOOR "cannot open door file"
14653 +#define JVM_ERR_CANT_CREATE_ATTACH_FILE "cannot create attach file"
14654 +#define JVM_ERR_DOOR_FILE_PERMISSION "door file is not secure"
14655 +#define JVM_ERR_CANT_SIGNAL "cannot send SIGQUIT to target"
14657 +// error messages for enable probe
14658 +#define JVM_ERR_DOOR_CMD_SEND "door command send failed"
14659 +#define JVM_ERR_DOOR_CANT_READ_STATUS "cannot read door command status"
14660 +#define JVM_ERR_DOOR_CMD_STATUS "door command error status"
14662 +// error message for detach
14663 +#define JVM_ERR_CANT_CLOSE_DOOR "cannot close door file"
14665 +#define RESTARTABLE(_cmd, _result) do { \
14666 + do { \
14667 + _result = _cmd; \
14668 + } while((_result == -1) && (errno == EINTR)); \
14669 +} while(0)
14671 +struct _jvm_t {
14672 + pid_t pid;
14673 + int door_fd;
14676 +static int libjvm_dtrace_debug;
14677 +static void print_debug(const char* fmt,...) {
14678 + if (libjvm_dtrace_debug) {
14679 + va_list alist;
14680 + va_start(alist, fmt);
14681 + fputs("libjvm_dtrace DEBUG: ", stderr);
14682 + vfprintf(stderr, fmt, alist);
14683 + va_end(alist);
14687 +/* Key for thread local error message */
14688 +static thread_key_t jvm_error_key;
14690 +/* init function for this library */
14691 +static void init_jvm_dtrace() {
14692 + /* check for env. var for debug mode */
14693 + libjvm_dtrace_debug = getenv("LIBJVM_DTRACE_DEBUG") != NULL;
14694 + /* create key for thread local error message */
14695 + if (thr_keycreate(&jvm_error_key, NULL) != 0) {
14696 + print_debug("can't create thread_key_t for jvm error key\n");
14697 + // exit(1); ?
14701 +#pragma init(init_jvm_dtrace)
14703 +/* set thread local error message */
14704 +static void set_jvm_error(const char* msg) {
14705 + thr_setspecific(jvm_error_key, (void*)msg);
14708 +/* clear thread local error message */
14709 +static void clear_jvm_error() {
14710 + thr_setspecific(jvm_error_key, NULL);
14713 +/* file handling functions that can handle interrupt */
14715 +static int file_open(const char* path, int flag) {
14716 + int ret;
14717 + RESTARTABLE(open(path, flag), ret);
14718 + return ret;
14721 +static int file_close(int fd) {
14722 + return close(fd);
14725 +static int file_read(int fd, char* buf, int len) {
14726 + int ret;
14727 + RESTARTABLE(read(fd, buf, len), ret);
14728 + return ret;
14731 +/* send SIGQUIT signal to given process */
14732 +static int send_sigquit(pid_t pid) {
14733 + int ret;
14734 + RESTARTABLE(kill(pid, SIGQUIT), ret);
14735 + return ret;
14738 +/* called to check permissions on attach file */
14739 +static int check_permission(const char* path) {
14740 + struct stat64 sb;
14741 + uid_t uid, gid;
14742 + int res;
14744 + /*
14745 + * Check that the path is owned by the effective uid/gid of this
14746 + * process. Also check that group/other access is not allowed.
14747 + */
14748 + uid = geteuid();
14749 + gid = getegid();
14751 + res = stat64(path, &sb);
14752 + if (res != 0) {
14753 + print_debug("stat failed for %s\n", path);
14754 + return -1;
14757 + if ((sb.st_uid != uid) || (sb.st_gid != gid) ||
14758 + ((sb.st_mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) != 0)) {
14759 + print_debug("well-known file %s is not secure\n", path);
14760 + return -1;
14762 + return 0;
14765 +#define ATTACH_FILE_PATTERN "/tmp/.attach_pid%d"
14767 +/* fill-in the name of attach file name in given buffer */
14768 +static void fill_attach_file_name(char* path, int len, pid_t pid) {
14769 + memset(path, 0, len);
14770 + sprintf(path, ATTACH_FILE_PATTERN, pid);
14773 +#define DOOR_FILE_PATTERN "/tmp/.java_pid%d"
14775 +/* open door file for the given JVM */
14776 +static int open_door(pid_t pid) {
14777 + char path[PATH_MAX + 1];
14778 + int fd;
14780 + sprintf(path, DOOR_FILE_PATTERN, pid);
14781 + fd = file_open(path, O_RDONLY);
14782 + if (fd < 0) {
14783 + set_jvm_error(JVM_ERR_CANT_OPEN_DOOR);
14784 + print_debug("cannot open door file %s\n", path);
14785 + return -1;
14787 + print_debug("opened door file %s\n", path);
14788 + if (check_permission(path) != 0) {
14789 + set_jvm_error(JVM_ERR_DOOR_FILE_PERMISSION);
14790 + print_debug("check permission failed for %s\n", path);
14791 + file_close(fd);
14792 + fd = -1;
14794 + return fd;
14797 +/* create attach file for given process */
14798 +static int create_attach_file(pid_t pid) {
14799 + char path[PATH_MAX + 1];
14800 + int fd;
14801 + fill_attach_file_name(path, sizeof(path), pid);
14802 + fd = file_open(path, O_CREAT | O_RDWR);
14803 + if (fd < 0) {
14804 + set_jvm_error(JVM_ERR_CANT_CREATE_ATTACH_FILE);
14805 + print_debug("cannot create file %s\n", path);
14806 + } else {
14807 + print_debug("created attach file %s\n", path);
14809 + return fd;
14812 +/* delete attach file for given process */
14813 +static void delete_attach_file(pid_t pid) {
14814 + char path[PATH_MAX + 1];
14815 + fill_attach_file_name(path, sizeof(path), pid);
14816 + int res = unlink(path);
14817 + if (res) {
14818 + print_debug("cannot delete attach file %s\n", path);
14819 + } else {
14820 + print_debug("deleted attach file %s\n", path);
14824 +/* attach to given JVM */
14825 +jvm_t* jvm_attach(pid_t pid) {
14826 + jvm_t* jvm;
14827 + int door_fd, attach_fd, i = 0;
14829 + jvm = (jvm_t*) calloc(1, sizeof(jvm_t));
14830 + if (jvm == NULL) {
14831 + set_jvm_error(JVM_ERR_OUT_OF_MEMORY);
14832 + print_debug("calloc failed in %s at %d\n", __FILE__, __LINE__);
14833 + return NULL;
14835 + jvm->pid = pid;
14836 + attach_fd = -1;
14838 + door_fd = open_door(pid);
14839 + if (door_fd < 0) {
14840 + print_debug("trying to create attach file\n");
14841 + if ((attach_fd = create_attach_file(pid)) < 0) {
14842 + goto quit;
14845 + /* send QUIT signal to the target so that it will
14846 + * check for the attach file.
14847 + */
14848 + if (send_sigquit(pid) != 0) {
14849 + set_jvm_error(JVM_ERR_CANT_SIGNAL);
14850 + print_debug("sending SIGQUIT failed\n");
14851 + goto quit;
14854 + /* give the target VM time to start the attach mechanism */
14855 + do {
14856 + int res;
14857 + RESTARTABLE(poll(0, 0, 200), res);
14858 + door_fd = open_door(pid);
14859 + i++;
14860 + } while (i <= 50 && door_fd == -1);
14861 + if (door_fd < 0) {
14862 + print_debug("Unable to open door to process %d\n", pid);
14863 + goto quit;
14867 +quit:
14868 + if (attach_fd >= 0) {
14869 + file_close(attach_fd);
14870 + delete_attach_file(jvm->pid);
14872 + if (door_fd >= 0) {
14873 + jvm->door_fd = door_fd;
14874 + clear_jvm_error();
14875 + } else {
14876 + free(jvm);
14877 + jvm = NULL;
14879 + return jvm;
14882 +/* return the last thread local error message */
14883 +const char* jvm_get_last_error() {
14884 + const char* res = NULL;
14885 + thr_getspecific(jvm_error_key, (void**)&res);
14886 + return res;
14889 +/* detach the givenb JVM */
14890 +int jvm_detach(jvm_t* jvm) {
14891 + if (jvm) {
14892 + int res = 0;
14893 + if (jvm->door_fd != -1) {
14894 + if (file_close(jvm->door_fd) != 0) {
14895 + set_jvm_error(JVM_ERR_CANT_CLOSE_DOOR);
14896 + res = -1;
14897 + } else {
14898 + clear_jvm_error();
14901 + free(jvm);
14902 + return res;
14903 + } else {
14904 + set_jvm_error(JVM_ERR_NULL_PARAM);
14905 + print_debug("jvm_t* is NULL\n");
14906 + return -1;
14911 + * A simple table to translate some known errors into reasonable
14912 + * error messages
14913 + */
14914 +static struct {
14915 + int err;
14916 + const char* msg;
14917 +} const error_messages[] = {
14918 + { 100, "Bad request" },
14919 + { 101, "Protocol mismatch" },
14920 + { 102, "Resource failure" },
14921 + { 103, "Internal error" },
14922 + { 104, "Permission denied" },
14926 + * Lookup the given error code and return the appropriate
14927 + * message. If not found return NULL.
14928 + */
14929 +static const char* translate_error(int err) {
14930 + int table_size = sizeof(error_messages) / sizeof(error_messages[0]);
14931 + int i;
14933 + for (i=0; i<table_size; i++) {
14934 + if (err == error_messages[i].err) {
14935 + return error_messages[i].msg;
14938 + return NULL;
14942 + * Current protocol version
14943 + */
14944 +static const char* PROTOCOL_VERSION = "1";
14946 +#define RES_BUF_SIZE 128
14949 + * Enqueue attach-on-demand command to the given JVM
14950 + */
14951 +static
14952 +int enqueue_command(jvm_t* jvm, const char* cstr, int arg_count, const char** args) {
14953 + size_t size;
14954 + door_arg_t door_args;
14955 + char res_buffer[RES_BUF_SIZE];
14956 + int rc, i;
14957 + char* buf = NULL;
14958 + int result = -1;
14960 + /*
14961 + * First we get the command string and create the start of the
14962 + * argument string to send to the target VM:
14963 + * <ver>\0<cmd>\0
14964 + */
14965 + if (cstr == NULL) {
14966 + print_debug("command name is NULL\n");
14967 + goto quit;
14969 + size = strlen(PROTOCOL_VERSION) + strlen(cstr) + 2;
14970 + buf = (char*)malloc(size);
14971 + if (buf != NULL) {
14972 + char* pos = buf;
14973 + strcpy(buf, PROTOCOL_VERSION);
14974 + pos += strlen(PROTOCOL_VERSION)+1;
14975 + strcpy(pos, cstr);
14976 + } else {
14977 + set_jvm_error(JVM_ERR_OUT_OF_MEMORY);
14978 + print_debug("malloc failed at %d in %s\n", __LINE__, __FILE__);
14979 + goto quit;
14982 + /*
14983 + * Next we iterate over the arguments and extend the buffer
14984 + * to include them.
14985 + */
14986 + for (i=0; i<arg_count; i++) {
14987 + cstr = args[i];
14988 + if (cstr != NULL) {
14989 + size_t len = strlen(cstr);
14990 + char* newbuf = (char*)realloc(buf, size+len+1);
14991 + if (newbuf == NULL) {
14992 + set_jvm_error(JVM_ERR_OUT_OF_MEMORY);
14993 + print_debug("realloc failed in %s at %d\n", __FILE__, __LINE__);
14994 + goto quit;
14996 + buf = newbuf;
14997 + strcpy(buf+size, cstr);
14998 + size += len+1;
15002 + /*
15003 + * The arguments to the door function are in 'buf' so we now
15004 + * do the door call
15005 + */
15006 + door_args.data_ptr = buf;
15007 + door_args.data_size = size;
15008 + door_args.desc_ptr = NULL;
15009 + door_args.desc_num = 0;
15010 + door_args.rbuf = (char*)&res_buffer;
15011 + door_args.rsize = sizeof(res_buffer);
15013 + RESTARTABLE(door_call(jvm->door_fd, &door_args), rc);
15015 + /*
15016 + * door_call failed
15017 + */
15018 + if (rc == -1) {
15019 + print_debug("door_call failed\n");
15020 + } else {
15021 + /*
15022 + * door_call succeeded but the call didn't return the expected jint.
15023 + */
15024 + if (door_args.data_size < sizeof(int)) {
15025 + print_debug("Enqueue error - reason unknown as result is truncated!");
15026 + } else {
15027 + int* res = (int*)(door_args.data_ptr);
15028 + if (*res != 0) {
15029 + const char* msg = translate_error(*res);
15030 + if (msg == NULL) {
15031 + print_debug("Unable to enqueue command to target VM: %d\n", *res);
15032 + } else {
15033 + print_debug("Unable to enqueue command to target VM: %s\n", msg);
15035 + } else {
15036 + /*
15037 + * The door call should return a file descriptor to one end of
15038 + * a socket pair
15039 + */
15040 + if ((door_args.desc_ptr != NULL) &&
15041 + (door_args.desc_num == 1) &&
15042 + (door_args.desc_ptr->d_attributes & DOOR_DESCRIPTOR)) {
15043 + result = door_args.desc_ptr->d_data.d_desc.d_descriptor;
15044 + } else {
15045 + print_debug("Reply from enqueue missing descriptor!\n");
15051 +quit:
15052 + if (buf) free(buf);
15053 + return result;
15056 +/* read status code for a door command */
15057 +static int read_status(int fd) {
15058 + char ch, buf[16];
15059 + int index = 0;
15061 + while (1) {
15062 + if (file_read(fd, &ch, sizeof(ch)) != sizeof(ch)) {
15063 + set_jvm_error(JVM_ERR_DOOR_CANT_READ_STATUS);
15064 + print_debug("door cmd status: read status failed\n");
15065 + return -1;
15067 + buf[index++] = ch;
15068 + if (ch == '\n') {
15069 + buf[index - 1] = '\0';
15070 + return atoi(buf);
15072 + if (index == sizeof(buf)) {
15073 + set_jvm_error(JVM_ERR_DOOR_CANT_READ_STATUS);
15074 + print_debug("door cmd status: read status overflow\n");
15075 + return -1;
15080 +static const char* ENABLE_DPROBES_CMD = "enabledprobes";
15082 +/* enable one or more DTrace probes for a given JVM */
15083 +int jvm_enable_dtprobes(jvm_t* jvm, int num_probe_types, const char** probe_types) {
15084 + int fd, status = 0;
15085 + char ch;
15086 + const char* args[1];
15087 + char buf[16];
15088 + int probe_type = 0, index;
15089 + int count = 0;
15091 + if (jvm == NULL) {
15092 + set_jvm_error(JVM_ERR_NULL_PARAM);
15093 + print_debug("jvm_t* is NULL\n");
15094 + return -1;
15097 + if (num_probe_types == 0 || probe_types == NULL ||
15098 + probe_types[0] == NULL) {
15099 + set_jvm_error(JVM_ERR_INVALID_PARAM);
15100 + print_debug("invalid probe type argument(s)\n");
15101 + return -1;
15104 + for (index = 0; index < num_probe_types; index++) {
15105 + const char* p = probe_types[index];
15106 + if (strcmp(p, JVM_DTPROBE_OBJECT_ALLOC) == 0) {
15107 + probe_type |= DTRACE_ALLOC_PROBES;
15108 + count++;
15109 + } else if (strcmp(p, JVM_DTPROBE_METHOD_ENTRY) == 0 ||
15110 + strcmp(p, JVM_DTPROBE_METHOD_RETURN) == 0) {
15111 + probe_type |= DTRACE_METHOD_PROBES;
15112 + count++;
15113 + } else if (strcmp(p, JVM_DTPROBE_MONITOR_ENTER) == 0 ||
15114 + strcmp(p, JVM_DTPROBE_MONITOR_ENTERED) == 0 ||
15115 + strcmp(p, JVM_DTPROBE_MONITOR_EXIT) == 0 ||
15116 + strcmp(p, JVM_DTPROBE_MONITOR_WAIT) == 0 ||
15117 + strcmp(p, JVM_DTPROBE_MONITOR_WAITED) == 0 ||
15118 + strcmp(p, JVM_DTPROBE_MONITOR_NOTIFY) == 0 ||
15119 + strcmp(p, JVM_DTPROBE_MONITOR_NOTIFYALL) == 0) {
15120 + probe_type |= DTRACE_MONITOR_PROBES;
15121 + count++;
15122 + } else if (strcmp(p, JVM_DTPROBE_ALL) == 0) {
15123 + probe_type |= DTRACE_ALL_PROBES;
15124 + count++;
15128 + if (count == 0) {
15129 + return count;
15131 + sprintf(buf, "%d", probe_type);
15132 + args[0] = buf;
15134 + fd = enqueue_command(jvm, ENABLE_DPROBES_CMD, 1, args);
15135 + if (fd < 0) {
15136 + set_jvm_error(JVM_ERR_DOOR_CMD_SEND);
15137 + return -1;
15140 + status = read_status(fd);
15141 + // non-zero status is error
15142 + if (status) {
15143 + set_jvm_error(JVM_ERR_DOOR_CMD_STATUS);
15144 + print_debug("%s command failed (status: %d) in target JVM\n",
15145 + ENABLE_DPROBES_CMD, status);
15146 + file_close(fd);
15147 + return -1;
15149 + // read from stream until EOF
15150 + while (file_read(fd, &ch, sizeof(ch)) == sizeof(ch)) {
15151 + if (libjvm_dtrace_debug) {
15152 + printf("%c", ch);
15156 + file_close(fd);
15157 + clear_jvm_error();
15158 + return count;
15160 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/solaris/native/libjvm_dtrace/jvm_dtrace.h jdk23u-jdk-23-36/src/java.base/solaris/native/libjvm_dtrace/jvm_dtrace.h
15161 --- jdk23u-jdk-23-36.orig/src/java.base/solaris/native/libjvm_dtrace/jvm_dtrace.h 1970-01-01 01:00:00.000000000 +0100
15162 +++ jdk23u-jdk-23-36/src/java.base/solaris/native/libjvm_dtrace/jvm_dtrace.h 2024-08-17 19:50:33.159780346 +0200
15163 @@ -0,0 +1,86 @@
15165 + * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
15166 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
15168 + * This code is free software; you can redistribute it and/or modify it
15169 + * under the terms of the GNU General Public License version 2 only, as
15170 + * published by the Free Software Foundation.
15172 + * This code is distributed in the hope that it will be useful, but WITHOUT
15173 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15174 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15175 + * version 2 for more details (a copy is included in the LICENSE file that
15176 + * accompanied this code).
15178 + * You should have received a copy of the GNU General Public License version
15179 + * 2 along with this work; if not, write to the Free Software Foundation,
15180 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
15182 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
15183 + * or visit www.oracle.com if you need additional information or have any
15184 + * questions.
15186 + */
15188 +#ifndef _JVM_DTRACE_H_
15189 +#define _JVM_DTRACE_H_
15192 + * Interface to dynamically turn on probes in Hotspot JVM. Currently,
15193 + * this interface can be used to dynamically enable certain DTrace
15194 + * probe points that are costly to have "always on".
15195 + */
15197 +#ifdef __cplusplus
15198 +extern "C" {
15199 +#endif
15201 +#include <sys/types.h>
15202 +#include "jni.h"
15204 +struct _jvm_t;
15205 +typedef struct _jvm_t jvm_t;
15208 +/* Attach to the given JVM process. Returns NULL on failure.
15209 + jvm_get_last_error() returns last error message. */
15210 +JNIEXPORT jvm_t* jvm_attach(pid_t pid);
15212 +/* Returns the last error message from this library or NULL if none. */
15213 +JNIEXPORT const char* jvm_get_last_error();
15215 +/* few well-known probe type constants for 'probe_types' param below */
15217 +#define JVM_DTPROBE_METHOD_ENTRY "method-entry"
15218 +#define JVM_DTPROBE_METHOD_RETURN "method-return"
15219 +#define JVM_DTPROBE_MONITOR_ENTER "monitor-contended-enter"
15220 +#define JVM_DTPROBE_MONITOR_ENTERED "monitor-contended-entered"
15221 +#define JVM_DTPROBE_MONITOR_EXIT "monitor-contended-exit"
15222 +#define JVM_DTPROBE_MONITOR_WAIT "monitor-wait"
15223 +#define JVM_DTPROBE_MONITOR_WAITED "monitor-waited"
15224 +#define JVM_DTPROBE_MONITOR_NOTIFY "monitor-notify"
15225 +#define JVM_DTPROBE_MONITOR_NOTIFYALL "monitor-notifyall"
15226 +#define JVM_DTPROBE_OBJECT_ALLOC "object-alloc"
15227 +#define JVM_DTPROBE_ALL "*"
15229 +/* Enable the specified DTrace probes of given probe types on
15230 + * the specified JVM. Returns >= 0 on success, -1 on failure.
15231 + * On success, this returns number of probe_types enabled.
15232 + * On failure, jvm_get_last_error() returns the last error message.
15233 + */
15234 +JNIEXPORT int jvm_enable_dtprobes(jvm_t* jvm, int num_probe_types, const char** probe_types);
15236 +/* Note: There is no jvm_disable_dtprobes function. Probes are automatically
15237 + * disabled when there are no more clients requiring those probes.
15238 + */
15240 +/* Detach the given JVM. Returns 0 on success, -1 on failure.
15241 + * jvm_get_last_error() returns the last error message.
15242 + */
15243 +JNIEXPORT int jvm_detach(jvm_t* jvm);
15245 +#ifdef __cplusplus
15247 +#endif
15249 +#endif /* _JVM_DTRACE_H_ */
15250 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/solaris/native/libnet/solaris_close.c jdk23u-jdk-23-36/src/java.base/solaris/native/libnet/solaris_close.c
15251 --- jdk23u-jdk-23-36.orig/src/java.base/solaris/native/libnet/solaris_close.c 1970-01-01 01:00:00.000000000 +0100
15252 +++ jdk23u-jdk-23-36/src/java.base/solaris/native/libnet/solaris_close.c 2024-08-17 19:50:33.160136874 +0200
15253 @@ -0,0 +1,107 @@
15255 + * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
15256 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
15258 + * This code is free software; you can redistribute it and/or modify it
15259 + * under the terms of the GNU General Public License version 2 only, as
15260 + * published by the Free Software Foundation. Oracle designates this
15261 + * particular file as subject to the "Classpath" exception as provided
15262 + * by Oracle in the LICENSE file that accompanied this code.
15264 + * This code is distributed in the hope that it will be useful, but WITHOUT
15265 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15266 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15267 + * version 2 for more details (a copy is included in the LICENSE file that
15268 + * accompanied this code).
15270 + * You should have received a copy of the GNU General Public License version
15271 + * 2 along with this work; if not, write to the Free Software Foundation,
15272 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
15274 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
15275 + * or visit www.oracle.com if you need additional information or have any
15276 + * questions.
15277 + */
15279 +#include <errno.h>
15280 +#include <sys/socket.h>
15281 +#include <stropts.h>
15282 +#include <unistd.h>
15283 +#include "jvm.h"
15284 +#include "net_util.h"
15286 +/* Support for restartable system calls on Solaris. */
15288 +#define RESTARTABLE_RETURN_INT(_cmd) do { \
15289 + int _result; \
15290 + if (1) { \
15291 + do { \
15292 + _result = _cmd; \
15293 + } while((_result == -1) && (errno == EINTR)); \
15294 + return _result; \
15295 + } \
15296 +} while(0)
15298 +int NET_Read(int s, void* buf, size_t len) {
15299 + RESTARTABLE_RETURN_INT(recv(s, buf, len, 0));
15302 +int NET_NonBlockingRead(int s, void* buf, size_t len) {
15303 + RESTARTABLE_RETURN_INT(recv(s, buf, len, MSG_DONTWAIT));
15306 +int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
15307 + struct sockaddr *from, socklen_t *fromlen) {
15308 + RESTARTABLE_RETURN_INT(recvfrom(s, buf, len, flags, from, fromlen));
15311 +int NET_Send(int s, void *msg, int len, unsigned int flags) {
15312 + RESTARTABLE_RETURN_INT(send(s, msg, len, flags));
15315 +int NET_SendTo(int s, const void *msg, int len, unsigned int flags,
15316 + const struct sockaddr *to, int tolen) {
15317 + RESTARTABLE_RETURN_INT(sendto(s, msg, len, flags, to, tolen));
15320 +int NET_Connect(int s, struct sockaddr *addr, int addrlen) {
15321 + RESTARTABLE_RETURN_INT(connect(s, addr, addrlen));
15324 +int NET_Accept(int s, struct sockaddr *addr, socklen_t *addrlen) {
15325 + RESTARTABLE_RETURN_INT(accept(s, addr, addrlen));
15328 +int NET_SocketClose(int fd) {
15329 + return close(fd);
15332 +int NET_Dup2(int fd, int fd2) {
15333 + return dup2(fd, fd2);
15336 +int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
15337 + RESTARTABLE_RETURN_INT(poll(ufds, nfds, timeout));
15340 +int NET_Timeout(JNIEnv *env, int s, long timeout, jlong nanoTimeStamp) {
15341 + int result;
15342 + jlong prevNanoTime = nanoTimeStamp;
15343 + jlong nanoTimeout = (jlong) timeout * NET_NSEC_PER_MSEC;
15344 + struct pollfd pfd;
15345 + pfd.fd = s;
15346 + pfd.events = POLLIN;
15348 + for(;;) {
15349 + result = poll(&pfd, 1, nanoTimeout / NET_NSEC_PER_MSEC);
15350 + if (result < 0 && errno == EINTR) {
15351 + jlong newNanoTime = JVM_NanoTime(env, 0);
15352 + nanoTimeout -= newNanoTime - prevNanoTime;
15353 + if (nanoTimeout < NET_NSEC_PER_MSEC)
15354 + return 0;
15355 + prevNanoTime = newNanoTime;
15356 + } else {
15357 + return result;
15361 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/solaris/native/libnio/ch/DevPollArrayWrapper.c jdk23u-jdk-23-36/src/java.base/solaris/native/libnio/ch/DevPollArrayWrapper.c
15362 --- jdk23u-jdk-23-36.orig/src/java.base/solaris/native/libnio/ch/DevPollArrayWrapper.c 1970-01-01 01:00:00.000000000 +0100
15363 +++ jdk23u-jdk-23-36/src/java.base/solaris/native/libnio/ch/DevPollArrayWrapper.c 2024-08-17 19:50:33.160505808 +0200
15364 @@ -0,0 +1,112 @@
15366 + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
15367 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
15369 + * This code is free software; you can redistribute it and/or modify it
15370 + * under the terms of the GNU General Public License version 2 only, as
15371 + * published by the Free Software Foundation. Oracle designates this
15372 + * particular file as subject to the "Classpath" exception as provided
15373 + * by Oracle in the LICENSE file that accompanied this code.
15375 + * This code is distributed in the hope that it will be useful, but WITHOUT
15376 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15377 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15378 + * version 2 for more details (a copy is included in the LICENSE file that
15379 + * accompanied this code).
15381 + * You should have received a copy of the GNU General Public License version
15382 + * 2 along with this work; if not, write to the Free Software Foundation,
15383 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
15385 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
15386 + * or visit www.oracle.com if you need additional information or have any
15387 + * questions.
15388 + */
15390 +#include <sys/types.h>
15391 +#include <sys/stat.h>
15392 +#include <devpoll.h>
15393 +#include <fcntl.h>
15394 +#include <poll.h>
15396 +#include "jni.h"
15397 +#include "jni_util.h"
15398 +#include "jvm.h"
15399 +#include "jlong.h"
15400 +#include "nio.h"
15401 +#include "nio_util.h"
15403 +#include "sun_nio_ch_DevPollArrayWrapper.h"
15405 +JNIEXPORT jint JNICALL
15406 +Java_sun_nio_ch_DevPollArrayWrapper_init(JNIEnv *env, jobject this)
15408 + int wfd = open("/dev/poll", O_RDWR);
15409 + if (wfd < 0) {
15410 + JNU_ThrowIOExceptionWithLastError(env, "Error opening driver");
15411 + return -1;
15413 + return wfd;
15416 +JNIEXPORT void JNICALL
15417 +Java_sun_nio_ch_DevPollArrayWrapper_register(JNIEnv *env, jobject this,
15418 + jint wfd, jint fd, jint mask)
15420 + struct pollfd a[1];
15421 + int n;
15423 + a[0].fd = fd;
15424 + a[0].events = mask;
15425 + a[0].revents = 0;
15427 + n = write(wfd, &a[0], sizeof(a));
15428 + if (n != sizeof(a)) {
15429 + if (n < 0) {
15430 + JNU_ThrowIOExceptionWithLastError(env, "Error writing pollfds");
15431 + } else {
15432 + JNU_ThrowIOException(env, "Unexpected number of bytes written");
15437 +JNIEXPORT void JNICALL
15438 +Java_sun_nio_ch_DevPollArrayWrapper_registerMultiple(JNIEnv *env, jobject this,
15439 + jint wfd, jlong address,
15440 + jint len)
15442 + unsigned char *pollBytes = (unsigned char *)jlong_to_ptr(address);
15443 + unsigned char *pollEnd = pollBytes + sizeof(struct pollfd) * len;
15444 + while (pollBytes < pollEnd) {
15445 + int bytesWritten = write(wfd, pollBytes, (int)(pollEnd - pollBytes));
15446 + if (bytesWritten < 0) {
15447 + JNU_ThrowIOExceptionWithLastError(env, "Error writing pollfds");
15448 + return;
15450 + pollBytes += bytesWritten;
15454 +JNIEXPORT jint JNICALL
15455 +Java_sun_nio_ch_DevPollArrayWrapper_poll0(JNIEnv *env, jobject this,
15456 + jlong address, jint numfds,
15457 + jlong timeout, jint wfd)
15459 + struct dvpoll a;
15460 + void *pfd = (void *) jlong_to_ptr(address);
15461 + int result;
15463 + a.dp_fds = pfd;
15464 + a.dp_nfds = numfds;
15465 + a.dp_timeout = (int)timeout;
15466 + result = ioctl(wfd, DP_POLL, &a);
15467 + if (result < 0) {
15468 + if (errno == EINTR) {
15469 + return IOS_INTERRUPTED;
15470 + } else {
15471 + JNU_ThrowIOExceptionWithLastError(env, "Error reading driver");
15472 + return IOS_THROWN;
15475 + return result;
15477 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/solaris/native/libnio/ch/SolarisEventPort.c jdk23u-jdk-23-36/src/java.base/solaris/native/libnio/ch/SolarisEventPort.c
15478 --- jdk23u-jdk-23-36.orig/src/java.base/solaris/native/libnio/ch/SolarisEventPort.c 1970-01-01 01:00:00.000000000 +0100
15479 +++ jdk23u-jdk-23-36/src/java.base/solaris/native/libnio/ch/SolarisEventPort.c 2024-08-17 19:50:33.160799851 +0200
15480 @@ -0,0 +1,147 @@
15482 + * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
15483 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
15485 + * This code is free software; you can redistribute it and/or modify it
15486 + * under the terms of the GNU General Public License version 2 only, as
15487 + * published by the Free Software Foundation. Oracle designates this
15488 + * particular file as subject to the "Classpath" exception as provided
15489 + * by Oracle in the LICENSE file that accompanied this code.
15491 + * This code is distributed in the hope that it will be useful, but WITHOUT
15492 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15493 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15494 + * version 2 for more details (a copy is included in the LICENSE file that
15495 + * accompanied this code).
15497 + * You should have received a copy of the GNU General Public License version
15498 + * 2 along with this work; if not, write to the Free Software Foundation,
15499 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
15501 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
15502 + * or visit www.oracle.com if you need additional information or have any
15503 + * questions.
15504 + */
15506 +#include <stdlib.h>
15507 +#include <dlfcn.h>
15508 +#include <sys/types.h>
15509 +#include <port.h>
15511 +#include "jni.h"
15512 +#include "jni_util.h"
15513 +#include "jvm.h"
15514 +#include "jlong.h"
15515 +#include "nio.h"
15516 +#include "nio_util.h"
15518 +#include "sun_nio_ch_SolarisEventPort.h"
15520 +JNIEXPORT jint JNICALL
15521 +Java_sun_nio_ch_SolarisEventPort_port_1create
15522 + (JNIEnv* env, jclass clazz)
15524 + int port = port_create();
15525 + if (port == -1) {
15526 + JNU_ThrowIOExceptionWithLastError(env, "port_create");
15528 + return (jint)port;
15531 +JNIEXPORT void JNICALL
15532 +Java_sun_nio_ch_SolarisEventPort_port_1close
15533 + (JNIEnv* env, jclass clazz, jint port)
15535 + int res = close(port);
15536 + if (res < 0 && res != EINTR) {
15537 + JNU_ThrowIOExceptionWithLastError(env, "close failed");
15541 +JNIEXPORT jboolean JNICALL
15542 +Java_sun_nio_ch_SolarisEventPort_port_1associate
15543 + (JNIEnv* env, jclass clazz, jint port, jint source, jlong objectAddress, jint events)
15545 + uintptr_t object = (uintptr_t)jlong_to_ptr(objectAddress);
15546 + if (port_associate((int)port, (int)source, object, (int)events, NULL) == 0) {
15547 + return JNI_TRUE;
15548 + } else {
15549 + if (errno != EBADFD)
15550 + JNU_ThrowIOExceptionWithLastError(env, "port_associate");
15551 + return JNI_FALSE;
15555 +JNIEXPORT jboolean JNICALL
15556 +Java_sun_nio_ch_SolarisEventPort_port_1dissociate
15557 + (JNIEnv* env, jclass clazz, jint port, jint source, jlong objectAddress)
15559 + uintptr_t object = (uintptr_t)jlong_to_ptr(objectAddress);
15561 + if (port_dissociate((int)port, (int)source, object) == 0) {
15562 + return JNI_TRUE;
15563 + } else {
15564 + if (errno != ENOENT)
15565 + JNU_ThrowIOExceptionWithLastError(env, "port_dissociate");
15566 + return JNI_FALSE;
15570 +JNIEXPORT void JNICALL
15571 +Java_sun_nio_ch_SolarisEventPort_port_1send(JNIEnv* env, jclass clazz,
15572 + jint port, jint events)
15574 + if (port_send((int)port, (int)events, NULL) == -1) {
15575 + JNU_ThrowIOExceptionWithLastError(env, "port_send");
15579 +JNIEXPORT jint JNICALL
15580 +Java_sun_nio_ch_SolarisEventPort_port_1get(JNIEnv* env, jclass clazz,
15581 + jint port, jlong eventAddress)
15583 + int res;
15584 + port_event_t* ev = (port_event_t*)jlong_to_ptr(eventAddress);
15586 + res = port_get((int)port, ev, NULL);
15587 + if (res == -1) {
15588 + if (errno == EINTR) {
15589 + return IOS_INTERRUPTED;
15590 + } else {
15591 + JNU_ThrowIOExceptionWithLastError(env, "port_get failed");
15592 + return IOS_THROWN;
15595 + return res;
15598 +JNIEXPORT jint JNICALL
15599 +Java_sun_nio_ch_SolarisEventPort_port_1getn(JNIEnv* env, jclass clazz,
15600 + jint port, jlong arrayAddress, jint max, jlong timeout)
15602 + int res;
15603 + uint_t n = 1;
15604 + port_event_t* list = (port_event_t*)jlong_to_ptr(arrayAddress);
15605 + timespec_t ts;
15606 + timespec_t* tsp;
15608 + if (timeout >= 0L) {
15609 + ts.tv_sec = timeout / 1000;
15610 + ts.tv_nsec = 1000000 * (timeout % 1000);
15611 + tsp = &ts;
15612 + } else {
15613 + tsp = NULL;
15616 + res = port_getn((int)port, list, (uint_t)max, &n, tsp);
15617 + if (res == -1 && errno != ETIME) {
15618 + if (errno == EINTR) {
15619 + return IOS_INTERRUPTED;
15620 + } else {
15621 + JNU_ThrowIOExceptionWithLastError(env, "port_getn failed");
15622 + return IOS_THROWN;
15626 + return (jint)n;
15628 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/solaris/native/libnio/fs/SolarisNativeDispatcher.c jdk23u-jdk-23-36/src/java.base/solaris/native/libnio/fs/SolarisNativeDispatcher.c
15629 --- jdk23u-jdk-23-36.orig/src/java.base/solaris/native/libnio/fs/SolarisNativeDispatcher.c 1970-01-01 01:00:00.000000000 +0100
15630 +++ jdk23u-jdk-23-36/src/java.base/solaris/native/libnio/fs/SolarisNativeDispatcher.c 2024-08-17 19:50:33.161150553 +0200
15631 @@ -0,0 +1,143 @@
15633 + * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
15634 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
15636 + * This code is free software; you can redistribute it and/or modify it
15637 + * under the terms of the GNU General Public License version 2 only, as
15638 + * published by the Free Software Foundation. Oracle designates this
15639 + * particular file as subject to the "Classpath" exception as provided
15640 + * by Oracle in the LICENSE file that accompanied this code.
15642 + * This code is distributed in the hope that it will be useful, but WITHOUT
15643 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15644 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15645 + * version 2 for more details (a copy is included in the LICENSE file that
15646 + * accompanied this code).
15648 + * You should have received a copy of the GNU General Public License version
15649 + * 2 along with this work; if not, write to the Free Software Foundation,
15650 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
15652 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
15653 + * or visit www.oracle.com if you need additional information or have any
15654 + * questions.
15655 + */
15657 +#include "jni.h"
15658 +#include "jni_util.h"
15659 +#include "jvm.h"
15660 +#include "jlong.h"
15662 +#include <strings.h>
15663 +#include <errno.h>
15664 +#include <sys/acl.h>
15665 +#include <sys/mnttab.h>
15666 +#include <sys/mkdev.h>
15668 +#include "jni.h"
15670 +#include "sun_nio_fs_SolarisNativeDispatcher.h"
15672 +static jfieldID entry_name;
15673 +static jfieldID entry_dir;
15674 +static jfieldID entry_fstype;
15675 +static jfieldID entry_options;
15676 +static jfieldID entry_dev;
15678 +static void throwUnixException(JNIEnv* env, int errnum) {
15679 + jobject x = JNU_NewObjectByName(env, "sun/nio/fs/UnixException",
15680 + "(I)V", errnum);
15681 + if (x != NULL) {
15682 + (*env)->Throw(env, x);
15686 +JNIEXPORT void JNICALL
15687 +Java_sun_nio_fs_SolarisNativeDispatcher_init(JNIEnv *env, jclass clazz) {
15688 + clazz = (*env)->FindClass(env, "sun/nio/fs/UnixMountEntry");
15689 + CHECK_NULL(clazz);
15690 + entry_name = (*env)->GetFieldID(env, clazz, "name", "[B");
15691 + CHECK_NULL(entry_name);
15692 + entry_dir = (*env)->GetFieldID(env, clazz, "dir", "[B");
15693 + CHECK_NULL(entry_dir);
15694 + entry_fstype = (*env)->GetFieldID(env, clazz, "fstype", "[B");
15695 + CHECK_NULL(entry_fstype);
15696 + entry_options = (*env)->GetFieldID(env, clazz, "opts", "[B");
15697 + CHECK_NULL(entry_options);
15698 + entry_dev = (*env)->GetFieldID(env, clazz, "dev", "J");
15699 + CHECK_NULL(entry_dev);
15702 +JNIEXPORT jint JNICALL
15703 +Java_sun_nio_fs_SolarisNativeDispatcher_facl(JNIEnv* env, jclass this, jint fd,
15704 + jint cmd, jint nentries, jlong address)
15706 + void* aclbufp = jlong_to_ptr(address);
15707 + int n = -1;
15709 + n = facl((int)fd, (int)cmd, (int)nentries, aclbufp);
15710 + if (n == -1) {
15711 + throwUnixException(env, errno);
15713 + return (jint)n;
15716 +JNIEXPORT jint JNICALL
15717 +Java_sun_nio_fs_SolarisNativeDispatcher_getextmntent(JNIEnv* env, jclass this,
15718 + jlong value, jobject entry)
15720 + struct extmnttab ent;
15721 + FILE* fp = jlong_to_ptr(value);
15722 + jsize len;
15723 + jbyteArray bytes;
15724 + char* name;
15725 + char* dir;
15726 + char* fstype;
15727 + char* options;
15728 + dev_t dev;
15730 + if (getextmntent(fp, &ent, 0))
15731 + return -1;
15732 + name = ent.mnt_special;
15733 + dir = ent.mnt_mountp;
15734 + fstype = ent.mnt_fstype;
15735 + options = ent.mnt_mntopts;
15736 + dev = makedev(ent.mnt_major, ent.mnt_minor);
15737 + if (dev == NODEV) {
15738 + throwUnixException(env, errno);
15739 + return -1;
15742 + len = strlen(name);
15743 + bytes = (*env)->NewByteArray(env, len);
15744 + if (bytes == NULL)
15745 + return -1;
15746 + (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)name);
15747 + (*env)->SetObjectField(env, entry, entry_name, bytes);
15749 + len = strlen(dir);
15750 + bytes = (*env)->NewByteArray(env, len);
15751 + if (bytes == NULL)
15752 + return -1;
15753 + (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)dir);
15754 + (*env)->SetObjectField(env, entry, entry_dir, bytes);
15756 + len = strlen(fstype);
15757 + bytes = (*env)->NewByteArray(env, len);
15758 + if (bytes == NULL)
15759 + return -1;
15760 + (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)fstype);
15761 + (*env)->SetObjectField(env, entry, entry_fstype, bytes);
15763 + len = strlen(options);
15764 + bytes = (*env)->NewByteArray(env, len);
15765 + if (bytes == NULL)
15766 + return -1;
15767 + (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)options);
15768 + (*env)->SetObjectField(env, entry, entry_options, bytes);
15770 + if (dev != 0)
15771 + (*env)->SetLongField(env, entry, entry_dev, (jlong)dev);
15773 + return 0;
15775 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/solaris/native/libnio/fs/SolarisWatchService.c jdk23u-jdk-23-36/src/java.base/solaris/native/libnio/fs/SolarisWatchService.c
15776 --- jdk23u-jdk-23-36.orig/src/java.base/solaris/native/libnio/fs/SolarisWatchService.c 1970-01-01 01:00:00.000000000 +0100
15777 +++ jdk23u-jdk-23-36/src/java.base/solaris/native/libnio/fs/SolarisWatchService.c 2024-08-17 19:50:33.161418635 +0200
15778 @@ -0,0 +1,104 @@
15780 + * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
15781 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
15783 + * This code is free software; you can redistribute it and/or modify it
15784 + * under the terms of the GNU General Public License version 2 only, as
15785 + * published by the Free Software Foundation. Oracle designates this
15786 + * particular file as subject to the "Classpath" exception as provided
15787 + * by Oracle in the LICENSE file that accompanied this code.
15789 + * This code is distributed in the hope that it will be useful, but WITHOUT
15790 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15791 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15792 + * version 2 for more details (a copy is included in the LICENSE file that
15793 + * accompanied this code).
15795 + * You should have received a copy of the GNU General Public License version
15796 + * 2 along with this work; if not, write to the Free Software Foundation,
15797 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
15799 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
15800 + * or visit www.oracle.com if you need additional information or have any
15801 + * questions.
15802 + */
15804 +#include "jni.h"
15805 +#include "jni_util.h"
15806 +#include "jvm.h"
15807 +#include "jlong.h"
15809 +#include <stdlib.h>
15810 +#include <dlfcn.h>
15811 +#include <sys/types.h>
15812 +#include <port.h> // Solaris 10
15814 +#include "sun_nio_fs_SolarisWatchService.h"
15816 +static void throwUnixException(JNIEnv* env, int errnum) {
15817 + jobject x = JNU_NewObjectByName(env, "sun/nio/fs/UnixException",
15818 + "(I)V", errnum);
15819 + if (x != NULL) {
15820 + (*env)->Throw(env, x);
15824 +JNIEXPORT void JNICALL
15825 +Java_sun_nio_fs_SolarisWatchService_init(JNIEnv *env, jclass clazz)
15829 +JNIEXPORT jint JNICALL
15830 +Java_sun_nio_fs_SolarisWatchService_portCreate
15831 + (JNIEnv* env, jclass clazz)
15833 + int port = port_create();
15834 + if (port == -1) {
15835 + throwUnixException(env, errno);
15837 + return (jint)port;
15840 +JNIEXPORT void JNICALL
15841 +Java_sun_nio_fs_SolarisWatchService_portAssociate
15842 + (JNIEnv* env, jclass clazz, jint port, jint source, jlong objectAddress, jint events)
15844 + uintptr_t object = (uintptr_t)jlong_to_ptr(objectAddress);
15846 + if (port_associate((int)port, (int)source, object, (int)events, NULL) == -1) {
15847 + throwUnixException(env, errno);
15851 +JNIEXPORT void JNICALL
15852 +Java_sun_nio_fs_SolarisWatchService_portDissociate
15853 + (JNIEnv* env, jclass clazz, jint port, jint source, jlong objectAddress)
15855 + uintptr_t object = (uintptr_t)jlong_to_ptr(objectAddress);
15857 + if (port_dissociate((int)port, (int)source, object) == -1) {
15858 + throwUnixException(env, errno);
15862 +JNIEXPORT void JNICALL
15863 +Java_sun_nio_fs_SolarisWatchService_portSend(JNIEnv* env, jclass clazz,
15864 + jint port, jint events)
15866 + if (port_send((int)port, (int)events, NULL) == -1) {
15867 + throwUnixException(env, errno);
15871 +JNIEXPORT jint JNICALL
15872 +Java_sun_nio_fs_SolarisWatchService_portGetn(JNIEnv* env, jclass clazz,
15873 + jint port, jlong arrayAddress, jint max)
15875 + uint_t n = 1;
15876 + port_event_t* list = (port_event_t*)jlong_to_ptr(arrayAddress);
15878 + if (port_getn((int)port, list, (uint_t)max, &n, NULL) == -1) {
15879 + throwUnixException(env, errno);
15881 + return (jint)n;
15883 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/unix/classes/java/lang/ProcessImpl.java jdk23u-jdk-23-36/src/java.base/unix/classes/java/lang/ProcessImpl.java
15884 --- jdk23u-jdk-23-36.orig/src/java.base/unix/classes/java/lang/ProcessImpl.java 2024-08-07 00:08:22.000000000 +0200
15885 +++ jdk23u-jdk-23-36/src/java.base/unix/classes/java/lang/ProcessImpl.java 2024-08-17 19:50:33.104399042 +0200
15886 @@ -83,6 +83,9 @@
15887 private /* final */ InputStream stdout;
15888 private /* final */ InputStream stderr;
15890 + // only used on Solaris
15891 + private /* final */ DeferredCloseInputStream stdout_inner_stream;
15893 private static enum LaunchMechanism {
15894 // order IS important!
15895 FORK,
15896 @@ -108,6 +111,7 @@
15897 return lm; // All options are valid for Linux
15898 case AIX:
15899 case MACOS:
15900 + case SOLARIS:
15901 if (lm != LaunchMechanism.VFORK) {
15902 return lm; // All but VFORK are valid
15904 @@ -364,6 +368,44 @@
15906 break;
15908 + case SOLARIS:
15909 + stdin = (fds[0] == -1) ?
15910 + ProcessBuilder.NullOutputStream.INSTANCE :
15911 + new BufferedOutputStream(
15912 + new FileOutputStream(newFileDescriptor(fds[0])));
15914 + stdout = (fds[1] == -1 || forceNullOutputStream) ?
15915 + ProcessBuilder.NullInputStream.INSTANCE :
15916 + new BufferedInputStream(
15917 + stdout_inner_stream =
15918 + new DeferredCloseInputStream(
15919 + newFileDescriptor(fds[1])));
15921 + stderr = (fds[2] == -1) ?
15922 + ProcessBuilder.NullInputStream.INSTANCE :
15923 + new DeferredCloseInputStream(newFileDescriptor(fds[2]));
15925 + /*
15926 + * For each subprocess forked a corresponding reaper task
15927 + * is submitted. That task is the only thread which waits
15928 + * for the subprocess to terminate and it doesn't hold any
15929 + * locks while doing so. This design allows waitFor() and
15930 + * exitStatus() to be safely executed in parallel (and they
15931 + * need no native code).
15932 + */
15933 + ProcessHandleImpl.completion(pid, true).handle((exitcode, throwable) -> {
15934 + lock.lock();
15935 + try {
15936 + this.exitcode = (exitcode == null) ? -1 : exitcode.intValue();
15937 + this.hasExited = true;
15938 + condition.signalAll();
15939 + } finally {
15940 + lock.unlock();
15942 + return null;
15943 + });
15944 + break;
15946 case AIX:
15947 stdin = (fds[0] == -1) ?
15948 ProcessBuilder.NullOutputStream.INSTANCE :
15949 @@ -480,6 +522,32 @@
15950 try { stderr.close(); } catch (IOException ignored) {}
15951 break;
15953 + case SOLARIS:
15954 + // There is a risk that pid will be recycled, causing us to
15955 + // kill the wrong process! So we only terminate processes
15956 + // that appear to still be running. Even with this check,
15957 + // there is an unavoidable race condition here, but the window
15958 + // is very small, and OSes try hard to not recycle pids too
15959 + // soon, so this is quite safe.
15960 + lock.lock();
15961 + try {
15962 + if (!hasExited)
15963 + processHandle.destroyProcess(force);
15964 + } finally {
15965 + lock.unlock();
15967 + try {
15968 + stdin.close();
15969 + if (stdout_inner_stream != null)
15970 + stdout_inner_stream.closeDeferred(stdout);
15971 + if (stderr instanceof DeferredCloseInputStream)
15972 + ((DeferredCloseInputStream) stderr)
15973 + .closeDeferred(stderr);
15974 + } catch (IOException e) {
15975 + // ignore
15977 + break;
15979 default: throw new AssertionError("Unsupported platform: " + OperatingSystem.current());
15982 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/unix/classes/sun/net/PortConfig.java jdk23u-jdk-23-36/src/java.base/unix/classes/sun/net/PortConfig.java
15983 --- jdk23u-jdk-23-36.orig/src/java.base/unix/classes/sun/net/PortConfig.java 2024-08-07 00:08:22.000000000 +0200
15984 +++ jdk23u-jdk-23-36/src/java.base/unix/classes/sun/net/PortConfig.java 2024-08-17 19:50:33.104771461 +0200
15985 @@ -48,6 +48,10 @@
15986 defaultLower = 32768;
15987 defaultUpper = 61000;
15988 break;
15989 + case SOLARIS:
15990 + defaultLower = 32768;
15991 + defaultUpper = 65535;
15992 + break;
15993 case MACOS:
15994 defaultLower = 49152;
15995 defaultUpper = 65535;
15996 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/unix/classes/sun/nio/fs/UnixConstants.java.template jdk23u-jdk-23-36/src/java.base/unix/classes/sun/nio/fs/UnixConstants.java.template
15997 --- jdk23u-jdk-23-36.orig/src/java.base/unix/classes/sun/nio/fs/UnixConstants.java.template 2024-08-07 00:08:22.000000000 +0200
15998 +++ jdk23u-jdk-23-36/src/java.base/unix/classes/sun/nio/fs/UnixConstants.java.template 2024-08-17 19:50:33.105180409 +0200
15999 @@ -35,6 +35,10 @@
16000 #include <sys/clonefile.h>
16001 #endif
16003 +/* On Solaris, "sun" is defined as a macro. Undefine to make package
16004 + declaration valid */
16005 +#undef sun
16007 /* To be able to name the Java constants the same as the C constants without
16008 having the preprocessor rewrite those identifiers, add PREFIX_ to all
16009 identifiers matching a C constant. The PREFIX_ is filtered out in the
16010 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java jdk23u-jdk-23-36/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java
16011 --- jdk23u-jdk-23-36.orig/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java 2024-08-07 00:08:22.000000000 +0200
16012 +++ jdk23u-jdk-23-36/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java 2024-08-17 19:50:33.105655382 +0200
16013 @@ -127,6 +127,10 @@
16014 return rootDirectory;
16017 + boolean isSolaris() {
16018 + return false;
16021 static List<String> standardFileAttributeViews() {
16022 return Arrays.asList("basic", "posix", "unix", "owner");
16024 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/unix/classes/sun/nio/fs/UnixPath.java jdk23u-jdk-23-36/src/java.base/unix/classes/sun/nio/fs/UnixPath.java
16025 --- jdk23u-jdk-23-36.orig/src/java.base/unix/classes/sun/nio/fs/UnixPath.java 2024-08-07 00:08:22.000000000 +0200
16026 +++ jdk23u-jdk-23-36/src/java.base/unix/classes/sun/nio/fs/UnixPath.java 2024-08-17 19:50:33.106158998 +0200
16027 @@ -830,7 +830,15 @@
16028 ("NOFOLLOW_LINKS is not supported on this platform");
16029 flags |= O_NOFOLLOW;
16031 - return open(this, flags, 0);
16032 + try {
16033 + return open(this, flags, 0);
16034 + } catch (UnixException x) {
16035 + // HACK: EINVAL instead of ELOOP on Solaris 10 prior to u4 (see 6460380)
16036 + if (getFileSystem().isSolaris() && x.errno() == EINVAL)
16037 + x.setError(ELOOP);
16039 + throw x;
16043 void checkRead() {
16044 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/unix/classes/sun/security/provider/NativePRNG.java jdk23u-jdk-23-36/src/java.base/unix/classes/sun/security/provider/NativePRNG.java
16045 --- jdk23u-jdk-23-36.orig/src/java.base/unix/classes/sun/security/provider/NativePRNG.java 2024-08-07 00:08:22.000000000 +0200
16046 +++ jdk23u-jdk-23-36/src/java.base/unix/classes/sun/security/provider/NativePRNG.java 2024-08-17 19:50:33.106652069 +0200
16047 @@ -33,7 +33,7 @@
16048 import sun.security.util.Debug;
16051 - * Native PRNG implementation for Linux/MacOS.
16052 + * Native PRNG implementation for Solaris/Linux/MacOS.
16053 * <p>
16054 * It obtains seed and random numbers by reading system files such as
16055 * the special device files /dev/random and /dev/urandom. This
16056 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/unix/native/libjava/io_util_md.c jdk23u-jdk-23-36/src/java.base/unix/native/libjava/io_util_md.c
16057 --- jdk23u-jdk-23-36.orig/src/java.base/unix/native/libjava/io_util_md.c 2024-08-07 00:08:22.000000000 +0200
16058 +++ jdk23u-jdk-23-36/src/java.base/unix/native/libjava/io_util_md.c 2024-08-17 19:50:33.109843297 +0200
16059 @@ -30,6 +30,10 @@
16060 #include <string.h>
16061 #include <unistd.h>
16063 +#ifdef __solaris__
16064 +#include <sys/filio.h>
16065 +#endif
16067 #if defined(__linux__) || defined(_ALLBSD_SOURCE) || defined(_AIX)
16068 #include <sys/ioctl.h>
16069 #endif
16070 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/unix/native/libjava/java_props_md.c jdk23u-jdk-23-36/src/java.base/unix/native/libjava/java_props_md.c
16071 --- jdk23u-jdk-23-36.orig/src/java.base/unix/native/libjava/java_props_md.c 2024-08-07 00:08:22.000000000 +0200
16072 +++ jdk23u-jdk-23-36/src/java.base/unix/native/libjava/java_props_md.c 2024-08-17 19:50:33.110285262 +0200
16073 @@ -323,6 +323,27 @@
16075 #endif
16077 +#ifdef __solaris__
16078 + if (strcmp(p,"eucJP") == 0) {
16079 + /* For Solaris use customized vendor defined character
16080 + * customized EUC-JP converter
16081 + */
16082 + *std_encoding = "eucJP-open";
16083 + } else if (strcmp(p, "Big5") == 0 || strcmp(p, "BIG5") == 0) {
16084 + /*
16085 + * Remap the encoding string to Big5_Solaris which augments
16086 + * the default converter for Solaris Big5 locales to include
16087 + * seven additional ideographic characters beyond those included
16088 + * in the Java "Big5" converter.
16089 + */
16090 + *std_encoding = "Big5_Solaris";
16091 + } else if (strcmp(p, "Big5-HKSCS") == 0) {
16092 + /*
16093 + * Solaris uses HKSCS2001
16094 + */
16095 + *std_encoding = "Big5-HKSCS-2001";
16097 +#endif
16098 #ifdef MACOSX
16100 * For the case on MacOS X where encoding is set to US-ASCII, but we
16101 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/unix/native/libjava/jlong_md.h jdk23u-jdk-23-36/src/java.base/unix/native/libjava/jlong_md.h
16102 --- jdk23u-jdk-23-36.orig/src/java.base/unix/native/libjava/jlong_md.h 2024-08-07 00:08:22.000000000 +0200
16103 +++ jdk23u-jdk-23-36/src/java.base/unix/native/libjava/jlong_md.h 2024-08-17 19:50:33.110682669 +0200
16104 @@ -23,8 +23,8 @@
16105 * questions.
16108 -#ifndef _UNIX_JLONG_MD_H_
16109 -#define _UNIX_JLONG_MD_H_
16110 +#ifndef _SOLARIS_JLONG_MD_H_
16111 +#define _SOLARIS_JLONG_MD_H_
16113 /* Make sure ptrdiff_t is defined */
16114 #include <stddef.h>
16115 @@ -97,4 +97,4 @@
16116 #define size_to_jlong(a) ((jlong)(a))
16117 #define long_to_jlong(a) ((jlong)(a))
16119 -#endif /* !_UNIX_JLONG_MD_H_ */
16120 +#endif /* !_SOLARIS_JLONG_MD_H_ */
16121 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c jdk23u-jdk-23-36/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c
16122 --- jdk23u-jdk-23-36.orig/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c 2024-08-07 00:08:22.000000000 +0200
16123 +++ jdk23u-jdk-23-36/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c 2024-08-17 19:50:33.107394863 +0200
16124 @@ -44,8 +44,16 @@
16125 #include <sys/stat.h>
16126 #include <sys/wait.h>
16128 +/* For POSIX-compliant getpwuid_r on Solaris */
16129 +#if defined(__solaris__)
16130 +#define _POSIX_PTHREAD_SEMANTICS
16131 +#endif
16132 #include <pwd.h>
16134 +#ifdef __solaris__
16135 +#include <procfs.h>
16136 +#endif
16138 #if defined(_AIX)
16139 #include <sys/procfs.h>
16140 #endif
16141 @@ -122,13 +130,18 @@
16142 #define WTERMSIG(status) ((status)&0x7F)
16143 #endif
16145 +#ifdef __solaris__
16146 /* The child exited because of a signal.
16147 * The best value to return is 0x80 + signal number,
16148 * because that is what all Unix shells do, and because
16149 * it allows callers to distinguish between process exit and
16150 * process death by signal.
16151 - */
16152 + * Unfortunately, the historical behavior on Solaris is to return
16153 + * the signal number, and we preserve this for compatibility. */
16154 +#define WTERMSIG_RETURN(status) WTERMSIG(status)
16155 +#else
16156 #define WTERMSIG_RETURN(status) (WTERMSIG(status) + 0x80)
16157 +#endif
16159 /* Field id for jString 'command' in java.lang.ProcessHandleImpl.Info */
16160 jfieldID ProcessHandleImpl_Info_commandID;
16161 @@ -469,7 +482,7 @@
16162 * The following functions are for Linux
16165 -#if defined (__linux__)
16166 +#if defined(__solaris__) || defined (__linux__)
16169 * Return pids of active processes, and optionally parent pids and
16170 @@ -598,13 +611,13 @@
16171 return count;
16174 -#endif // defined (__linux__)
16175 +#endif // defined(__solaris__) || defined (__linux__)
16178 - * The following functions are for AIX.
16179 + * The following functions are common on Solaris and AIX.
16182 -#if defined(_AIX)
16183 +#if defined(__solaris__) || defined(_AIX)
16186 * Helper function to get the 'psinfo_t' data from "/proc/%d/psinfo".
16187 @@ -668,6 +681,19 @@
16188 int ret;
16191 + * On Solaris, the full path to the executable command is the link in
16192 + * /proc/<pid>/paths/a.out. But it is only readable for processes we own.
16193 + */
16194 +#if defined(__solaris__)
16195 + snprintf(fn, sizeof fn, "/proc/%d/path/a.out", pid);
16196 + if ((ret = readlink(fn, exePath, PATH_MAX - 1)) > 0) {
16197 + // null terminate and create String to store for command
16198 + exePath[ret] = '\0';
16199 + CHECK_NULL(cmdexe = JNU_NewStringPlatform(env, exePath));
16201 +#endif
16203 + /*
16204 * Now try to open /proc/%d/psinfo
16206 if (getPsinfo(pid, &psinfo) < 0) {
16207 @@ -696,4 +722,4 @@
16208 prargs[0] == '\0' ? NULL : prargs);
16211 -#endif // defined(_AIX)
16212 +#endif // defined(__solaris__) || defined(_AIX)
16213 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.h jdk23u-jdk-23-36/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.h
16214 --- jdk23u-jdk-23-36.orig/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.h 2024-08-07 00:08:22.000000000 +0200
16215 +++ jdk23u-jdk-23-36/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.h 2024-08-17 19:50:33.107744082 +0200
16216 @@ -29,7 +29,7 @@
16217 * Declaration of ProcessHandleImpl functions common on all Unix platforms.
16218 * 'unix_' functions have a single implementation in ProcessHandleImpl_unix.c
16219 * 'os_' prefixed functions have different, os-specific implementations in the
16220 - * various ProcessHandleImpl_{linux,macosx,aix}.c files.
16221 + * various ProcessHandleImpl_{linux,macosx,solaris,aix}.c files.
16222 * See ProcessHandleImpl_unix.c for more details.
16225 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/unix/native/libjava/ProcessImpl_md.c jdk23u-jdk-23-36/src/java.base/unix/native/libjava/ProcessImpl_md.c
16226 --- jdk23u-jdk-23-36.orig/src/java.base/unix/native/libjava/ProcessImpl_md.c 2024-08-07 00:08:22.000000000 +0200
16227 +++ jdk23u-jdk-23-36/src/java.base/unix/native/libjava/ProcessImpl_md.c 2024-08-17 19:50:33.108292610 +0200
16228 @@ -230,7 +230,14 @@
16229 static const char*
16230 defaultPath(void)
16232 - return ":/bin:/usr/bin";
16233 +#ifdef __solaris__
16234 + /* These really are the Solaris defaults! */
16235 + return (geteuid() == 0 || getuid() == 0) ?
16236 + "/usr/xpg4/bin:/usr/bin:/opt/SUNWspro/bin:/usr/sbin" :
16237 + "/usr/xpg4/bin:/usr/bin:/opt/SUNWspro/bin:";
16238 +#else
16239 + return ":/bin:/usr/bin"; /* glibc */
16240 +#endif
16243 static const char*
16244 @@ -447,7 +454,7 @@
16245 #endif
16247 /* vfork(2) is deprecated on Darwin */
16248 -#ifndef __APPLE__
16249 +#ifndef __solaris__
16250 static pid_t
16251 vforkChild(ChildStuff *c) {
16252 volatile pid_t resultPid;
16253 @@ -611,7 +618,7 @@
16254 startChild(JNIEnv *env, jobject process, ChildStuff *c, const char *helperpath) {
16255 switch (c->mode) {
16256 /* vfork(2) is deprecated on Darwin*/
16257 - #ifndef __APPLE__
16258 + #ifndef __solaris__
16259 case MODE_VFORK:
16260 return vforkChild(c);
16261 #endif
16262 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/unix/native/libjava/TimeZone_md.c jdk23u-jdk-23-36/src/java.base/unix/native/libjava/TimeZone_md.c
16263 --- jdk23u-jdk-23-36.orig/src/java.base/unix/native/libjava/TimeZone_md.c 2024-08-07 00:08:22.000000000 +0200
16264 +++ jdk23u-jdk-23-36/src/java.base/unix/native/libjava/TimeZone_md.c 2024-08-17 19:50:33.109043706 +0200
16265 @@ -35,6 +35,9 @@
16266 #include <string.h>
16267 #include <dirent.h>
16268 #include <unistd.h>
16269 +#if defined(__solaris__)
16270 +#include <libscf.h>
16271 +#endif
16273 #include "jvm.h"
16274 #include "jni_util.h"
16275 @@ -43,9 +46,11 @@
16277 static char *isFileIdentical(char* buf, size_t size, char *pathname);
16279 +#if !defined(__solaris__) || defined(__sparcv9) || defined(amd64)
16280 #define fileopen fopen
16281 #define filegets fgets
16282 #define fileclose fclose
16283 +#endif
16285 #if defined(__linux__) || defined(_ALLBSD_SOURCE)
16286 static const char *ETC_TIMEZONE_FILE = "/etc/timezone";
16287 @@ -63,7 +68,7 @@
16288 static const char *ETC_ENVIRONMENT_FILE = "/etc/environment";
16289 #endif
16291 -#if defined(__linux__) || defined(MACOSX)
16292 +#if defined(__linux__) || defined(MACOSX) || defined(__solaris__)
16295 * remove repeated path separators ('/') in the given 'path'.
16296 @@ -173,6 +178,13 @@
16298 if ((strcmp(dp->d_name, "ROC") == 0)
16299 || (strcmp(dp->d_name, "posixrules") == 0)
16300 +#if defined(__solaris__)
16301 + /*
16302 + * Skip the "src" and "tab" directories on Solaris.
16303 + */
16304 + || (strcmp(dp->d_name, "src") == 0)
16305 + || (strcmp(dp->d_name, "tab") == 0)
16306 +#endif
16307 || (strcmp(dp->d_name, "localtime") == 0)) {
16308 continue;
16310 @@ -244,6 +256,8 @@
16311 return possibleMatch;
16314 +#if defined(__linux__) || defined(MACOSX)
16317 * Performs Linux specific mapping and returns a zone ID
16318 * if found. Otherwise, NULL is returned.
16319 @@ -355,6 +369,183 @@
16320 return tz;
16323 +#elif defined(__solaris__)
16326 + * Performs Solaris dependent mapping. Returns a zone ID if
16327 + * found. Otherwise, NULL is returned. Solaris libc looks up
16328 + * "/etc/default/init" to get the default TZ value if TZ is not defined
16329 + * as an environment variable.
16330 + */
16331 +static char *
16332 +getPlatformTimeZoneID()
16334 + char *tz = NULL;
16335 + FILE *fp;
16337 + /*
16338 + * Try the TZ entry in /etc/default/init.
16339 + */
16340 + if ((fp = fileopen(SYS_INIT_FILE, "r")) != NULL) {
16341 + char line[256];
16342 + char quote = '\0';
16344 + while (filegets(line, sizeof(line), fp) != NULL) {
16345 + char *p = line;
16346 + char *s;
16347 + char c;
16349 + /* quick check for comment lines */
16350 + if (*p == '#') {
16351 + continue;
16353 + if (strncmp(p, "TZ=", 3) == 0) {
16354 + p += 3;
16355 + while (*p == ' ' || *p == '\t') p++;
16356 + c = *p;
16357 + if (c == '"' || c == '\'') {
16358 + quote = c;
16359 + p++;
16362 + /*
16363 + * PSARC/2001/383: quoted string support
16364 + */
16365 + for (s = p; (c = *s) != '\0' && c != '\n'; s++) {
16366 + /* No '\\' is supported here. */
16367 + if (c == quote) {
16368 + quote = '\0';
16369 + break;
16371 + if (c == ' ' && quote == '\0') {
16372 + break;
16375 + if (quote != '\0') {
16376 + jio_fprintf(stderr, "ZoneInfo: unterminated time zone name in /etc/TIMEZONE\n");
16378 + *s = '\0';
16379 + tz = strdup(p);
16380 + break;
16383 + (void) fileclose(fp);
16385 + return tz;
16388 +#define TIMEZONE_FMRI "svc:/system/timezone:default"
16389 +#define TIMEZONE_PG "timezone"
16390 +#define LOCALTIME_PROP "localtime"
16392 +static void
16393 +cleanupScf(scf_handle_t *h,
16394 + scf_snapshot_t *snap,
16395 + scf_instance_t *inst,
16396 + scf_propertygroup_t *pg,
16397 + scf_property_t *prop,
16398 + scf_value_t *val,
16399 + char *buf) {
16400 + if (buf != NULL) {
16401 + free(buf);
16403 + if (snap != NULL) {
16404 + scf_snapshot_destroy(snap);
16406 + if (val != NULL) {
16407 + scf_value_destroy(val);
16409 + if (prop != NULL) {
16410 + scf_property_destroy(prop);
16412 + if (pg != NULL) {
16413 + scf_pg_destroy(pg);
16415 + if (inst != NULL) {
16416 + scf_instance_destroy(inst);
16418 + if (h != NULL) {
16419 + scf_handle_destroy(h);
16424 + * Returns a zone ID of Solaris when the TZ value is "localtime".
16425 + * First, it tries scf. If scf fails, it looks for the same file as
16426 + * /usr/share/lib/zoneinfo/localtime under /usr/share/lib/zoneinfo/.
16427 + */
16428 +static char *
16429 +getSolarisDefaultZoneID() {
16430 + char *tz = NULL;
16431 + struct stat64 statbuf;
16432 + size_t size;
16433 + char *buf;
16434 + int fd;
16435 + int res;
16436 + /* scf specific variables */
16437 + scf_handle_t *h = NULL;
16438 + scf_snapshot_t *snap = NULL;
16439 + scf_instance_t *inst = NULL;
16440 + scf_propertygroup_t *pg = NULL;
16441 + scf_property_t *prop = NULL;
16442 + scf_value_t *val = NULL;
16444 + if ((h = scf_handle_create(SCF_VERSION)) != NULL
16445 + && scf_handle_bind(h) == 0
16446 + && (inst = scf_instance_create(h)) != NULL
16447 + && (snap = scf_snapshot_create(h)) != NULL
16448 + && (pg = scf_pg_create(h)) != NULL
16449 + && (prop = scf_property_create(h)) != NULL
16450 + && (val = scf_value_create(h)) != NULL
16451 + && scf_handle_decode_fmri(h, TIMEZONE_FMRI, NULL, NULL, inst,
16452 + NULL, NULL, SCF_DECODE_FMRI_REQUIRE_INSTANCE) == 0
16453 + && scf_instance_get_snapshot(inst, "running", snap) == 0
16454 + && scf_instance_get_pg_composed(inst, snap, TIMEZONE_PG, pg) == 0
16455 + && scf_pg_get_property(pg, LOCALTIME_PROP, prop) == 0
16456 + && scf_property_get_value(prop, val) == 0) {
16457 + ssize_t len;
16459 + /* Gets the length of the zone ID string */
16460 + len = scf_value_get_astring(val, NULL, 0);
16461 + if (len != -1) {
16462 + tz = malloc(++len); /* +1 for a null byte */
16463 + if (tz != NULL && scf_value_get_astring(val, tz, len) != -1) {
16464 + cleanupScf(h, snap, inst, pg, prop, val, NULL);
16465 + return tz;
16469 + cleanupScf(h, snap, inst, pg, prop, val, tz);
16471 + RESTARTABLE(stat64(DEFAULT_ZONEINFO_FILE, &statbuf), res);
16472 + if (res == -1) {
16473 + return NULL;
16475 + size = (size_t) statbuf.st_size;
16476 + buf = malloc(size);
16477 + if (buf == NULL) {
16478 + return NULL;
16480 + RESTARTABLE(open(DEFAULT_ZONEINFO_FILE, O_RDONLY), fd);
16481 + if (fd == -1) {
16482 + free((void *) buf);
16483 + return NULL;
16486 + RESTARTABLE(read(fd, buf, size), res);
16487 + if (res != (ssize_t) size) {
16488 + (void) close(fd);
16489 + free((void *) buf);
16490 + return NULL;
16492 + (void) close(fd);
16493 + tz = findZoneinfoFile(buf, size, ZONEINFO_DIR);
16494 + free((void *) buf);
16495 + return tz;
16498 +#endif /* defined(__solaris__) */
16500 #elif defined(_AIX)
16502 static char *
16503 @@ -520,6 +711,15 @@
16504 free((void *) freetz);
16506 #else
16507 +#if defined(__solaris__)
16508 + /* Solaris might use localtime, so handle it here. */
16509 + if (strcmp(tz, "localtime") == 0) {
16510 + javatz = getSolarisDefaultZoneID();
16511 + if (freetz != NULL) {
16512 + free((void *) freetz);
16514 + } else
16515 +#endif
16516 if (freetz == NULL) {
16517 /* strdup if we are still working on getenv result. */
16518 javatz = strdup(tz);
16519 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/unix/native/libjava/UnixFileSystem_md.c jdk23u-jdk-23-36/src/java.base/unix/native/libjava/UnixFileSystem_md.c
16520 --- jdk23u-jdk-23-36.orig/src/java.base/unix/native/libjava/UnixFileSystem_md.c 2024-08-07 00:08:22.000000000 +0200
16521 +++ jdk23u-jdk-23-36/src/java.base/unix/native/libjava/UnixFileSystem_md.c 2024-08-17 19:50:33.109481091 +0200
16522 @@ -57,6 +57,11 @@
16523 #endif
16524 #define statvfs statvfs64
16525 #endif
16527 +#if defined(__solaris__) && !defined(NAME_MAX)
16528 + #define NAME_MAX MAXNAMLEN
16529 +#endif
16531 /* -- Field IDs -- */
16533 static struct {
16534 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/unix/native/libjsig/jsig.c jdk23u-jdk-23-36/src/java.base/unix/native/libjsig/jsig.c
16535 --- jdk23u-jdk-23-36.orig/src/java.base/unix/native/libjsig/jsig.c 2024-08-07 00:08:22.000000000 +0200
16536 +++ jdk23u-jdk-23-36/src/java.base/unix/native/libjsig/jsig.c 2024-08-17 19:50:33.111399095 +0200
16537 @@ -35,6 +35,16 @@
16539 #include "jni.h"
16541 +#ifdef SOLARIS
16542 +/* Our redeclarations of the system functions must not have a less
16543 + * restrictive linker scoping, so we have to declare them as JNIEXPORT
16544 + * before including signal.h */
16545 +#include "sys/signal.h"
16546 +JNIEXPORT void (*signal(int sig, void (*disp)(int)))(int);
16547 +JNIEXPORT void (*sigset(int sig, void (*disp)(int)))(int);
16548 +JNIEXPORT int sigaction(int sig, const struct sigaction *act, struct sigaction *oact);
16549 +#endif
16551 #include <dlfcn.h>
16552 #include <errno.h>
16553 #include <pthread.h>
16554 @@ -51,9 +61,16 @@
16555 #define false 0
16556 #endif
16558 +#ifdef SOLARIS
16559 +#define MAX_SIGNALS (SIGRTMAX+1)
16561 +/* On solaris, MAX_SIGNALS is a macro, not a constant, so we must allocate sact dynamically. */
16562 +static struct sigaction *sact = (struct sigaction *)NULL; /* saved signal handlers */
16563 +#else
16564 #define MAX_SIGNALS NSIG
16566 static struct sigaction sact[MAX_SIGNALS]; /* saved signal handlers */
16567 +#endif
16569 static sigset_t jvmsigs; /* Signals used by jvm. */
16571 @@ -78,6 +95,20 @@
16572 static bool jvm_signal_installed = false;
16575 +/* assume called within signal_lock */
16576 +static void allocate_sact() {
16577 +#ifdef SOLARIS
16578 + if (sact == NULL) {
16579 + sact = (struct sigaction *)malloc((MAX_SIGNALS) * (size_t)sizeof(struct sigaction));
16580 + if (sact == NULL) {
16581 + printf("%s\n", "libjsig.so unable to allocate memory");
16582 + exit(0);
16584 + memset(sact, 0, (MAX_SIGNALS) * (size_t)sizeof(struct sigaction));
16586 +#endif
16589 static void signal_lock() {
16590 pthread_mutex_lock(&mutex);
16591 /* When the jvm is installing its set of signal handlers, threads
16592 @@ -137,7 +168,18 @@
16593 sact[sig].sa_handler = disp;
16594 sigemptyset(&set);
16595 sact[sig].sa_mask = set;
16596 - sact[sig].sa_flags = 0;
16597 + if (!is_sigset) {
16598 +#ifdef SOLARIS
16599 + sact[sig].sa_flags = SA_NODEFER;
16600 + if (sig != SIGILL && sig != SIGTRAP && sig != SIGPWR) {
16601 + sact[sig].sa_flags |= SA_RESETHAND;
16603 +#else
16604 + sact[sig].sa_flags = 0;
16605 +#endif
16606 + } else {
16607 + sact[sig].sa_flags = 0;
16611 static sa_handler_t set_signal(int sig, sa_handler_t disp, bool is_sigset) {
16612 @@ -146,6 +188,7 @@
16613 bool sigblocked;
16615 signal_lock();
16616 + allocate_sact();
16618 sigused = sigismember(&jvmsigs, sig);
16619 if (jvm_signal_installed && sigused) {
16620 @@ -157,6 +200,13 @@
16621 oldhandler = sact[sig].sa_handler;
16622 save_signal_handler(sig, disp, is_sigset);
16624 +#ifdef SOLARIS
16625 + if (is_sigset && sigblocked) {
16626 + /* We won't honor the SIG_HOLD request to change the signal mask */
16627 + oldhandler = SIG_HOLD;
16629 +#endif
16631 signal_unlock();
16632 return oldhandler;
16633 } else if (jvm_signal_installing) {
16634 @@ -234,6 +284,7 @@
16636 signal_lock();
16638 + allocate_sact();
16639 sigused = sigismember(&jvmsigs, sig);
16640 if (jvm_signal_installed && sigused) {
16641 /* jvm has installed its signal handler for this signal. */
16642 @@ -300,6 +351,7 @@
16645 JNIEXPORT struct sigaction *JVM_get_signal_action(int sig) {
16646 + allocate_sact();
16647 /* Does race condition make sense here? */
16648 if (sigismember(&jvmsigs, sig)) {
16649 return &sact[sig];
16650 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/unix/native/libnet/Inet4AddressImpl.c jdk23u-jdk-23-36/src/java.base/unix/native/libnet/Inet4AddressImpl.c
16651 --- jdk23u-jdk-23-36.orig/src/java.base/unix/native/libnet/Inet4AddressImpl.c 2024-08-07 00:08:22.000000000 +0200
16652 +++ jdk23u-jdk-23-36/src/java.base/unix/native/libnet/Inet4AddressImpl.c 2024-08-17 19:50:33.111869610 +0200
16653 @@ -66,8 +66,27 @@
16654 if (gethostname(hostname, sizeof(hostname)) != 0) {
16655 strcpy(hostname, "localhost");
16656 } else {
16657 +#if defined(__solaris__)
16658 + // try to resolve hostname via nameservice
16659 + // if it is known but getnameinfo fails, hostname will still be the
16660 + // value from gethostname
16661 + struct addrinfo hints, *res;
16663 // make sure string is null-terminated
16664 hostname[NI_MAXHOST] = '\0';
16665 + memset(&hints, 0, sizeof(hints));
16666 + hints.ai_flags = AI_CANONNAME;
16667 + hints.ai_family = AF_INET;
16669 + if (getaddrinfo(hostname, NULL, &hints, &res) == 0) {
16670 + getnameinfo(res->ai_addr, res->ai_addrlen, hostname, sizeof(hostname),
16671 + NULL, 0, NI_NAMEREQD);
16672 + freeaddrinfo(res);
16674 +#else
16675 + // make sure string is null-terminated
16676 + hostname[NI_MAXHOST] = '\0';
16677 +#endif
16679 return (*env)->NewStringUTF(env, hostname);
16681 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/unix/native/libnet/Inet6AddressImpl.c jdk23u-jdk-23-36/src/java.base/unix/native/libnet/Inet6AddressImpl.c
16682 --- jdk23u-jdk-23-36.orig/src/java.base/unix/native/libnet/Inet6AddressImpl.c 2024-08-07 00:08:22.000000000 +0200
16683 +++ jdk23u-jdk-23-36/src/java.base/unix/native/libnet/Inet6AddressImpl.c 2024-08-17 19:50:33.112306576 +0200
16684 @@ -67,8 +67,27 @@
16685 if (gethostname(hostname, sizeof(hostname)) != 0) {
16686 strcpy(hostname, "localhost");
16687 } else {
16688 +#if defined(__solaris__)
16689 + // try to resolve hostname via nameservice
16690 + // if it is known but getnameinfo fails, hostname will still be the
16691 + // value from gethostname
16692 + struct addrinfo hints, *res;
16694 // make sure string is null-terminated
16695 hostname[NI_MAXHOST] = '\0';
16696 + memset(&hints, 0, sizeof(hints));
16697 + hints.ai_flags = AI_CANONNAME;
16698 + hints.ai_family = AF_UNSPEC;
16700 + if (getaddrinfo(hostname, NULL, &hints, &res) == 0) {
16701 + getnameinfo(res->ai_addr, res->ai_addrlen, hostname, sizeof(hostname),
16702 + NULL, 0, NI_NAMEREQD);
16703 + freeaddrinfo(res);
16705 +#else
16706 + // make sure string is null-terminated
16707 + hostname[NI_MAXHOST] = '\0';
16708 +#endif
16710 return (*env)->NewStringUTF(env, hostname);
16712 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/unix/native/libnet/net_util_md.c jdk23u-jdk-23-36/src/java.base/unix/native/libnet/net_util_md.c
16713 --- jdk23u-jdk-23-36.orig/src/java.base/unix/native/libnet/net_util_md.c 2024-08-07 00:08:22.000000000 +0200
16714 +++ jdk23u-jdk-23-36/src/java.base/unix/native/libnet/net_util_md.c 2024-08-17 19:50:33.114410441 +0200
16715 @@ -36,6 +36,14 @@
16716 #include <sys/utsname.h>
16717 #endif
16719 +#if defined(__solaris__)
16720 +#include <inet/nd.h>
16721 +#include <limits.h>
16722 +#include <stropts.h>
16723 +#include <sys/filio.h>
16724 +#include <sys/sockio.h>
16725 +#endif
16727 #if defined(MACOSX)
16728 #include <sys/sysctl.h>
16729 #endif
16730 @@ -50,12 +58,114 @@
16731 #define IPV6_FLOWINFO_SEND 33
16732 #endif
16734 +#if defined(__solaris__) && !defined(MAXINT)
16735 +#define MAXINT INT_MAX
16736 +#endif
16739 + * EXCLBIND socket options only on Solaris
16740 + */
16741 +#if defined(__solaris__) && !defined(TCP_EXCLBIND)
16742 +#define TCP_EXCLBIND 0x21
16743 +#endif
16744 +#if defined(__solaris__) && !defined(UDP_EXCLBIND)
16745 +#define UDP_EXCLBIND 0x0101
16746 +#endif
16748 void
16749 NET_ThrowByNameWithLastError(JNIEnv *env, const char *name,
16750 const char *defaultDetail) {
16751 JNU_ThrowByNameWithMessageAndLastError(env, name, defaultDetail);
16754 +#ifdef __solaris__
16755 +static int init_tcp_max_buf, init_udp_max_buf;
16756 +static int tcp_max_buf;
16757 +static int udp_max_buf;
16758 +static int useExclBind = 0;
16761 + * Get the specified parameter from the specified driver. The value
16762 + * of the parameter is assumed to be an 'int'. If the parameter
16763 + * cannot be obtained return -1
16764 + */
16765 +int net_getParam(char *driver, char *param)
16767 + struct strioctl stri;
16768 + char buf [64];
16769 + int s;
16770 + int value;
16772 + s = open (driver, O_RDWR);
16773 + if (s < 0) {
16774 + return -1;
16776 + strncpy (buf, param, sizeof(buf));
16777 + stri.ic_cmd = ND_GET;
16778 + stri.ic_timout = 0;
16779 + stri.ic_dp = buf;
16780 + stri.ic_len = sizeof(buf);
16781 + if (ioctl (s, I_STR, &stri) < 0) {
16782 + value = -1;
16783 + } else {
16784 + value = atoi(buf);
16786 + close (s);
16787 + return value;
16791 + * Iterative way to find the max value that SO_SNDBUF or SO_RCVBUF
16792 + * for Solaris versions that do not support the ioctl() in net_getParam().
16793 + * Ugly, but only called once (for each sotype).
16795 + * As an optimization, we make a guess using the default values for Solaris
16796 + * assuming they haven't been modified with ndd.
16797 + */
16799 +#define MAX_TCP_GUESS 1024 * 1024
16800 +#define MAX_UDP_GUESS 2 * 1024 * 1024
16802 +#define FAIL_IF_NOT_ENOBUFS if (errno != ENOBUFS) return -1
16804 +static int findMaxBuf(int fd, int opt, int sotype) {
16805 + int a = 0;
16806 + int b = MAXINT;
16807 + int initial_guess;
16808 + int limit = -1;
16810 + if (sotype == SOCK_DGRAM) {
16811 + initial_guess = MAX_UDP_GUESS;
16812 + } else {
16813 + initial_guess = MAX_TCP_GUESS;
16816 + if (setsockopt(fd, SOL_SOCKET, opt, &initial_guess, sizeof(int)) == 0) {
16817 + initial_guess++;
16818 + if (setsockopt(fd, SOL_SOCKET, opt, &initial_guess,sizeof(int)) < 0) {
16819 + FAIL_IF_NOT_ENOBUFS;
16820 + return initial_guess - 1;
16822 + a = initial_guess;
16823 + } else {
16824 + FAIL_IF_NOT_ENOBUFS;
16825 + b = initial_guess - 1;
16827 + do {
16828 + int mid = a + (b-a)/2;
16829 + if (setsockopt(fd, SOL_SOCKET, opt, &mid, sizeof(int)) == 0) {
16830 + limit = mid;
16831 + a = mid + 1;
16832 + } else {
16833 + FAIL_IF_NOT_ENOBUFS;
16834 + b = mid - 1;
16836 + } while (b >= a);
16838 + return limit;
16840 +#endif
16842 void
16843 NET_ThrowNew(JNIEnv *env, int errorNumber, char *msg) {
16844 char fullMsg[512];
16845 @@ -133,6 +243,50 @@
16847 #endif
16849 + /**
16850 + * On Solaris 8 it's possible to create INET6 sockets even
16851 + * though IPv6 is not enabled on all interfaces. Thus we
16852 + * query the number of IPv6 addresses to verify that IPv6
16853 + * has been configured on at least one interface.
16855 + * On Linux it doesn't matter - if IPv6 is built-in the
16856 + * kernel then IPv6 addresses will be bound automatically
16857 + * to all interfaces.
16858 + */
16859 +#ifdef __solaris__
16861 +#ifdef SIOCGLIFNUM
16863 + struct lifnum numifs;
16865 + numifs.lifn_family = AF_INET6;
16866 + numifs.lifn_flags = 0;
16867 + if (ioctl(fd, SIOCGLIFNUM, (char *)&numifs) < 0) {
16868 + /**
16869 + * SIOCGLIFNUM failed - assume IPv6 not configured
16870 + */
16871 + close(fd);
16872 + return JNI_FALSE;
16874 + /**
16875 + * If no IPv6 addresses then return false. If count > 0
16876 + * it's possible that all IPv6 addresses are "down" but
16877 + * that's okay as they may be brought "up" while the
16878 + * VM is running.
16879 + */
16880 + if (numifs.lifn_count == 0) {
16881 + close(fd);
16882 + return JNI_FALSE;
16885 +#else
16886 + /* SIOCGLIFNUM not defined in build environment ??? */
16887 + close(fd);
16888 + return JNI_FALSE;
16889 +#endif
16891 +#endif /* __solaris */
16894 * OK we may have the stack available in the kernel,
16895 * we should also check if the APIs are available.
16896 @@ -197,6 +351,26 @@
16900 +void parseExclusiveBindProperty(JNIEnv *env) {
16901 +#ifdef __solaris__
16902 + jstring s, flagSet;
16903 + jclass iCls;
16904 + jmethodID mid;
16906 + s = (*env)->NewStringUTF(env, "sun.net.useExclusiveBind");
16907 + CHECK_NULL(s);
16908 + iCls = (*env)->FindClass(env, "java/lang/System");
16909 + CHECK_NULL(iCls);
16910 + mid = (*env)->GetStaticMethodID(env, iCls, "getProperty",
16911 + "(Ljava/lang/String;)Ljava/lang/String;");
16912 + CHECK_NULL(mid);
16913 + flagSet = (*env)->CallStaticObjectMethod(env, iCls, mid, s);
16914 + if (flagSet != NULL) {
16915 + useExclBind = 1;
16917 +#endif
16920 JNIEXPORT jint JNICALL
16921 NET_EnableFastTcpLoopback(int fd) {
16922 return 0;
16923 @@ -438,6 +612,65 @@
16924 *iptos &= (IPTOS_TOS_MASK | IPTOS_PREC_MASK);
16927 + /*
16928 + * SOL_SOCKET/{SO_SNDBUF,SO_RCVBUF} - On Solaris we may need to clamp
16929 + * the value when it exceeds the system limit.
16930 + */
16931 +#ifdef __solaris__
16932 + if (level == SOL_SOCKET) {
16933 + if (opt == SO_SNDBUF || opt == SO_RCVBUF) {
16934 + int sotype=0;
16935 + socklen_t arglen;
16936 + int *bufsize, maxbuf;
16937 + int ret;
16939 + /* Attempt with the original size */
16940 + ret = setsockopt(fd, level, opt, arg, len);
16941 + if ((ret == 0) || (ret == -1 && errno != ENOBUFS))
16942 + return ret;
16944 + /* Exceeded system limit so clamp and retry */
16946 + arglen = sizeof(sotype);
16947 + if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *)&sotype,
16948 + &arglen) < 0) {
16949 + return -1;
16952 + /*
16953 + * We try to get tcp_maxbuf (and udp_max_buf) using
16954 + * an ioctl() that isn't available on all versions of Solaris.
16955 + * If that fails, we use the search algorithm in findMaxBuf()
16956 + */
16957 + if (!init_tcp_max_buf && sotype == SOCK_STREAM) {
16958 + tcp_max_buf = net_getParam("/dev/tcp", "tcp_max_buf");
16959 + if (tcp_max_buf == -1) {
16960 + tcp_max_buf = findMaxBuf(fd, opt, SOCK_STREAM);
16961 + if (tcp_max_buf == -1) {
16962 + return -1;
16965 + init_tcp_max_buf = 1;
16966 + } else if (!init_udp_max_buf && sotype == SOCK_DGRAM) {
16967 + udp_max_buf = net_getParam("/dev/udp", "udp_max_buf");
16968 + if (udp_max_buf == -1) {
16969 + udp_max_buf = findMaxBuf(fd, opt, SOCK_DGRAM);
16970 + if (udp_max_buf == -1) {
16971 + return -1;
16974 + init_udp_max_buf = 1;
16977 + maxbuf = (sotype == SOCK_STREAM) ? tcp_max_buf : udp_max_buf;
16978 + bufsize = (int *)arg;
16979 + if (*bufsize > maxbuf) {
16980 + *bufsize = maxbuf;
16984 +#endif
16986 #ifdef _AIX
16987 if (level == SOL_SOCKET) {
16988 if (opt == SO_SNDBUF || opt == SO_RCVBUF) {
16989 @@ -552,10 +785,20 @@
16991 * Linux allows a socket to bind to 127.0.0.255 which must be
16992 * caught.
16994 + * On Solaris with IPv6 enabled we must use an exclusive
16995 + * bind to guarantee a unique port number across the IPv4 and
16996 + * IPv6 port spaces.
17000 NET_Bind(int fd, SOCKETADDRESS *sa, int len)
17002 +#if defined(__solaris__)
17003 + int level = -1;
17004 + int exclbind = -1;
17005 + int arg, alen;
17006 +#endif
17007 int rv;
17009 #ifdef __linux__
17010 @@ -572,8 +815,61 @@
17012 #endif
17014 +#if defined(__solaris__)
17015 + /*
17016 + * Solaris has separate IPv4 and IPv6 port spaces so we
17017 + * use an exclusive bind when SO_REUSEADDR is not used to
17018 + * give the illusion of a unified port space.
17019 + * This also avoids problems with IPv6 sockets connecting
17020 + * to IPv4 mapped addresses whereby the socket conversion
17021 + * results in a late bind that fails because the
17022 + * corresponding IPv4 port is in use.
17023 + */
17024 + alen = sizeof(arg);
17026 + if (useExclBind ||
17027 + getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&arg, &alen) == 0)
17029 + if (useExclBind || arg == 0) {
17030 + /*
17031 + * SO_REUSEADDR is disabled or sun.net.useExclusiveBind
17032 + * property is true so enable TCP_EXCLBIND or
17033 + * UDP_EXCLBIND
17034 + */
17035 + alen = sizeof(arg);
17036 + if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&arg, &alen) == 0)
17038 + if (arg == SOCK_STREAM) {
17039 + level = IPPROTO_TCP;
17040 + exclbind = TCP_EXCLBIND;
17041 + } else {
17042 + level = IPPROTO_UDP;
17043 + exclbind = UDP_EXCLBIND;
17047 + arg = 1;
17048 + setsockopt(fd, level, exclbind, (char *)&arg, sizeof(arg));
17052 +#endif
17054 rv = bind(fd, &sa->sa, len);
17056 +#if defined(__solaris__)
17057 + if (rv < 0) {
17058 + int en = errno;
17059 + /* Restore *_EXCLBIND if the bind fails */
17060 + if (exclbind != -1) {
17061 + int arg = 0;
17062 + setsockopt(fd, level, exclbind, (char *)&arg,
17063 + sizeof(arg));
17065 + errno = en;
17067 +#endif
17069 return rv;
17072 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/unix/native/libnet/net_util_md.h jdk23u-jdk-23-36/src/java.base/unix/native/libnet/net_util_md.h
17073 --- jdk23u-jdk-23-36.orig/src/java.base/unix/native/libnet/net_util_md.h 2024-08-07 00:08:22.000000000 +0200
17074 +++ jdk23u-jdk-23-36/src/java.base/unix/native/libnet/net_util_md.h 2024-08-17 19:50:33.114832600 +0200
17075 @@ -47,6 +47,8 @@
17076 #ifndef SO_REUSEPORT
17077 #ifdef __linux__
17078 #define SO_REUSEPORT 15
17079 +#elif defined(__solaris__)
17080 +#define SO_REUSEPORT 0x100e
17081 #elif defined(AIX) || defined(MACOSX)
17082 #define SO_REUSEPORT 0x0200
17083 #else
17084 @@ -80,4 +82,8 @@
17085 void NET_ThrowByNameWithLastError(JNIEnv *env, const char *name,
17086 const char *defaultDetail);
17088 +#ifdef __solaris__
17089 +int net_getParam(char *driver, char *param);
17090 +#endif
17092 #endif /* NET_UTILS_MD_H */
17093 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/unix/native/libnet/NetworkInterface.c jdk23u-jdk-23-36/src/java.base/unix/native/libnet/NetworkInterface.c
17094 --- jdk23u-jdk-23-36.orig/src/java.base/unix/native/libnet/NetworkInterface.c 2024-08-07 00:08:22.000000000 +0200
17095 +++ jdk23u-jdk-23-36/src/java.base/unix/native/libnet/NetworkInterface.c 2024-08-17 19:50:33.113210527 +0200
17096 @@ -37,6 +37,12 @@
17097 #include <strings.h>
17098 #endif
17100 +#if defined(__solaris__)
17101 +#include <stropts.h>
17102 +#include <sys/dlpi.h>
17103 +#include <sys/sockio.h>
17104 +#endif
17106 #if defined(_ALLBSD_SOURCE)
17107 #include <net/ethernet.h>
17108 #include <net/if_dl.h>
17109 @@ -49,6 +55,11 @@
17111 #if defined(__linux__)
17112 #define _PATH_PROCNET_IFINET6 "/proc/net/if_inet6"
17113 +#elif defined(__solaris__)
17114 + #ifndef SIOCGLIFHWADDR
17115 + #define SIOCGLIFHWADDR _IOWR('i', 192, struct lifreq)
17116 + #endif
17117 + #define DEV_PREFIX "/dev/"
17118 #endif
17120 #ifdef LIFNAMSIZ
17121 @@ -135,6 +146,11 @@
17122 const struct in_addr *addr, unsigned char *buf);
17123 static int getMTU(JNIEnv *env, int sock, const char *ifname);
17125 +#if defined(__solaris__)
17126 +static int getMacFromDevice(JNIEnv *env, const char *ifname,
17127 + unsigned char *retbuf);
17128 +#endif
17130 /******************* Java entry points *****************************/
17133 @@ -1658,6 +1674,372 @@
17135 #endif /* _AIX */
17137 +/** Solaris **/
17138 +#if defined(__solaris__)
17141 + * Opens a socket for further ioctl calls. Tries AF_INET socket first and
17142 + * if it fails return AF_INET6 socket.
17143 + */
17144 +static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
17145 + int sock, alreadyV6 = 0;
17146 + struct lifreq if2;
17148 + if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
17149 + if (errno == EPROTONOSUPPORT || errno == EAFNOSUPPORT) {
17150 + if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
17151 + JNU_ThrowByNameWithMessageAndLastError
17152 + (env, JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
17153 + return -1;
17155 + alreadyV6 = 1;
17156 + } else { // errno is not NOSUPPORT
17157 + JNU_ThrowByNameWithMessageAndLastError
17158 + (env, JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed");
17159 + return -1;
17163 + // Solaris requires that we have an IPv6 socket to query an interface
17164 + // without an IPv4 address - check it here. POSIX 1 require the kernel to
17165 + // return ENOTTY if the call is inappropriate for a device e.g. the NETMASK
17166 + // for a device having IPv6 only address but not all devices follow the
17167 + // standard so fall back on any error. It's not an ecologically friendly
17168 + // gesture but more reliable.
17169 + if (!alreadyV6) {
17170 + memset((char *)&if2, 0, sizeof(if2));
17171 + strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
17172 + if (ioctl(sock, SIOCGLIFNETMASK, (char *)&if2) < 0) {
17173 + close(sock);
17174 + if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
17175 + JNU_ThrowByNameWithMessageAndLastError
17176 + (env, JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
17177 + return -1;
17182 + return sock;
17186 + * Enumerates and returns all IPv4 interfaces on Solaris.
17187 + */
17188 +static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
17189 + struct lifconf ifc;
17190 + struct lifreq *ifreqP;
17191 + struct lifnum numifs;
17192 + char *buf = NULL;
17193 + unsigned i;
17195 + // call SIOCGLIFNUM to get the interface count
17196 + numifs.lifn_family = AF_INET;
17197 + numifs.lifn_flags = 0;
17198 + if (ioctl(sock, SIOCGLIFNUM, (char *)&numifs) < 0) {
17199 + JNU_ThrowByNameWithMessageAndLastError
17200 + (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFNUM) failed");
17201 + return ifs;
17204 + // call SIOCGLIFCONF to enumerate the interfaces
17205 + ifc.lifc_len = numifs.lifn_count * sizeof(struct lifreq);
17206 + CHECKED_MALLOC3(buf, char *, ifc.lifc_len);
17207 + ifc.lifc_buf = buf;
17208 + ifc.lifc_family = AF_INET;
17209 + ifc.lifc_flags = 0;
17210 + if (ioctl(sock, SIOCGLIFCONF, (char *)&ifc) < 0) {
17211 + JNU_ThrowByNameWithMessageAndLastError
17212 + (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFCONF) failed");
17213 + free(buf);
17214 + return ifs;
17217 + // iterate through each interface
17218 + ifreqP = ifc.lifc_req;
17219 + for (i = 0; i < numifs.lifn_count; i++, ifreqP++) {
17220 + struct sockaddr addr, *broadaddrP = NULL;
17222 + // ignore non IPv4 addresses
17223 + if (ifreqP->lifr_addr.ss_family != AF_INET) {
17224 + continue;
17227 + // save socket address
17228 + memcpy(&addr, &(ifreqP->lifr_addr), sizeof(struct sockaddr));
17230 + // determine broadcast address, if applicable
17231 + if ((ioctl(sock, SIOCGLIFFLAGS, ifreqP) == 0) &&
17232 + ifreqP->lifr_flags & IFF_BROADCAST) {
17234 + // restore socket address to ifreqP
17235 + memcpy(&(ifreqP->lifr_addr), &addr, sizeof(struct sockaddr));
17237 + // query broadcast address and set pointer to it
17238 + if (ioctl(sock, SIOCGLIFBRDADDR, ifreqP) == 0) {
17239 + broadaddrP = (struct sockaddr *)&(ifreqP->lifr_broadaddr);
17243 + // add to the list
17244 + ifs = addif(env, sock, ifreqP->lifr_name, ifs,
17245 + &addr, broadaddrP, AF_INET, (short)ifreqP->lifr_addrlen);
17247 + // if an exception occurred we return immediately
17248 + if ((*env)->ExceptionOccurred(env)) {
17249 + free(buf);
17250 + return ifs;
17254 + // free buffer
17255 + free(buf);
17256 + return ifs;
17260 + * Enumerates and returns all IPv6 interfaces on Solaris.
17261 + */
17262 +static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
17263 + struct lifconf ifc;
17264 + struct lifreq *ifreqP;
17265 + struct lifnum numifs;
17266 + char *buf = NULL;
17267 + unsigned i;
17269 + // call SIOCGLIFNUM to get the interface count
17270 + numifs.lifn_family = AF_INET6;
17271 + numifs.lifn_flags = 0;
17272 + if (ioctl(sock, SIOCGLIFNUM, (char *)&numifs) < 0) {
17273 + JNU_ThrowByNameWithMessageAndLastError
17274 + (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFNUM) failed");
17275 + return ifs;
17278 + // call SIOCGLIFCONF to enumerate the interfaces
17279 + ifc.lifc_len = numifs.lifn_count * sizeof(struct lifreq);
17280 + CHECKED_MALLOC3(buf, char *, ifc.lifc_len);
17281 + ifc.lifc_buf = buf;
17282 + ifc.lifc_family = AF_INET6;
17283 + ifc.lifc_flags = 0;
17284 + if (ioctl(sock, SIOCGLIFCONF, (char *)&ifc) < 0) {
17285 + JNU_ThrowByNameWithMessageAndLastError
17286 + (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFCONF) failed");
17287 + free(buf);
17288 + return ifs;
17291 + // iterate through each interface
17292 + ifreqP = ifc.lifc_req;
17293 + for (i = 0; i < numifs.lifn_count; i++, ifreqP++) {
17295 + // ignore non IPv6 addresses
17296 + if (ifreqP->lifr_addr.ss_family != AF_INET6) {
17297 + continue;
17300 + // set scope ID to interface index
17301 + ((struct sockaddr_in6 *)&(ifreqP->lifr_addr))->sin6_scope_id =
17302 + getIndex(sock, ifreqP->lifr_name);
17304 + // add to the list
17305 + ifs = addif(env, sock, ifreqP->lifr_name, ifs,
17306 + (struct sockaddr *)&(ifreqP->lifr_addr),
17307 + NULL, AF_INET6, (short)ifreqP->lifr_addrlen);
17309 + // if an exception occurred we return immediately
17310 + if ((*env)->ExceptionOccurred(env)) {
17311 + free(buf);
17312 + return ifs;
17316 + // free buffer
17317 + free(buf);
17318 + return ifs;
17322 + * Try to get the interface index.
17323 + * (Not supported on Solaris 2.6 or 7)
17324 + */
17325 +static int getIndex(int sock, const char *name) {
17326 + struct lifreq if2;
17327 + memset((char *)&if2, 0, sizeof(if2));
17328 + strncpy(if2.lifr_name, name, sizeof(if2.lifr_name) - 1);
17330 + if (ioctl(sock, SIOCGLIFINDEX, (char *)&if2) < 0) {
17331 + return -1;
17334 + return if2.lifr_index;
17338 + * Solaris specific DLPI code to get hardware address from a device.
17339 + * Unfortunately, at least up to Solaris X, you have to have special
17340 + * privileges (i.e. be root).
17341 + */
17342 +static int getMacFromDevice
17343 + (JNIEnv *env, const char *ifname, unsigned char *retbuf)
17345 + char style1dev[MAXPATHLEN];
17346 + int fd;
17347 + dl_phys_addr_req_t dlpareq;
17348 + dl_phys_addr_ack_t *dlpaack;
17349 + dl_error_ack_t *dlerack;
17350 + struct strbuf msg;
17351 + char buf[128];
17352 + int flags = 0;
17354 + // Device is in /dev. e.g.: /dev/bge0
17355 + strcpy(style1dev, DEV_PREFIX);
17356 + strcat(style1dev, ifname);
17357 + if ((fd = open(style1dev, O_RDWR)) < 0) {
17358 + // Can't open it. We probably are missing the privilege.
17359 + // We'll have to try something else
17360 + return 0;
17363 + dlpareq.dl_primitive = DL_PHYS_ADDR_REQ;
17364 + dlpareq.dl_addr_type = DL_CURR_PHYS_ADDR;
17366 + msg.buf = (char *)&dlpareq;
17367 + msg.len = DL_PHYS_ADDR_REQ_SIZE;
17369 + if (putmsg(fd, &msg, NULL, 0) < 0) {
17370 + JNU_ThrowByNameWithMessageAndLastError
17371 + (env, JNU_JAVANETPKG "SocketException", "putmsg() failed");
17372 + return -1;
17375 + dlpaack = (dl_phys_addr_ack_t *)buf;
17377 + msg.buf = (char *)buf;
17378 + msg.len = 0;
17379 + msg.maxlen = sizeof (buf);
17380 + if (getmsg(fd, &msg, NULL, &flags) < 0) {
17381 + JNU_ThrowByNameWithMessageAndLastError
17382 + (env, JNU_JAVANETPKG "SocketException", "getmsg() failed");
17383 + return -1;
17386 + if (dlpaack->dl_primitive == DL_ERROR_ACK) {
17387 + dlerack = (dl_error_ack_t *)buf;
17388 + if (dlerack->dl_error_primitive != DL_PHYS_ADDR_REQ) {
17389 + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
17390 + "Couldn't obtain physical address\n");
17391 + return -1;
17393 + if (dlerack->dl_errno == DL_UNSUPPORTED) {
17394 + // fallback to lookup in the ARP table
17395 + return 0;
17399 + if (msg.len < DL_PHYS_ADDR_ACK_SIZE || dlpaack->dl_primitive != DL_PHYS_ADDR_ACK) {
17400 + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
17401 + "Couldn't obtain phys addr\n");
17402 + return -1;
17405 + memcpy(retbuf, &buf[dlpaack->dl_addr_offset], dlpaack->dl_addr_length);
17406 + return dlpaack->dl_addr_length;
17410 + * Gets the Hardware address (usually MAC address) for the named interface.
17411 + * On return puts the data in buf, and returns the length, in byte, of the
17412 + * MAC address. Returns -1 if there is no hardware address on that interface.
17413 + */
17414 +static int getMacAddress
17415 + (JNIEnv *env, const char *ifname, const struct in_addr *addr,
17416 + unsigned char *buf)
17418 + struct lifreq if2;
17419 + int len, i, sock;
17421 + if ((sock = openSocketWithFallback(env, ifname)) < 0) {
17422 + return -1;
17425 + // First, try the new (S11) SIOCGLIFHWADDR ioctl(). If that fails
17426 + // try the old way.
17427 + memset((char *)&if2, 0, sizeof(if2));
17428 + strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
17430 + if (ioctl(sock, SIOCGLIFHWADDR, &if2) != -1) {
17431 + struct sockaddr_dl *sp;
17432 + sp = (struct sockaddr_dl *)&if2.lifr_addr;
17433 + memcpy(buf, &sp->sdl_data[0], sp->sdl_alen);
17434 + close(sock);
17435 + return sp->sdl_alen;
17438 + // On Solaris we have to use DLPI, but it will only work if we have
17439 + // privileged access (i.e. root). If that fails, we try a lookup
17440 + // in the ARP table, which requires an IPv4 address.
17441 + if (((len = getMacFromDevice(env, ifname, buf)) == 0) && (addr != NULL)) {
17442 + struct arpreq arpreq;
17443 + struct sockaddr_in *sin;
17444 + struct sockaddr_in ipAddr;
17446 + len = 6; //???
17448 + sin = (struct sockaddr_in *)&arpreq.arp_pa;
17449 + memset((char *)&arpreq, 0, sizeof(struct arpreq));
17450 + ipAddr.sin_port = 0;
17451 + ipAddr.sin_family = AF_INET;
17452 + memcpy(&ipAddr.sin_addr, addr, sizeof(struct in_addr));
17453 + memcpy(&arpreq.arp_pa, &ipAddr, sizeof(struct sockaddr_in));
17454 + arpreq.arp_flags= ATF_PUBL;
17456 + if (ioctl(sock, SIOCGARP, &arpreq) < 0) {
17457 + close(sock);
17458 + return -1;
17461 + memcpy(buf, &arpreq.arp_ha.sa_data[0], len);
17463 + close(sock);
17465 + // all bytes to 0 means no hardware address
17466 + for (i = 0; i < len; i++) {
17467 + if (buf[i] != 0)
17468 + return len;
17471 + return -1;
17474 +static int getMTU(JNIEnv *env, int sock, const char *ifname) {
17475 + struct lifreq if2;
17476 + memset((char *)&if2, 0, sizeof(if2));
17477 + strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
17479 + if (ioctl(sock, SIOCGLIFMTU, (char *)&if2) < 0) {
17480 + JNU_ThrowByNameWithMessageAndLastError
17481 + (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFMTU) failed");
17482 + return -1;
17485 + return if2.lifr_mtu;
17488 +static int getFlags(int sock, const char *ifname, int *flags) {
17489 + struct lifreq if2;
17490 + memset((char *)&if2, 0, sizeof(if2));
17491 + strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
17493 + if (ioctl(sock, SIOCGLIFFLAGS, (char *)&if2) < 0) {
17494 + return -1;
17497 + *flags = if2.lifr_flags;
17498 + return 0;
17501 +#endif /* __solaris__ */
17503 /** BSD **/
17504 #if defined(_ALLBSD_SOURCE)
17506 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/unix/native/libnet/portconfig.c jdk23u-jdk-23-36/src/java.base/unix/native/libnet/portconfig.c
17507 --- jdk23u-jdk-23-36.orig/src/java.base/unix/native/libnet/portconfig.c 2024-08-07 00:08:22.000000000 +0200
17508 +++ jdk23u-jdk-23-36/src/java.base/unix/native/libnet/portconfig.c 2024-08-17 19:50:33.115185323 +0200
17509 @@ -60,6 +60,13 @@
17511 return -1;
17514 +#elif defined(__solaris__)
17516 + range->higher = net_getParam("/dev/tcp", "tcp_largest_anon_port");
17517 + range->lower = net_getParam("/dev/tcp", "tcp_smallest_anon_port");
17518 + return 0;
17520 #elif defined(_ALLBSD_SOURCE)
17522 int ret;
17523 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/unix/native/libnet/SdpSupport.c jdk23u-jdk-23-36/src/java.base/unix/native/libnet/SdpSupport.c
17524 --- jdk23u-jdk-23-36.orig/src/java.base/unix/native/libnet/SdpSupport.c 2024-08-07 00:08:22.000000000 +0200
17525 +++ jdk23u-jdk-23-36/src/java.base/unix/native/libnet/SdpSupport.c 2024-08-17 19:50:33.113595589 +0200
17526 @@ -27,7 +27,11 @@
17527 #include <sys/socket.h>
17528 #include <errno.h>
17530 -#if defined(__linux__)
17531 +#if defined(__solaris__)
17532 + #if !defined(PROTO_SDP)
17533 + #define PROTO_SDP 257
17534 + #endif
17535 +#elif defined(__linux__)
17536 #if !defined(AF_INET_SDP)
17537 #define AF_INET_SDP 27
17538 #endif
17539 @@ -44,7 +48,10 @@
17541 int s;
17543 -#if defined(__linux__)
17544 +#if defined(__solaris__)
17545 + int domain = ipv6_available() ? AF_INET6 : AF_INET;
17546 + s = socket(domain, SOCK_STREAM, PROTO_SDP);
17547 +#elif defined(__linux__)
17549 * IPv6 not supported by SDP on Linux
17551 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/unix/native/libnio/ch/DatagramChannelImpl.c jdk23u-jdk-23-36/src/java.base/unix/native/libnio/ch/DatagramChannelImpl.c
17552 --- jdk23u-jdk-23-36.orig/src/java.base/unix/native/libnio/ch/DatagramChannelImpl.c 2024-08-07 00:08:22.000000000 +0200
17553 +++ jdk23u-jdk-23-36/src/java.base/unix/native/libnio/ch/DatagramChannelImpl.c 2024-08-17 19:50:33.115649555 +0200
17554 @@ -50,6 +50,9 @@
17555 jint fd = fdval(env, fdo);
17556 int rv;
17558 +#if defined(__solaris__)
17559 + rv = connect(fd, 0, 0);
17560 +#else
17561 #if defined(__APPLE__)
17562 // On macOS systems we use disconnectx
17563 rv = disconnectx(fd, SAE_ASSOCID_ANY, SAE_CONNID_ANY);
17564 @@ -83,6 +86,8 @@
17565 rv = errno = 0;
17566 #endif // defined(_ALLBSD_SOURCE) || defined(_AIX)
17568 +#endif // defined(__solaris__)
17570 if (rv < 0)
17571 handleSocketError(env, errno);
17573 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/unix/native/libnio/ch/NativeThread.c jdk23u-jdk-23-36/src/java.base/unix/native/libnio/ch/NativeThread.c
17574 --- jdk23u-jdk-23-36.orig/src/java.base/unix/native/libnio/ch/NativeThread.c 2024-08-07 00:08:22.000000000 +0200
17575 +++ jdk23u-jdk-23-36/src/java.base/unix/native/libnio/ch/NativeThread.c 2024-08-17 19:50:33.116047985 +0200
17576 @@ -40,6 +40,9 @@
17577 #elif defined(_AIX)
17578 /* Also defined in net/aix_close.c */
17579 #define INTERRUPT_SIGNAL (SIGRTMAX - 1)
17580 +#elif defined(__solaris__)
17581 + #include <thread.h>
17582 + #define INTERRUPT_SIGNAL (SIGRTMAX - 2)
17583 #elif defined(_ALLBSD_SOURCE)
17584 /* Also defined in net/bsd_close.c */
17585 #define INTERRUPT_SIGNAL SIGIO
17586 @@ -73,14 +76,22 @@
17587 JNIEXPORT jlong JNICALL
17588 Java_sun_nio_ch_NativeThread_current0(JNIEnv *env, jclass cl)
17590 +#ifdef __solaris__
17591 + return (jlong)thr_self();
17592 +#else
17593 return (jlong)pthread_self();
17594 +#endif
17597 JNIEXPORT void JNICALL
17598 Java_sun_nio_ch_NativeThread_signal0(JNIEnv *env, jclass cl, jlong thread)
17600 int ret;
17601 +#ifdef __solaris__
17602 + ret = thr_kill((thread_t)thread, INTERRUPT_SIGNAL);
17603 +#else
17604 ret = pthread_kill((pthread_t)thread, INTERRUPT_SIGNAL);
17605 +#endif
17606 #ifdef MACOSX
17607 if (ret != 0 && ret != ESRCH)
17608 #else
17609 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/unix/native/libnio/ch/Net.c jdk23u-jdk-23-36/src/java.base/unix/native/libnio/ch/Net.c
17610 --- jdk23u-jdk-23-36.orig/src/java.base/unix/native/libnio/ch/Net.c 2024-08-07 00:08:22.000000000 +0200
17611 +++ jdk23u-jdk-23-36/src/java.base/unix/native/libnio/ch/Net.c 2024-08-17 19:50:33.116572974 +0200
17612 @@ -25,6 +25,7 @@
17614 #include <poll.h>
17615 #include <sys/ioctl.h>
17616 +#include <sys/filio.h>
17617 #include <sys/types.h>
17618 #include <sys/socket.h>
17619 #include <string.h>
17620 @@ -220,7 +221,7 @@
17621 JNIEXPORT jboolean JNICALL
17622 Java_sun_nio_ch_Net_canIPv6SocketJoinIPv4Group0(JNIEnv* env, jclass cl)
17624 -#if defined(__linux__) || defined(__APPLE__)
17625 +#if defined(__linux__) || defined(__APPLE__) || defined(__solaris__)
17626 /* IPv6 sockets can join IPv4 multicast groups */
17627 return JNI_TRUE;
17628 #else
17629 @@ -232,7 +233,7 @@
17630 JNIEXPORT jboolean JNICALL
17631 Java_sun_nio_ch_Net_canJoin6WithIPv4Group0(JNIEnv* env, jclass cl)
17633 -#if defined(__APPLE__)
17634 +#if defined(__APPLE__) || defined(__solaris__)
17635 /* IPV6_ADD_MEMBERSHIP can be used to join IPv4 multicast groups */
17636 return JNI_TRUE;
17637 #else
17638 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/unix/native/libnio/ch/nio_util.h jdk23u-jdk-23-36/src/java.base/unix/native/libnio/ch/nio_util.h
17639 --- jdk23u-jdk-23-36.orig/src/java.base/unix/native/libnio/ch/nio_util.h 2024-08-07 00:08:22.000000000 +0200
17640 +++ jdk23u-jdk-23-36/src/java.base/unix/native/libnio/ch/nio_util.h 2024-08-17 19:50:33.116895525 +0200
17641 @@ -35,6 +35,8 @@
17642 #ifndef SO_REUSEPORT
17643 #ifdef __linux__
17644 #define SO_REUSEPORT 15
17645 +#elif defined(__solaris__)
17646 +#define SO_REUSEPORT 0x100e
17647 #elif defined(AIX) || defined(MACOSX)
17648 #define SO_REUSEPORT 0x0200
17649 #else
17650 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c jdk23u-jdk-23-36/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c
17651 --- jdk23u-jdk-23-36.orig/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c 2024-08-07 00:08:22.000000000 +0200
17652 +++ jdk23u-jdk-23-36/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c 2024-08-17 19:50:33.117545230 +0200
17653 @@ -46,10 +46,17 @@
17654 #include <sys/xattr.h>
17655 #endif
17657 -/* For POSIX-compliant getpwuid_r */
17658 +/* For POSIX-compliant getpwuid_r, getgrgid_r on Solaris */
17659 +#if defined(__solaris__)
17660 +#define _POSIX_PTHREAD_SEMANTICS
17661 +#endif
17662 #include <pwd.h>
17663 #include <grp.h>
17665 +#ifdef __solaris__
17666 +#include <strings.h>
17667 +#endif
17669 #ifdef __linux__
17670 #include <sys/syscall.h>
17671 #include <sys/sysmacros.h> // makedev macros
17672 @@ -341,7 +348,8 @@
17674 /* system calls that might not be available at run time */
17676 -#if defined(_ALLBSD_SOURCE)
17677 +#if defined(__solaris__) || defined(_ALLBSD_SOURCE)
17678 + /* Solaris 64-bit does not have openat64/fstatat64 */
17679 my_openat_func = (openat_func*)dlsym(RTLD_DEFAULT, "openat");
17680 my_fstatat_func = (fstatat_func*)dlsym(RTLD_DEFAULT, "fstatat");
17681 #else
17682 diff -Nru jdk23u-jdk-23-36.orig/src/java.base/windows/native/libnet/net_util_md.c jdk23u-jdk-23-36/src/java.base/windows/native/libnet/net_util_md.c
17683 --- jdk23u-jdk-23-36.orig/src/java.base/windows/native/libnet/net_util_md.c 2024-08-07 00:08:22.000000000 +0200
17684 +++ jdk23u-jdk-23-36/src/java.base/windows/native/libnet/net_util_md.c 2024-08-17 19:50:33.118065483 +0200
17685 @@ -125,6 +125,8 @@
17687 return TRUE;
17690 +void parseExclusiveBindProperty(JNIEnv *env) {}
17693 * Since winsock doesn't have the equivalent of strerror(errno)
17694 diff -Nru jdk23u-jdk-23-36.orig/src/java.desktop/share/classes/sun/awt/FontConfiguration.java jdk23u-jdk-23-36/src/java.desktop/share/classes/sun/awt/FontConfiguration.java
17695 --- jdk23u-jdk-23-36.orig/src/java.desktop/share/classes/sun/awt/FontConfiguration.java 2024-08-07 00:08:22.000000000 +0200
17696 +++ jdk23u-jdk-23-36/src/java.desktop/share/classes/sun/awt/FontConfiguration.java 2024-08-17 19:50:33.119144043 +0200
17697 @@ -1422,6 +1422,22 @@
17701 + if (OSInfo.getOSType() == OSInfo.OSType.SOLARIS) {
17702 + for (int ii = 0; ii < table_awtfontpaths.length; ii++) {
17703 + if (table_awtfontpaths[ii] == 0) {
17704 + String script = getString(table_scriptIDs[ii]);
17705 + if (script.contains("dingbats") ||
17706 + script.contains("symbol")) {
17707 + continue;
17709 + System.err.println("\nError: "
17710 + + "<awtfontpath."
17711 + + script
17712 + + "> entry is missing!!!");
17713 + errors++;
17717 if (errors != 0) {
17718 System.err.println("!!THERE ARE " + errors + " ERROR(S) IN "
17719 + "THE FONTCONFIG FILE, PLEASE CHECK ITS CONTENT!!\n");
17720 diff -Nru jdk23u-jdk-23-36.orig/src/java.desktop/share/classes/sun/awt/OSInfo.java jdk23u-jdk-23-36/src/java.desktop/share/classes/sun/awt/OSInfo.java
17721 --- jdk23u-jdk-23-36.orig/src/java.desktop/share/classes/sun/awt/OSInfo.java 2024-08-07 00:08:22.000000000 +0200
17722 +++ jdk23u-jdk-23-36/src/java.desktop/share/classes/sun/awt/OSInfo.java 2024-08-17 19:50:33.119553322 +0200
17723 @@ -39,6 +39,7 @@
17724 public static enum OSType {
17725 WINDOWS,
17726 LINUX,
17727 + SOLARIS,
17728 MACOSX,
17729 AIX,
17730 UNKNOWN
17731 @@ -95,6 +96,7 @@
17732 // Map OperatingSystem enum values to OSType enum values.
17733 case WINDOWS -> WINDOWS;
17734 case LINUX -> LINUX;
17735 + case SOLARIS -> SOLARIS;
17736 case MACOS -> MACOSX;
17737 case AIX -> AIX;
17738 default -> UNKNOWN;
17739 diff -Nru jdk23u-jdk-23-36.orig/src/java.desktop/share/classes/sun/font/FontUtilities.java jdk23u-jdk-23-36/src/java.desktop/share/classes/sun/font/FontUtilities.java
17740 --- jdk23u-jdk-23-36.orig/src/java.desktop/share/classes/sun/font/FontUtilities.java 2024-08-07 00:08:22.000000000 +0200
17741 +++ jdk23u-jdk-23-36/src/java.desktop/share/classes/sun/font/FontUtilities.java 2024-08-17 19:50:33.120079848 +0200
17742 @@ -41,6 +41,8 @@
17744 public final class FontUtilities {
17746 + public static boolean isSolaris;
17748 public static boolean isLinux;
17750 public static boolean isMacOSX;
17751 @@ -66,6 +68,8 @@
17752 @Override
17753 public Object run() {
17755 + isSolaris = OSInfo.getOSType() == OSInfo.OSType.SOLARIS;
17757 isLinux = OSInfo.getOSType() == OSInfo.OSType.LINUX;
17759 isMacOSX = OSInfo.getOSType() == OSInfo.OSType.MACOSX;
17760 diff -Nru jdk23u-jdk-23-36.orig/src/java.desktop/share/native/libjsound/SoundDefs.h jdk23u-jdk-23-36/src/java.desktop/share/native/libjsound/SoundDefs.h
17761 --- jdk23u-jdk-23-36.orig/src/java.desktop/share/native/libjsound/SoundDefs.h 2024-08-07 00:08:22.000000000 +0200
17762 +++ jdk23u-jdk-23-36/src/java.desktop/share/native/libjsound/SoundDefs.h 2024-08-17 19:50:33.120574406 +0200
17763 @@ -29,9 +29,10 @@
17765 // types for X_PLATFORM
17766 #define X_WINDOWS 1
17767 -#define X_LINUX 2
17768 -#define X_BSD 3
17769 -#define X_MACOSX 4
17770 +#define X_SOLARIS 2
17771 +#define X_LINUX 3
17772 +#define X_BSD 4
17773 +#define X_MACOSX 5
17775 // **********************************
17776 // Make sure you set X_PLATFORM defines correctly.
17777 @@ -44,7 +45,7 @@
17780 // following is needed for _LP64
17781 -#if ((X_PLATFORM == X_LINUX) || (X_PLATFORM == X_MACOSX))
17782 +#if ((X_PLATFORM == X_SOLARIS) || (X_PLATFORM == X_LINUX) || (X_PLATFORM == X_MACOSX))
17783 #include <sys/types.h>
17784 #endif
17786 @@ -114,6 +115,11 @@
17787 #endif
17790 +#if X_PLATFORM == X_SOLARIS
17791 +#define INLINE
17792 +#endif
17795 #if X_PLATFORM == X_LINUX
17796 #define INLINE inline
17797 #endif
17798 diff -Nru jdk23u-jdk-23-36.orig/src/java.desktop/solaris/classes/sun/font/X11CNS11643.java jdk23u-jdk-23-36/src/java.desktop/solaris/classes/sun/font/X11CNS11643.java
17799 --- jdk23u-jdk-23-36.orig/src/java.desktop/solaris/classes/sun/font/X11CNS11643.java 1970-01-01 01:00:00.000000000 +0100
17800 +++ jdk23u-jdk-23-36/src/java.desktop/solaris/classes/sun/font/X11CNS11643.java 2024-08-17 19:50:33.161877582 +0200
17801 @@ -0,0 +1,178 @@
17803 + * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
17804 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
17806 + * This code is free software; you can redistribute it and/or modify it
17807 + * under the terms of the GNU General Public License version 2 only, as
17808 + * published by the Free Software Foundation. Oracle designates this
17809 + * particular file as subject to the "Classpath" exception as provided
17810 + * by Oracle in the LICENSE file that accompanied this code.
17812 + * This code is distributed in the hope that it will be useful, but WITHOUT
17813 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17814 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17815 + * version 2 for more details (a copy is included in the LICENSE file that
17816 + * accompanied this code).
17818 + * You should have received a copy of the GNU General Public License version
17819 + * 2 along with this work; if not, write to the Free Software Foundation,
17820 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17822 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
17823 + * or visit www.oracle.com if you need additional information or have any
17824 + * questions.
17825 + */
17827 +package sun.font;
17829 +import java.nio.CharBuffer;
17830 +import java.nio.ByteBuffer;
17831 +import java.nio.charset.*;
17832 +import sun.nio.cs.*;
17834 +public abstract class X11CNS11643 extends Charset {
17835 + private final int plane;
17836 + public X11CNS11643 (int plane, String name) {
17837 + super(name, null);
17838 + switch (plane) {
17839 + case 1:
17840 + this.plane = 0; // CS1
17841 + break;
17842 + case 2:
17843 + case 3:
17844 + this.plane = plane;
17845 + break;
17846 + default:
17847 + throw new IllegalArgumentException
17848 + ("Only planes 1, 2, and 3 supported");
17852 + public CharsetEncoder newEncoder() {
17853 + return new Encoder(this, plane);
17856 + public CharsetDecoder newDecoder() {
17857 + return new Decoder(this, plane);
17860 + public boolean contains(Charset cs) {
17861 + return cs instanceof X11CNS11643;
17864 + private class Encoder extends EUC_TW.Encoder {
17865 + private int plane;
17866 + public Encoder(Charset cs, int plane) {
17867 + super(cs);
17868 + this.plane = plane;
17871 + private byte[] bb = new byte[4];
17872 + public boolean canEncode(char c) {
17873 + if (c <= 0x7F) {
17874 + return false;
17876 + int nb = toEUC(c, bb);
17877 + if (nb == -1)
17878 + return false;
17879 + int p = 0;
17880 + if (nb == 4)
17881 + p = (bb[1] & 0xff) - 0xa0;
17882 + return (p == plane);
17885 + public boolean isLegalReplacement(byte[] repl) {
17886 + return true;
17889 + protected CoderResult encodeLoop(CharBuffer src, ByteBuffer dst) {
17890 + char[] sa = src.array();
17891 + int sp = src.arrayOffset() + src.position();
17892 + int sl = src.arrayOffset() + src.limit();
17893 + byte[] da = dst.array();
17894 + int dp = dst.arrayOffset() + dst.position();
17895 + int dl = dst.arrayOffset() + dst.limit();
17897 + try {
17898 + while (sp < sl) {
17899 + char c = sa[sp];
17900 + if ( c > '\u007f'&& c < '\uFFFE') {
17901 + int nb = toEUC(c, bb);
17902 + if (nb != -1) {
17903 + int p = 0;
17904 + if (nb == 4)
17905 + p = (bb[1] & 0xff) - 0xa0;
17906 + if (p == plane) {
17907 + if (dl - dp < 2)
17908 + return CoderResult.OVERFLOW;
17909 + if (nb == 2) {
17910 + da[dp++] = (byte)(bb[0] & 0x7f);
17911 + da[dp++] = (byte)(bb[1] & 0x7f);
17912 + } else {
17913 + da[dp++] = (byte)(bb[2] & 0x7f);
17914 + da[dp++] = (byte)(bb[3] & 0x7f);
17916 + sp++;
17917 + continue;
17921 + return CoderResult.unmappableForLength(1);
17923 + return CoderResult.UNDERFLOW;
17924 + } finally {
17925 + src.position(sp - src.arrayOffset());
17926 + dst.position(dp - dst.arrayOffset());
17931 + private class Decoder extends EUC_TW.Decoder {
17932 + int plane;
17933 + private String table;
17934 + protected Decoder(Charset cs, int plane) {
17935 + super(cs);
17936 + if (plane == 0)
17937 + this.plane = plane;
17938 + else if (plane == 2 || plane == 3)
17939 + this.plane = plane - 1;
17940 + else
17941 + throw new IllegalArgumentException
17942 + ("Only planes 1, 2, and 3 supported");
17945 + //we only work on array backed buffer.
17946 + protected CoderResult decodeLoop(ByteBuffer src, CharBuffer dst) {
17947 + byte[] sa = src.array();
17948 + int sp = src.arrayOffset() + src.position();
17949 + int sl = src.arrayOffset() + src.limit();
17951 + char[] da = dst.array();
17952 + int dp = dst.arrayOffset() + dst.position();
17953 + int dl = dst.arrayOffset() + dst.limit();
17955 + try {
17956 + while (sp < sl) {
17957 + if ( sl - sp < 2) {
17958 + return CoderResult.UNDERFLOW;
17960 + int b1 = (sa[sp] & 0xff) | 0x80;
17961 + int b2 = (sa[sp + 1] & 0xff) | 0x80;
17962 + char[] cc = toUnicode(b1, b2, plane);
17963 + // plane3 has non-bmp characters(added), x11cnsp3
17964 + // however does not support them
17965 + if (cc == null || cc.length == 2)
17966 + return CoderResult.unmappableForLength(2);
17967 + if (dl - dp < 1)
17968 + return CoderResult.OVERFLOW;
17969 + da[dp++] = cc[0];
17970 + sp +=2;
17972 + return CoderResult.UNDERFLOW;
17973 + } finally {
17974 + src.position(sp - src.arrayOffset());
17975 + dst.position(dp - dst.arrayOffset());
17980 diff -Nru jdk23u-jdk-23-36.orig/src/java.desktop/solaris/classes/sun/font/X11CNS11643P1.java jdk23u-jdk-23-36/src/java.desktop/solaris/classes/sun/font/X11CNS11643P1.java
17981 --- jdk23u-jdk-23-36.orig/src/java.desktop/solaris/classes/sun/font/X11CNS11643P1.java 1970-01-01 01:00:00.000000000 +0100
17982 +++ jdk23u-jdk-23-36/src/java.desktop/solaris/classes/sun/font/X11CNS11643P1.java 2024-08-17 19:50:33.162128207 +0200
17983 @@ -0,0 +1,33 @@
17985 + * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
17986 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
17988 + * This code is free software; you can redistribute it and/or modify it
17989 + * under the terms of the GNU General Public License version 2 only, as
17990 + * published by the Free Software Foundation. Oracle designates this
17991 + * particular file as subject to the "Classpath" exception as provided
17992 + * by Oracle in the LICENSE file that accompanied this code.
17994 + * This code is distributed in the hope that it will be useful, but WITHOUT
17995 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17996 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17997 + * version 2 for more details (a copy is included in the LICENSE file that
17998 + * accompanied this code).
18000 + * You should have received a copy of the GNU General Public License version
18001 + * 2 along with this work; if not, write to the Free Software Foundation,
18002 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18004 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
18005 + * or visit www.oracle.com if you need additional information or have any
18006 + * questions.
18007 + */
18010 +package sun.font;
18012 +public class X11CNS11643P1 extends X11CNS11643 {
18013 + public X11CNS11643P1() {
18014 + super(1, "X11CNS11643P1");
18017 diff -Nru jdk23u-jdk-23-36.orig/src/java.desktop/solaris/classes/sun/font/X11CNS11643P2.java jdk23u-jdk-23-36/src/java.desktop/solaris/classes/sun/font/X11CNS11643P2.java
18018 --- jdk23u-jdk-23-36.orig/src/java.desktop/solaris/classes/sun/font/X11CNS11643P2.java 1970-01-01 01:00:00.000000000 +0100
18019 +++ jdk23u-jdk-23-36/src/java.desktop/solaris/classes/sun/font/X11CNS11643P2.java 2024-08-17 19:50:33.162391145 +0200
18020 @@ -0,0 +1,32 @@
18022 + * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
18023 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
18025 + * This code is free software; you can redistribute it and/or modify it
18026 + * under the terms of the GNU General Public License version 2 only, as
18027 + * published by the Free Software Foundation. Oracle designates this
18028 + * particular file as subject to the "Classpath" exception as provided
18029 + * by Oracle in the LICENSE file that accompanied this code.
18031 + * This code is distributed in the hope that it will be useful, but WITHOUT
18032 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18033 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18034 + * version 2 for more details (a copy is included in the LICENSE file that
18035 + * accompanied this code).
18037 + * You should have received a copy of the GNU General Public License version
18038 + * 2 along with this work; if not, write to the Free Software Foundation,
18039 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18041 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
18042 + * or visit www.oracle.com if you need additional information or have any
18043 + * questions.
18044 + */
18046 +package sun.font;
18048 +public class X11CNS11643P2 extends X11CNS11643 {
18049 + public X11CNS11643P2() {
18050 + super(2, "X11CNS11643P2");
18053 diff -Nru jdk23u-jdk-23-36.orig/src/java.desktop/solaris/classes/sun/font/X11CNS11643P3.java jdk23u-jdk-23-36/src/java.desktop/solaris/classes/sun/font/X11CNS11643P3.java
18054 --- jdk23u-jdk-23-36.orig/src/java.desktop/solaris/classes/sun/font/X11CNS11643P3.java 1970-01-01 01:00:00.000000000 +0100
18055 +++ jdk23u-jdk-23-36/src/java.desktop/solaris/classes/sun/font/X11CNS11643P3.java 2024-08-17 19:50:33.162630390 +0200
18056 @@ -0,0 +1,32 @@
18058 + * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved.
18059 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
18061 + * This code is free software; you can redistribute it and/or modify it
18062 + * under the terms of the GNU General Public License version 2 only, as
18063 + * published by the Free Software Foundation. Oracle designates this
18064 + * particular file as subject to the "Classpath" exception as provided
18065 + * by Oracle in the LICENSE file that accompanied this code.
18067 + * This code is distributed in the hope that it will be useful, but WITHOUT
18068 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18069 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18070 + * version 2 for more details (a copy is included in the LICENSE file that
18071 + * accompanied this code).
18073 + * You should have received a copy of the GNU General Public License version
18074 + * 2 along with this work; if not, write to the Free Software Foundation,
18075 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18077 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
18078 + * or visit www.oracle.com if you need additional information or have any
18079 + * questions.
18080 + */
18082 +package sun.font;
18084 +public class X11CNS11643P3 extends X11CNS11643 {
18085 + public X11CNS11643P3() {
18086 + super(3, "X11CNS11643P3");
18089 diff -Nru jdk23u-jdk-23-36.orig/src/java.desktop/solaris/data/fontconfig/fontconfig.properties jdk23u-jdk-23-36/src/java.desktop/solaris/data/fontconfig/fontconfig.properties
18090 --- jdk23u-jdk-23-36.orig/src/java.desktop/solaris/data/fontconfig/fontconfig.properties 1970-01-01 01:00:00.000000000 +0100
18091 +++ jdk23u-jdk-23-36/src/java.desktop/solaris/data/fontconfig/fontconfig.properties 2024-08-17 19:50:33.138607505 +0200
18092 @@ -0,0 +1,516 @@
18095 +# Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
18096 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
18098 +# This code is free software; you can redistribute it and/or modify it
18099 +# under the terms of the GNU General Public License version 2 only, as
18100 +# published by the Free Software Foundation. Oracle designates this
18101 +# particular file as subject to the "Classpath" exception as provided
18102 +# by Oracle in the LICENSE file that accompanied this code.
18104 +# This code is distributed in the hope that it will be useful, but WITHOUT
18105 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18106 +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18107 +# version 2 for more details (a copy is included in the LICENSE file that
18108 +# accompanied this code).
18110 +# You should have received a copy of the GNU General Public License version
18111 +# 2 along with this work; if not, write to the Free Software Foundation,
18112 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18114 +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
18115 +# or visit www.oracle.com if you need additional information or have any
18116 +# questions.
18119 +# Version
18121 +version=1
18123 +# Component Font Mappings
18125 +allfonts.chinese-gb2312=-arphic-uming-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18126 +allfonts.chinese-gbk=-arphic-uming-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18127 +allfonts.chinese-gb18030-0=-arphic-uming-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18128 +allfonts.chinese-gb18030-1=-arphic-uming-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18129 +allfonts.chinese-cns11643-1=-arphic-uming-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18130 +allfonts.chinese-cns11643-2=-arphic-uming-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18131 +allfonts.chinese-cns11643-3=-arphic-uming-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18132 +allfonts.chinese-big5=-arphic-uming-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18133 +allfonts.chinese-hkscs=-arphic-uming-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18134 +allfonts.dingbats=-microsoft-wingdings-medium-r-normal--*-%d-*-*-p-*-adobe-fontspecific
18135 +allfonts.japanese-x0212=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18136 +allfonts.korean=-hanyang-gothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18137 +allfonts.korean-johab=-hanyang-gothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18138 +allfonts.symbol=-monotype-symbol-medium-r-normal--*-%d-*-*-p-*-adobe-symbol
18139 +allfonts.bengali=-misc-lohit bengali-medium-r-normal--0-0-0-0-p-0-iso10646-1
18140 +allfonts.gujarati=-misc-lohit gujarati-medium-r-normal--0-0-0-0-p-0-iso10646-1
18141 +allfonts.hindi=-misc-lohit hindi-medium-r-normal--0-0-0-0-p-0-iso10646-1
18142 +allfonts.kannada=-misc-lohit kannada-medium-r-normal--0-0-0-0-p-0-iso10646-1
18143 +allfonts.malayalam=-misc-lohit malayalam-medium-r-normal--0-0-0-0-p-0-iso10646-1
18144 +allfonts.marathi=-misc-lohit marathi-medium-r-normal--0-0-0-0-p-0-iso10646-1
18145 +allfonts.tamil=-misc-lohit tamil-medium-r-normal--0-0-0-0-p-0-iso10646-1
18146 +allfonts.telugu=-misc-lohit telugu-medium-r-normal--0-0-0-0-p-0-iso10646-1
18147 +allfonts.dejavusans=-misc-dejavu sans-medium-r-normal--0-0-0-0-p-0-iso10646-1
18149 +serif.plain.arabic=-monotype-times new roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18150 +serif.plain.cyrillic-iso8859-5=-monotype-times new roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18151 +serif.plain.cyrillic-cp1251=-monotype-times new roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18152 +serif.plain.cyrillic-koi8-r=-monotype-times new roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18153 +serif.plain.greek=-monotype-times new roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18154 +serif.plain.hebrew=-monotype-times new roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18155 +serif.plain.japanese-x0201=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18156 +serif.plain.japanese-x0208=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18157 +serif.plain.latin-1=-monotype-times new roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18158 +serif.plain.latin-2=-monotype-times new roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18159 +serif.plain.latin-5=-monotype-times new roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18160 +serif.plain.latin-7=-monotype-times new roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18161 +serif.plain.latin-9=-monotype-times new roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18162 +serif.plain.thai=-monotype-angsana new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18164 +serif.bold.arabic=-monotype-times new roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18165 +serif.bold.cyrillic-iso8859-5=-monotype-times new roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18166 +serif.bold.cyrillic-cp1251=-monotype-times new roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18167 +serif.bold.cyrillic-koi8-r=-monotype-times new roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18168 +serif.bold.greek=-monotype-times new roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18169 +serif.bold.hebrew=-monotype-times new roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18170 +serif.bold.japanese-x0201=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18171 +serif.bold.japanese-x0208=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18172 +serif.bold.latin-1=-monotype-times new roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18173 +serif.bold.latin-2=-monotype-times new roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18174 +serif.bold.latin-5=-monotype-times new roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18175 +serif.bold.latin-7=-monotype-times new roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18176 +serif.bold.latin-9=-monotype-times new roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18177 +serif.bold.thai=-monotype-angsana new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18179 +serif.italic.arabic=-monotype-times new roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18180 +serif.italic.cyrillic-iso8859-5=-monotype-times new roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18181 +serif.italic.cyrillic-cp1251=-monotype-times new roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18182 +serif.italic.cyrillic-koi8-r=-monotype-times new roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18183 +serif.italic.greek=-monotype-times new roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18184 +serif.italic.hebrew=-monotype-times new roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18185 +serif.italic.japanese-x0201=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18186 +serif.italic.japanese-x0208=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18187 +serif.italic.latin-1=-monotype-times new roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18188 +serif.italic.latin-2=-monotype-times new roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18189 +serif.italic.latin-5=-monotype-times new roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18190 +serif.italic.latin-7=-monotype-times new roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18191 +serif.italic.latin-9=-monotype-times new roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18192 +serif.italic.thai=-monotype-angsana new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18194 +serif.bolditalic.arabic=-monotype-times new roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18195 +serif.bolditalic.cyrillic-iso8859-5=-monotype-times new roman-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18196 +serif.bolditalic.cyrillic-cp1251=-monotype-times new roman-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18197 +serif.bolditalic.cyrillic-koi8-r=-monotype-times new roman-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18198 +serif.bolditalic.greek=-monotype-times new roman-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18199 +serif.bolditalic.hebrew=-monotype-times new roman-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18200 +serif.bolditalic.japanese-x0201=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18201 +serif.bolditalic.japanese-x0208=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18202 +serif.bolditalic.latin-1=-monotype-times new roman-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18203 +serif.bolditalic.latin-2=-monotype-times new roman-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18204 +serif.bolditalic.latin-5=-monotype-times new roman-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18205 +serif.bolditalic.latin-7=-monotype-times new roman-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18206 +serif.bolditalic.latin-9=-monotype-times new roman-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18207 +serif.bolditalic.thai=-monotype-angsana new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18209 +sansserif.plain.arabic=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18210 +sansserif.plain.cyrillic-iso8859-5=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18211 +sansserif.plain.cyrillic-cp1251=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18212 +sansserif.plain.cyrillic-koi8-r=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18213 +sansserif.plain.greek=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18214 +sansserif.plain.hebrew=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18215 +sansserif.plain.japanese-x0201=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18216 +sansserif.plain.japanese-x0208=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18217 +sansserif.plain.latin-1=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18218 +sansserif.plain.latin-2=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18219 +sansserif.plain.latin-5=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18220 +sansserif.plain.latin-7=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18221 +sansserif.plain.latin-9=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18222 +sansserif.plain.thai=-monotype-browallia new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18224 +sansserif.bold.arabic=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18225 +sansserif.bold.cyrillic-iso8859-5=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18226 +sansserif.bold.cyrillic-cp1251=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18227 +sansserif.bold.cyrillic-koi8-r=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18228 +sansserif.bold.greek=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18229 +sansserif.bold.hebrew=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18230 +sansserif.bold.japanese-x0201=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18231 +sansserif.bold.japanese-x0208=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18232 +sansserif.bold.latin-1=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18233 +sansserif.bold.latin-2=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18234 +sansserif.bold.latin-5=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18235 +sansserif.bold.latin-7=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18236 +sansserif.bold.latin-9=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18237 +sansserif.bold.thai=-monotype-browallia new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18239 +sansserif.italic.arabic=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18240 +sansserif.italic.cyrillic-iso8859-5=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18241 +sansserif.italic.cyrillic-cp1251=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18242 +sansserif.italic.cyrillic-koi8-r=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18243 +sansserif.italic.greek=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18244 +sansserif.italic.hebrew=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18245 +sansserif.italic.japanese-x0201=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18246 +sansserif.italic.japanese-x0208=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18247 +sansserif.italic.latin-1=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18248 +sansserif.italic.latin-2=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18249 +sansserif.italic.latin-5=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18250 +sansserif.italic.latin-7=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18251 +sansserif.italic.latin-9=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18252 +sansserif.italic.thai=-monotype-browallia new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18254 +sansserif.bolditalic.arabic=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18255 +sansserif.bolditalic.cyrillic-iso8859-5=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18256 +sansserif.bolditalic.cyrillic-cp1251=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18257 +sansserif.bolditalic.cyrillic-koi8-r=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18258 +sansserif.bolditalic.greek=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18259 +sansserif.bolditalic.hebrew=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18260 +sansserif.bolditalic.japanese-x0201=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18261 +sansserif.bolditalic.japanese-x0208=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18262 +sansserif.bolditalic.latin-1=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18263 +sansserif.bolditalic.latin-2=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18264 +sansserif.bolditalic.latin-5=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18265 +sansserif.bolditalic.latin-7=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18266 +sansserif.bolditalic.latin-9=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18267 +sansserif.bolditalic.thai=-monotype-browallia new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18269 +monospaced.plain.arabic=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18270 +monospaced.plain.cyrillic-iso8859-5=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18271 +monospaced.plain.cyrillic-cp1251=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18272 +monospaced.plain.cyrillic-koi8-r=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18273 +monospaced.plain.greek=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18274 +monospaced.plain.hebrew=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18275 +monospaced.plain.japanese-x0201=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18276 +monospaced.plain.japanese-x0208=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18277 +monospaced.plain.latin-1=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18278 +monospaced.plain.latin-2=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18279 +monospaced.plain.latin-5=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18280 +monospaced.plain.latin-7=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18281 +monospaced.plain.latin-9=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18282 +monospaced.plain.thai=-monotype-cordia new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18284 +monospaced.bold.arabic=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18285 +monospaced.bold.cyrillic-iso8859-5=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18286 +monospaced.bold.cyrillic-cp1251=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18287 +monospaced.bold.cyrillic-koi8-r=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18288 +monospaced.bold.greek=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18289 +monospaced.bold.hebrew=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18290 +monospaced.bold.japanese-x0201=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18291 +monospaced.bold.japanese-x0208=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18292 +monospaced.bold.latin-1=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18293 +monospaced.bold.latin-2=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18294 +monospaced.bold.latin-5=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18295 +monospaced.bold.latin-7=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18296 +monospaced.bold.latin-9=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18297 +monospaced.bold.thai=-monotype-cordia new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18299 +monospaced.italic.arabic=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18300 +monospaced.italic.cyrillic-iso8859-5=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18301 +monospaced.italic.cyrillic-cp1251=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18302 +monospaced.italic.cyrillic-koi8-r=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18303 +monospaced.italic.greek=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18304 +monospaced.italic.hebrew=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18305 +monospaced.italic.japanese-x0201=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18306 +monospaced.italic.japanese-x0208=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18307 +monospaced.italic.latin-1=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18308 +monospaced.italic.latin-2=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18309 +monospaced.italic.latin-5=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18310 +monospaced.italic.latin-7=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18311 +monospaced.italic.latin-9=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18312 +monospaced.italic.thai=-monotype-cordia new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18314 +monospaced.bolditalic.arabic=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18315 +monospaced.bolditalic.cyrillic-iso8859-5=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18316 +monospaced.bolditalic.cyrillic-cp1251=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18317 +monospaced.bolditalic.cyrillic-koi8-r=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18318 +monospaced.bolditalic.greek=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18319 +monospaced.bolditalic.hebrew=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18320 +monospaced.bolditalic.japanese-x0201=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18321 +monospaced.bolditalic.japanese-x0208=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18322 +monospaced.bolditalic.latin-1=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18323 +monospaced.bolditalic.latin-2=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18324 +monospaced.bolditalic.latin-5=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18325 +monospaced.bolditalic.latin-7=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18326 +monospaced.bolditalic.latin-9=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18327 +monospaced.bolditalic.thai=-monotype-cordia new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18329 +dialog.plain.arabic=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18330 +dialog.plain.cyrillic-iso8859-5=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18331 +dialog.plain.cyrillic-cp1251=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18332 +dialog.plain.cyrillic-koi8-r=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18333 +dialog.plain.greek=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18334 +dialog.plain.hebrew=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18335 +dialog.plain.japanese-x0201=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18336 +dialog.plain.japanese-x0208=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18337 +dialog.plain.latin-1=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18338 +dialog.plain.latin-2=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18339 +dialog.plain.latin-5=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18340 +dialog.plain.latin-7=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18341 +dialog.plain.latin-9=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18342 +dialog.plain.thai=-monotype-browallia new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18344 +dialog.bold.arabic=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18345 +dialog.bold.cyrillic-iso8859-5=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18346 +dialog.bold.cyrillic-cp1251=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18347 +dialog.bold.cyrillic-koi8-r=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18348 +dialog.bold.greek=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18349 +dialog.bold.hebrew=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18350 +dialog.bold.japanese-x0201=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18351 +dialog.bold.japanese-x0208=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18352 +dialog.bold.latin-1=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18353 +dialog.bold.latin-2=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18354 +dialog.bold.latin-5=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18355 +dialog.bold.latin-7=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18356 +dialog.bold.latin-9=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18357 +dialog.bold.thai=-monotype-browallia new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18359 +dialog.italic.arabic=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18360 +dialog.italic.cyrillic-iso8859-5=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18361 +dialog.italic.cyrillic-cp1251=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18362 +dialog.italic.cyrillic-koi8-r=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18363 +dialog.italic.greek=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18364 +dialog.italic.hebrew=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18365 +dialog.italic.japanese-x0201=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18366 +dialog.italic.japanese-x0208=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18367 +dialog.italic.latin-1=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18368 +dialog.italic.latin-2=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18369 +dialog.italic.latin-5=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18370 +dialog.italic.latin-7=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18371 +dialog.italic.latin-9=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18372 +dialog.italic.thai=-monotype-browallia new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18374 +dialog.bolditalic.arabic=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18375 +dialog.bolditalic.cyrillic-iso8859-5=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18376 +dialog.bolditalic.cyrillic-cp1251=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18377 +dialog.bolditalic.cyrillic-koi8-r=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18378 +dialog.bolditalic.greek=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18379 +dialog.bolditalic.hebrew=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18380 +dialog.bolditalic.japanese-x0201=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18381 +dialog.bolditalic.japanese-x0208=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18382 +dialog.bolditalic.latin-1=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18383 +dialog.bolditalic.latin-2=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18384 +dialog.bolditalic.latin-5=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18385 +dialog.bolditalic.latin-7=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18386 +dialog.bolditalic.latin-9=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18387 +dialog.bolditalic.thai=-monotype-browallia new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18389 +dialoginput.plain.arabic=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18390 +dialoginput.plain.cyrillic-iso8859-5=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18391 +dialoginput.plain.cyrillic-cp1251=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18392 +dialoginput.plain.cyrillic-koi8-r=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18393 +dialoginput.plain.greek=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18394 +dialoginput.plain.hebrew=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18395 +dialoginput.plain.japanese-x0201=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18396 +dialoginput.plain.japanese-x0208=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18397 +dialoginput.plain.latin-1=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18398 +dialoginput.plain.latin-2=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18399 +dialoginput.plain.latin-5=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18400 +dialoginput.plain.latin-7=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18401 +dialoginput.plain.latin-9=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18402 +dialoginput.plain.thai=-monotype-cordia new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18404 +dialoginput.bold.arabic=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18405 +dialoginput.bold.cyrillic-iso8859-5=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18406 +dialoginput.bold.cyrillic-cp1251=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18407 +dialoginput.bold.cyrillic-koi8-r=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18408 +dialoginput.bold.greek=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18409 +dialoginput.bold.hebrew=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18410 +dialoginput.bold.japanese-x0201=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18411 +dialoginput.bold.japanese-x0208=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18412 +dialoginput.bold.latin-1=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18413 +dialoginput.bold.latin-2=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18414 +dialoginput.bold.latin-5=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18415 +dialoginput.bold.latin-7=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18416 +dialoginput.bold.latin-9=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18417 +dialoginput.bold.thai=-monotype-cordia new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18419 +dialoginput.italic.arabic=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18420 +dialoginput.italic.cyrillic-iso8859-5=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18421 +dialoginput.italic.cyrillic-cp1251=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18422 +dialoginput.italic.cyrillic-koi8-r=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18423 +dialoginput.italic.greek=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18424 +dialoginput.italic.hebrew=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18425 +dialoginput.italic.japanese-x0201=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18426 +dialoginput.italic.japanese-x0208=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18427 +dialoginput.italic.latin-1=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18428 +dialoginput.italic.latin-2=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18429 +dialoginput.italic.latin-5=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18430 +dialoginput.italic.latin-7=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18431 +dialoginput.italic.latin-9=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18432 +dialoginput.italic.thai=-monotype-cordia new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18434 +dialoginput.bolditalic.arabic=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18435 +dialoginput.bolditalic.cyrillic-iso8859-5=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18436 +dialoginput.bolditalic.cyrillic-cp1251=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18437 +dialoginput.bolditalic.cyrillic-koi8-r=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18438 +dialoginput.bolditalic.greek=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18439 +dialoginput.bolditalic.hebrew=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18440 +dialoginput.bolditalic.japanese-x0201=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18441 +dialoginput.bolditalic.japanese-x0208=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18442 +dialoginput.bolditalic.latin-1=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18443 +dialoginput.bolditalic.latin-2=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18444 +dialoginput.bolditalic.latin-5=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18445 +dialoginput.bolditalic.latin-7=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18446 +dialoginput.bolditalic.latin-9=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18447 +dialoginput.bolditalic.thai=-monotype-cordia new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18449 +# Search Sequences
18451 +sequence.allfonts=latin-1
18453 +sequence.allfonts.Big5=latin-1,chinese-big5
18455 +sequence.allfonts.Big5-HKSCS-2001=latin-1,chinese-big5,chinese-hkscs
18457 +sequence.allfonts.windows-1251=cyrillic-cp1251,latin-1
18459 +sequence.allfonts.GB2312=latin-1,chinese-gb2312
18461 +sequence.allfonts.x-eucJP-Open=latin-1,japanese-x0201,japanese-x0208,japanese-x0212
18463 +sequence.allfonts.EUC-KR=latin-1,korean
18465 +sequence.allfonts.x-EUC-TW=latin-1,chinese-cns11643-1,chinese-cns11643-2,chinese-cns11643-3
18467 +sequence.allfonts.GBK=latin-1,chinese-gbk
18469 +sequence.allfonts.GB18030=latin-1,chinese-gb18030-0,chinese-gb18030-1
18471 +sequence.allfonts.ISO-8859-2=latin-2,latin-1
18473 +sequence.allfonts.ISO-8859-5=cyrillic-iso8859-5,latin-1
18475 +sequence.allfonts.ISO-8859-6=arabic,latin-1
18477 +sequence.allfonts.ISO-8859-7=latin-1,greek
18479 +sequence.allfonts.ISO-8859-8=latin-1,hebrew
18481 +sequence.allfonts.ISO-8859-9=latin-5,latin-1
18483 +sequence.allfonts.ISO-8859-13=latin-7,latin-1
18485 +sequence.allfonts.ISO-8859-15=latin-9
18487 +sequence.allfonts.KOI8-R=cyrillic-koi8-r,latin-1
18489 +sequence.allfonts.x-PCK=latin-1,japanese-x0201,japanese-x0208,japanese-x0212
18491 +sequence.allfonts.TIS-620=latin-1,thai
18493 +sequence.allfonts.UTF-8=latin-1
18494 +sequence.allfonts.UTF-8.en=latin-1
18495 +sequence.allfonts.UTF-8.hi=latin-1,hindi
18496 +sequence.allfonts.UTF-8.be=latin-1,bengali
18497 +sequence.allfonts.UTF-8.te=latin-1,telugu
18498 +sequence.allfonts.UTF-8.mr=latin-1,marathi
18499 +sequence.allfonts.UTF-8.ta=latin-1,tamil
18500 +sequence.allfonts.UTF-8.gu=latin-1,gujarati
18501 +sequence.allfonts.UTF-8.kn=latin-1,kannada
18502 +sequence.allfonts.UTF-8.ma=latin-1,malayalam
18504 +sequence.allfonts.UTF-8.ko=latin-1,korean-johab,japanese-x0201,japanese-x0208,japanese-x0212
18506 +sequence.allfonts.UTF-8.th=latin-1,thai
18508 +sequence.allfonts.UTF-8.zh.CN=latin-1,chinese-gb18030-0,chinese-gb18030-1,chinese-big5,chinese-hkscs
18510 +sequence.allfonts.UTF-8.zh.HK=latin-1,chinese-big5,chinese-hkscs,chinese-gb18030-0,chinese-gb18030-1
18512 +sequence.allfonts.UTF-8.zh.TW=latin-1,chinese-big5,chinese-hkscs,chinese-gb18030-0,chinese-gb18030-1
18514 +# the fallback sequence omits the following character subsets:
18515 +# - chinese: all same file : just use chinese-gb18030-0
18516 +# - japanese-x0208: same files as japanese-x0201
18517 +# - japanese-x0212: same files as japanese-x0201
18518 +# - korean: same file as korean-johab
18519 +sequence.fallback=latin-1,latin-2,latin-7,cyrillic-iso8859-5,greek,latin-5,latin-9,\
18520 + arabic,hebrew,thai,\
18521 + chinese-gb18030-0,\
18522 + japanese-x0201,korean-johab,\
18523 + hindi,bengali,telugu,marathi,tamil,gujarati,kannada,malayalam,\
18524 + dejavusans,dingbats,symbol
18526 +# Font File Names
18528 +filename.-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/arial.ttf
18529 +filename.-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/ariali.ttf
18530 +filename.-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/arialbd.ttf
18531 +filename.-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/arialbi.ttf
18532 +filename.-monotype-courier_new-medium-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/cour.ttf
18533 +filename.-monotype-courier_new-medium-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/couri.ttf
18534 +filename.-monotype-courier_new-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/courbd.ttf
18535 +filename.-monotype-courier_new-bold-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/courbi.ttf
18536 +filename.-monotype-times_new_roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/times.ttf
18537 +filename.-monotype-times_new_roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/timesi.ttf
18538 +filename.-monotype-times_new_roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/timesbd.ttf
18539 +filename.-monotype-times_new_roman-bold-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/timesbi.ttf
18541 +filename.-monotype-angsana_new-medium-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/angsa.ttf
18542 +filename.-monotype-angsana_new-medium-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/angsai.ttf
18543 +filename.-monotype-angsana_new-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/angsab.ttf
18544 +filename.-monotype-angsana_new-bold-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/angsaz.ttf
18545 +filename.-monotype-browallia_new-medium-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/browa.ttf
18546 +filename.-monotype-browallia_new-medium-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/browai.ttf
18547 +filename.-monotype-browallia_new-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/browab.ttf
18548 +filename.-monotype-browallia_new-bold-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/browaz.ttf
18549 +filename.-monotype-cordia_new-medium-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/cordia.ttf
18550 +filename.-monotype-cordia_new-medium-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/cordiai.ttf
18551 +filename.-monotype-cordia_new-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/cordiab.ttf
18552 +filename.-monotype-cordia_new-bold-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/cordiaz.ttf
18554 +filename.-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1=/usr/share/fonts/TrueType/ipafont/ipag.otf
18555 +filename.-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1=/usr/share/fonts/TrueType/ipafont/ipam.otf
18556 +filename.-hanyang-gothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1=/usr/share/fonts/TrueType/hanyang/h2gtrm.ttf
18557 +filename.-arphic-uming-medium-r-normal--*-%d-*-*-m-*-iso10646-1=/usr/share/fonts/TrueType/arphic/uming.ttf
18558 +filename.-monotype-symbol-medium-r-normal--*-%d-*-*-p-*-adobe-symbol=/usr/share/fonts/TrueType/core/symbol.ttf
18559 +filename.-microsoft-wingdings-medium-r-normal--*-%d-*-*-p-*-adobe-fontspecific=/usr/share/fonts/TrueType/core/wingdings.ttf
18560 +filename.-misc-lohit_bengali-medium-r-normal--0-0-0-0-p-0-iso10646-1=/usr/share/fonts/TrueType/lohit/Lohit-Bengali.ttf
18561 +filename.-misc-lohit_gujarati-medium-r-normal--0-0-0-0-p-0-iso10646-1=/usr/share/fonts/TrueType/lohit/Lohit-Gujarati.ttf
18562 +filename.-misc-lohit_hindi-medium-r-normal--0-0-0-0-p-0-iso10646-1=/usr/share/fonts/TrueType/lohit/Lohit-Hindi.ttf
18563 +filename.-misc-lohit_kannada-medium-r-normal--0-0-0-0-p-0-iso10646-1=/usr/share/fonts/TrueType/lohit/Lohit-Kannada.ttf
18564 +filename.-misc-lohit_malayalam-medium-r-normal--0-0-0-0-p-0-iso10646-1=/usr/share/fonts/TrueType/lohit/Lohit-Malayalam.ttf
18565 +filename.-misc-lohit_marathi-medium-r-normal--0-0-0-0-p-0-iso10646-1=/usr/share/fonts/TrueType/lohit/Lohit-Marathi.ttf
18566 +filename.-misc-lohit_tamil-medium-r-normal--0-0-0-0-p-0-iso10646-1=/usr/share/fonts/TrueType/lohit/Lohit-Tamil.ttf
18567 +filename.-misc-lohit_telugu-medium-r-normal--0-0-0-0-p-0-iso10646-1=/usr/share/fonts/TrueType/lohit/Lohit-Telugu.ttf
18568 +filename.-misc-dejavu_sans-medium-r-normal--0-0-0-0-p-0-iso10646-1=/usr/share/fonts/TrueType/dejavu/DejaVuSans.ttf
18570 +# AWT X11 font paths
18571 +awtfontpath.latin-1=/usr/share/fonts/TrueType/core
18572 +awtfontpath.latin-2=/usr/share/fonts/TrueType/core
18573 +awtfontpath.latin-5=/usr/share/fonts/TrueType/core
18574 +awtfontpath.latin-7=/usr/share/fonts/TrueType/core
18575 +awtfontpath.latin-9=/usr/share/fonts/TrueType/core
18576 +awtfontpath.hebrew=/usr/share/fonts/TrueType/core
18577 +awtfontpath.arabic=/usr/share/fonts/TrueType/core
18578 +awtfontpath.thai=/usr/share/fonts/TrueType/core
18579 +awtfontpath.greek=/usr/share/fonts/TrueType/core
18580 +awtfontpath.cyrillic-iso8859-5=/usr/share/fonts/TrueType/core
18581 +awtfontpath.cyrillic-cp1251=/usr/share/fonts/TrueType/core
18582 +awtfontpath.cyrillic-koi8-r=/usr/share/fonts/TrueType/core
18583 +awtfontpath.korean=/usr/share/fonts/TrueType/hanyang
18584 +awtfontpath.korean-johab=/usr/share/fonts/TrueType/hanyang
18585 +awtfontpath.japanese-x0201=/usr/share/fonts/TrueType/ipafont
18586 +awtfontpath.japanese-x0208=/usr/share/fonts/TrueType/ipafont
18587 +awtfontpath.japanese-x0212=/usr/share/fonts/TrueType/ipafont
18588 +awtfontpath.chinese-gbk=/usr/share/fonts/TrueType/arphic
18589 +awtfontpath.chinese-cns11643-1=/usr/share/fonts/TrueType/arphic
18590 +awtfontpath.chinese-cns11643-2=/usr/share/fonts/TrueType/arphic
18591 +awtfontpath.chinese-cns11643-3=/usr/share/fonts/TrueType/arphic
18592 +awtfontpath.chinese-big5=/usr/share/fonts/TrueType/arphic
18593 +awtfontpath.chinese-gb2312=/usr/share/fonts/TrueType/arphic
18594 +awtfontpath.chinese-gb18030-0=/usr/share/fonts/TrueType/arphic
18595 +awtfontpath.chinese-gb18030-1=/usr/share/fonts/TrueType/arphic
18596 +awtfontpath.chinese-hkscs=/usr/share/fonts/TrueType/arphic
18597 +awtfontpath.bengali=/usr/share/fonts/TrueType/lohit
18598 +awtfontpath.gujarati=/usr/share/fonts/TrueType/lohit
18599 +awtfontpath.hindi=/usr/share/fonts/TrueType/lohit
18600 +awtfontpath.kannada=/usr/share/fonts/TrueType/lohit
18601 +awtfontpath.malayalam=/usr/share/fonts/TrueType/lohit
18602 +awtfontpath.marathi=/usr/share/fonts/TrueType/lohit
18603 +awtfontpath.tamil=/usr/share/fonts/TrueType/lohit
18604 +awtfontpath.telugu=/usr/share/fonts/TrueType/lohit
18605 +awtfontpath.dejavusans=/usr/share/fonts/TrueType/dejavu
18607 +# Appended Font Path
18609 diff -Nru jdk23u-jdk-23-36.orig/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_PCM.c jdk23u-jdk-23-36/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_PCM.c
18610 --- jdk23u-jdk-23-36.orig/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_PCM.c 1970-01-01 01:00:00.000000000 +0100
18611 +++ jdk23u-jdk-23-36/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_PCM.c 2024-08-17 19:50:33.163208605 +0200
18612 @@ -0,0 +1,627 @@
18614 + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
18615 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
18617 + * This code is free software; you can redistribute it and/or modify it
18618 + * under the terms of the GNU General Public License version 2 only, as
18619 + * published by the Free Software Foundation. Oracle designates this
18620 + * particular file as subject to the "Classpath" exception as provided
18621 + * by Oracle in the LICENSE file that accompanied this code.
18623 + * This code is distributed in the hope that it will be useful, but WITHOUT
18624 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18625 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18626 + * version 2 for more details (a copy is included in the LICENSE file that
18627 + * accompanied this code).
18629 + * You should have received a copy of the GNU General Public License version
18630 + * 2 along with this work; if not, write to the Free Software Foundation,
18631 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18633 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
18634 + * or visit www.oracle.com if you need additional information or have any
18635 + * questions.
18636 + */
18638 +#define USE_ERROR
18639 +#define USE_TRACE
18641 +#include "PLATFORM_API_SolarisOS_Utils.h"
18642 +#include "DirectAudio.h"
18644 +#if USE_DAUDIO == TRUE
18647 +// The default buffer time
18648 +#define DEFAULT_PERIOD_TIME_MILLIS 50
18650 +///// implemented functions of DirectAudio.h
18652 +INT32 DAUDIO_GetDirectAudioDeviceCount() {
18653 + return (INT32) getAudioDeviceCount();
18657 +INT32 DAUDIO_GetDirectAudioDeviceDescription(INT32 mixerIndex,
18658 + DirectAudioDeviceDescription* description) {
18659 + AudioDeviceDescription desc;
18661 + if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, TRUE)) {
18662 + description->maxSimulLines = desc.maxSimulLines;
18663 + strncpy(description->name, desc.name, DAUDIO_STRING_LENGTH-1);
18664 + description->name[DAUDIO_STRING_LENGTH-1] = 0;
18665 + strncpy(description->vendor, desc.vendor, DAUDIO_STRING_LENGTH-1);
18666 + description->vendor[DAUDIO_STRING_LENGTH-1] = 0;
18667 + strncpy(description->version, desc.version, DAUDIO_STRING_LENGTH-1);
18668 + description->version[DAUDIO_STRING_LENGTH-1] = 0;
18669 + /*strncpy(description->description, desc.description, DAUDIO_STRING_LENGTH-1);*/
18670 + strncpy(description->description, "Solaris Mixer", DAUDIO_STRING_LENGTH-1);
18671 + description->description[DAUDIO_STRING_LENGTH-1] = 0;
18672 + return TRUE;
18674 + return FALSE;
18678 +#define MAX_SAMPLE_RATES 20
18680 +void DAUDIO_GetFormats(INT32 mixerIndex, INT32 deviceID, int isSource, void* creator) {
18681 + int fd = -1;
18682 + AudioDeviceDescription desc;
18683 + am_sample_rates_t *sr;
18684 + /* hardcoded bits and channels */
18685 + int bits[] = {8, 16};
18686 + int bitsCount = 2;
18687 + int channels[] = {1, 2};
18688 + int channelsCount = 2;
18689 + /* for querying sample rates */
18690 + int err;
18691 + int ch, b;
18692 + uint_t s;
18694 + TRACE2("DAUDIO_GetFormats, mixer %d, isSource=%d\n", mixerIndex, isSource);
18695 + if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, FALSE)) {
18696 + fd = open(desc.pathctl, O_RDONLY);
18698 + if (fd < 0) {
18699 + ERROR1("Couldn't open audio device ctl for device %d!\n", mixerIndex);
18700 + return;
18703 + /* get sample rates */
18704 + sr = (am_sample_rates_t*) malloc(AUDIO_MIXER_SAMP_RATES_STRUCT_SIZE(MAX_SAMPLE_RATES));
18705 + if (sr == NULL) {
18706 + ERROR1("DAUDIO_GetFormats: out of memory for mixer %d\n", (int) mixerIndex);
18707 + close(fd);
18708 + return;
18711 + sr->num_samp_rates = MAX_SAMPLE_RATES;
18712 + sr->type = isSource?AUDIO_PLAY:AUDIO_RECORD;
18713 + sr->samp_rates[0] = -2;
18714 + err = ioctl(fd, AUDIO_MIXER_GET_SAMPLE_RATES, sr);
18715 + if (err < 0) {
18716 + ERROR1(" DAUDIO_GetFormats: AUDIO_MIXER_GET_SAMPLE_RATES failed for mixer %d!\n",
18717 + (int)mixerIndex);
18718 + ERROR2(" -> num_sample_rates=%d sample_rates[0] = %d\n",
18719 + (int) sr->num_samp_rates,
18720 + (int) sr->samp_rates[0]);
18721 + /* Some Solaris 8 drivers fail for get sample rates!
18722 + * Do as if we support all sample rates
18723 + */
18724 + sr->flags = MIXER_SR_LIMITS;
18726 + if ((sr->flags & MIXER_SR_LIMITS)
18727 + || (sr->num_samp_rates > MAX_SAMPLE_RATES)) {
18728 +#ifdef USE_TRACE
18729 + if ((sr->flags & MIXER_SR_LIMITS)) {
18730 + TRACE1(" DAUDIO_GetFormats: floating sample rate allowed by mixer %d\n",
18731 + (int)mixerIndex);
18733 + if (sr->num_samp_rates > MAX_SAMPLE_RATES) {
18734 + TRACE2(" DAUDIO_GetFormats: more than %d formats. Use -1 for sample rates mixer %d\n",
18735 + MAX_SAMPLE_RATES, (int)mixerIndex);
18737 +#endif
18738 + /*
18739 + * Fake it to have only one sample rate: -1
18740 + */
18741 + sr->num_samp_rates = 1;
18742 + sr->samp_rates[0] = -1;
18744 + close(fd);
18746 + for (ch = 0; ch < channelsCount; ch++) {
18747 + for (b = 0; b < bitsCount; b++) {
18748 + for (s = 0; s < sr->num_samp_rates; s++) {
18749 + DAUDIO_AddAudioFormat(creator,
18750 + bits[b], /* significant bits */
18751 + 0, /* frameSize: let it be calculated */
18752 + channels[ch],
18753 + (float) ((int) sr->samp_rates[s]),
18754 + DAUDIO_PCM, /* encoding - let's only do PCM */
18755 + (bits[b] > 8)?TRUE:TRUE, /* isSigned */
18756 +#ifdef _LITTLE_ENDIAN
18757 + FALSE /* little endian */
18758 +#else
18759 + (bits[b] > 8)?TRUE:FALSE /* big endian */
18760 +#endif
18761 + );
18765 + free(sr);
18769 +typedef struct {
18770 + int fd;
18771 + audio_info_t info;
18772 + int bufferSizeInBytes;
18773 + int frameSize; /* storage size in Bytes */
18774 + /* how many bytes were written or read */
18775 + INT32 transferedBytes;
18776 + /* if transferedBytes exceed 32-bit boundary,
18777 + * it will be reset and positionOffset will receive
18778 + * the offset
18779 + */
18780 + INT64 positionOffset;
18781 +} SolPcmInfo;
18784 +void* DAUDIO_Open(INT32 mixerIndex, INT32 deviceID, int isSource,
18785 + int encoding, float sampleRate, int sampleSizeInBits,
18786 + int frameSize, int channels,
18787 + int isSigned, int isBigEndian, int bufferSizeInBytes) {
18788 + int err = 0;
18789 + int openMode;
18790 + AudioDeviceDescription desc;
18791 + SolPcmInfo* info;
18793 + TRACE0("> DAUDIO_Open\n");
18794 + if (encoding != DAUDIO_PCM) {
18795 + ERROR1(" DAUDIO_Open: invalid encoding %d\n", (int) encoding);
18796 + return NULL;
18798 + if (channels <= 0) {
18799 + ERROR1(" DAUDIO_Open: Invalid number of channels=%d!\n", channels);
18800 + return NULL;
18803 + info = (SolPcmInfo*) malloc(sizeof(SolPcmInfo));
18804 + if (!info) {
18805 + ERROR0("Out of memory\n");
18806 + return NULL;
18808 + memset(info, 0, sizeof(SolPcmInfo));
18809 + info->frameSize = frameSize;
18810 + info->fd = -1;
18812 + if (isSource) {
18813 + openMode = O_WRONLY;
18814 + } else {
18815 + openMode = O_RDONLY;
18818 +#ifndef __linux__
18819 + /* blackdown does not use NONBLOCK */
18820 + openMode |= O_NONBLOCK;
18821 +#endif
18823 + if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, FALSE)) {
18824 + info->fd = open(desc.path, openMode);
18826 + if (info->fd < 0) {
18827 + ERROR1("Couldn't open audio device for mixer %d!\n", mixerIndex);
18828 + free(info);
18829 + return NULL;
18831 + /* set to multiple open */
18832 + if (ioctl(info->fd, AUDIO_MIXER_MULTIPLE_OPEN, NULL) >= 0) {
18833 + TRACE1("DAUDIO_Open: %s set to multiple open\n", desc.path);
18834 + } else {
18835 + ERROR1("DAUDIO_Open: ioctl AUDIO_MIXER_MULTIPLE_OPEN failed on %s!\n", desc.path);
18838 + AUDIO_INITINFO(&(info->info));
18839 + /* need AUDIO_GETINFO ioctl to get this to work on solaris x86 */
18840 + err = ioctl(info->fd, AUDIO_GETINFO, &(info->info));
18842 + /* not valid to call AUDIO_SETINFO ioctl with all the fields from AUDIO_GETINFO. */
18843 + AUDIO_INITINFO(&(info->info));
18845 + if (isSource) {
18846 + info->info.play.sample_rate = sampleRate;
18847 + info->info.play.precision = sampleSizeInBits;
18848 + info->info.play.channels = channels;
18849 + info->info.play.encoding = AUDIO_ENCODING_LINEAR;
18850 + info->info.play.buffer_size = bufferSizeInBytes;
18851 + info->info.play.pause = 1;
18852 + } else {
18853 + info->info.record.sample_rate = sampleRate;
18854 + info->info.record.precision = sampleSizeInBits;
18855 + info->info.record.channels = channels;
18856 + info->info.record.encoding = AUDIO_ENCODING_LINEAR;
18857 + info->info.record.buffer_size = bufferSizeInBytes;
18858 + info->info.record.pause = 1;
18860 + err = ioctl(info->fd, AUDIO_SETINFO, &(info->info));
18861 + if (err < 0) {
18862 + ERROR0("DAUDIO_Open: could not set info!\n");
18863 + DAUDIO_Close((void*) info, isSource);
18864 + return NULL;
18866 + DAUDIO_Flush((void*) info, isSource);
18868 + err = ioctl(info->fd, AUDIO_GETINFO, &(info->info));
18869 + if (err >= 0) {
18870 + if (isSource) {
18871 + info->bufferSizeInBytes = info->info.play.buffer_size;
18872 + } else {
18873 + info->bufferSizeInBytes = info->info.record.buffer_size;
18875 + TRACE2("DAUDIO: buffersize in bytes: requested=%d, got %d\n",
18876 + (int) bufferSizeInBytes,
18877 + (int) info->bufferSizeInBytes);
18878 + } else {
18879 + ERROR0("DAUDIO_Open: cannot get info!\n");
18880 + DAUDIO_Close((void*) info, isSource);
18881 + return NULL;
18883 + TRACE0("< DAUDIO_Open: Opened device successfully.\n");
18884 + return (void*) info;
18888 +int DAUDIO_Start(void* id, int isSource) {
18889 + SolPcmInfo* info = (SolPcmInfo*) id;
18890 + int err, modified;
18891 + audio_info_t audioInfo;
18893 + TRACE0("> DAUDIO_Start\n");
18895 + AUDIO_INITINFO(&audioInfo);
18896 + err = ioctl(info->fd, AUDIO_GETINFO, &audioInfo);
18897 + if (err >= 0) {
18898 + // unpause
18899 + modified = FALSE;
18900 + if (isSource && audioInfo.play.pause) {
18901 + audioInfo.play.pause = 0;
18902 + modified = TRUE;
18904 + if (!isSource && audioInfo.record.pause) {
18905 + audioInfo.record.pause = 0;
18906 + modified = TRUE;
18908 + if (modified) {
18909 + err = ioctl(info->fd, AUDIO_SETINFO, &audioInfo);
18913 + TRACE1("< DAUDIO_Start %s\n", (err>=0)?"success":"error");
18914 + return (err >= 0)?TRUE:FALSE;
18917 +int DAUDIO_Stop(void* id, int isSource) {
18918 + SolPcmInfo* info = (SolPcmInfo*) id;
18919 + int err, modified;
18920 + audio_info_t audioInfo;
18922 + TRACE0("> DAUDIO_Stop\n");
18924 + AUDIO_INITINFO(&audioInfo);
18925 + err = ioctl(info->fd, AUDIO_GETINFO, &audioInfo);
18926 + if (err >= 0) {
18927 + // pause
18928 + modified = FALSE;
18929 + if (isSource && !audioInfo.play.pause) {
18930 + audioInfo.play.pause = 1;
18931 + modified = TRUE;
18933 + if (!isSource && !audioInfo.record.pause) {
18934 + audioInfo.record.pause = 1;
18935 + modified = TRUE;
18937 + if (modified) {
18938 + err = ioctl(info->fd, AUDIO_SETINFO, &audioInfo);
18942 + TRACE1("< DAUDIO_Stop %s\n", (err>=0)?"success":"error");
18943 + return (err >= 0)?TRUE:FALSE;
18946 +void DAUDIO_Close(void* id, int isSource) {
18947 + SolPcmInfo* info = (SolPcmInfo*) id;
18949 + TRACE0("DAUDIO_Close\n");
18950 + if (info != NULL) {
18951 + if (info->fd >= 0) {
18952 + DAUDIO_Flush(id, isSource);
18953 + close(info->fd);
18955 + free(info);
18959 +#ifndef USE_TRACE
18960 +/* close to 2^31 */
18961 +#define POSITION_MAX 2000000000
18962 +#else
18963 +/* for testing */
18964 +#define POSITION_MAX 1000000
18965 +#endif
18967 +void resetErrorFlagAndAdjustPosition(SolPcmInfo* info, int isSource, int count) {
18968 + audio_info_t audioInfo;
18969 + audio_prinfo_t* prinfo;
18970 + int err;
18971 + int offset = -1;
18972 + int underrun = FALSE;
18973 + int devBytes = 0;
18975 + if (count > 0) {
18976 + info->transferedBytes += count;
18978 + if (isSource) {
18979 + prinfo = &(audioInfo.play);
18980 + } else {
18981 + prinfo = &(audioInfo.record);
18983 + AUDIO_INITINFO(&audioInfo);
18984 + err = ioctl(info->fd, AUDIO_GETINFO, &audioInfo);
18985 + if (err >= 0) {
18986 + underrun = prinfo->error;
18987 + devBytes = prinfo->samples * info->frameSize;
18989 + AUDIO_INITINFO(&audioInfo);
18990 + if (underrun) {
18991 + /* if an underrun occurred, reset */
18992 + ERROR1("DAUDIO_Write/Read: Underrun/overflow: adjusting positionOffset by %d:\n",
18993 + (devBytes - info->transferedBytes));
18994 + ERROR1(" devBytes from %d to 0, ", devBytes);
18995 + ERROR2(" positionOffset from %d to %d ",
18996 + (int) info->positionOffset,
18997 + (int) (info->positionOffset + info->transferedBytes));
18998 + ERROR1(" transferedBytes from %d to 0\n",
18999 + (int) info->transferedBytes);
19000 + prinfo->samples = 0;
19001 + info->positionOffset += info->transferedBytes;
19002 + info->transferedBytes = 0;
19004 + else if (info->transferedBytes > POSITION_MAX) {
19005 + /* we will reset transferedBytes and
19006 + * the samples field in prinfo
19007 + */
19008 + offset = devBytes;
19009 + prinfo->samples = 0;
19011 + /* reset error flag */
19012 + prinfo->error = 0;
19014 + err = ioctl(info->fd, AUDIO_SETINFO, &audioInfo);
19015 + if (err >= 0) {
19016 + if (offset > 0) {
19017 + /* upon exit of AUDIO_SETINFO, the samples parameter
19018 + * was set to the previous value. This is our
19019 + * offset.
19020 + */
19021 + TRACE1("Adjust samplePos: offset=%d, ", (int) offset);
19022 + TRACE2("transferedBytes=%d -> %d, ",
19023 + (int) info->transferedBytes,
19024 + (int) (info->transferedBytes - offset));
19025 + TRACE2("positionOffset=%d -> %d\n",
19026 + (int) (info->positionOffset),
19027 + (int) (((int) info->positionOffset) + offset));
19028 + info->transferedBytes -= offset;
19029 + info->positionOffset += offset;
19031 + } else {
19032 + ERROR0("DAUDIO: resetErrorFlagAndAdjustPosition ioctl failed!\n");
19037 +// returns -1 on error
19038 +int DAUDIO_Write(void* id, char* data, int byteSize) {
19039 + SolPcmInfo* info = (SolPcmInfo*) id;
19040 + int ret = -1;
19042 + TRACE1("> DAUDIO_Write %d bytes\n", byteSize);
19043 + if (info!=NULL) {
19044 + ret = write(info->fd, data, byteSize);
19045 + resetErrorFlagAndAdjustPosition(info, TRUE, ret);
19046 + /* sets ret to -1 if buffer full, no error! */
19047 + if (ret < 0) {
19048 + ret = 0;
19051 + TRACE1("< DAUDIO_Write: returning %d bytes.\n", ret);
19052 + return ret;
19055 +// returns -1 on error
19056 +int DAUDIO_Read(void* id, char* data, int byteSize) {
19057 + SolPcmInfo* info = (SolPcmInfo*) id;
19058 + int ret = -1;
19060 + TRACE1("> DAUDIO_Read %d bytes\n", byteSize);
19061 + if (info != NULL) {
19062 + ret = read(info->fd, data, byteSize);
19063 + resetErrorFlagAndAdjustPosition(info, TRUE, ret);
19064 + /* sets ret to -1 if buffer full, no error! */
19065 + if (ret < 0) {
19066 + ret = 0;
19069 + TRACE1("< DAUDIO_Read: returning %d bytes.\n", ret);
19070 + return ret;
19074 +int DAUDIO_GetBufferSize(void* id, int isSource) {
19075 + SolPcmInfo* info = (SolPcmInfo*) id;
19076 + if (info) {
19077 + return info->bufferSizeInBytes;
19079 + return 0;
19082 +int DAUDIO_StillDraining(void* id, int isSource) {
19083 + SolPcmInfo* info = (SolPcmInfo*) id;
19084 + audio_info_t audioInfo;
19085 + audio_prinfo_t* prinfo;
19086 + int ret = FALSE;
19088 + if (info!=NULL) {
19089 + if (isSource) {
19090 + prinfo = &(audioInfo.play);
19091 + } else {
19092 + prinfo = &(audioInfo.record);
19094 + /* check error flag */
19095 + AUDIO_INITINFO(&audioInfo);
19096 + ioctl(info->fd, AUDIO_GETINFO, &audioInfo);
19097 + ret = (prinfo->error != 0)?FALSE:TRUE;
19099 + return ret;
19103 +int getDevicePosition(SolPcmInfo* info, int isSource) {
19104 + audio_info_t audioInfo;
19105 + audio_prinfo_t* prinfo;
19106 + int err;
19108 + if (isSource) {
19109 + prinfo = &(audioInfo.play);
19110 + } else {
19111 + prinfo = &(audioInfo.record);
19113 + AUDIO_INITINFO(&audioInfo);
19114 + err = ioctl(info->fd, AUDIO_GETINFO, &audioInfo);
19115 + if (err >= 0) {
19116 + /*TRACE2("---> device paused: %d eof=%d\n",
19117 + prinfo->pause, prinfo->eof);
19118 + */
19119 + return (int) (prinfo->samples * info->frameSize);
19121 + ERROR0("DAUDIO: getDevicePosition: ioctl failed!\n");
19122 + return -1;
19125 +int DAUDIO_Flush(void* id, int isSource) {
19126 + SolPcmInfo* info = (SolPcmInfo*) id;
19127 + int err = -1;
19128 + int pos;
19130 + TRACE0("DAUDIO_Flush\n");
19131 + if (info) {
19132 + if (isSource) {
19133 + err = ioctl(info->fd, I_FLUSH, FLUSHW);
19134 + } else {
19135 + err = ioctl(info->fd, I_FLUSH, FLUSHR);
19137 + if (err >= 0) {
19138 + /* resets the transferedBytes parameter to
19139 + * the current samples count of the device
19140 + */
19141 + pos = getDevicePosition(info, isSource);
19142 + if (pos >= 0) {
19143 + info->transferedBytes = pos;
19147 + if (err < 0) {
19148 + ERROR0("ERROR in DAUDIO_Flush\n");
19150 + return (err < 0)?FALSE:TRUE;
19153 +int DAUDIO_GetAvailable(void* id, int isSource) {
19154 + SolPcmInfo* info = (SolPcmInfo*) id;
19155 + int ret = 0;
19156 + int pos;
19158 + if (info) {
19159 + /* unfortunately, the STREAMS architecture
19160 + * seems to not have a method for querying
19161 + * the available bytes to read/write!
19162 + * estimate it...
19163 + */
19164 + pos = getDevicePosition(info, isSource);
19165 + if (pos >= 0) {
19166 + if (isSource) {
19167 + /* we usually have written more bytes
19168 + * to the queue than the device position should be
19169 + */
19170 + ret = (info->bufferSizeInBytes) - (info->transferedBytes - pos);
19171 + } else {
19172 + /* for record, the device stream should
19173 + * be usually ahead of our read actions
19174 + */
19175 + ret = pos - info->transferedBytes;
19177 + if (ret > info->bufferSizeInBytes) {
19178 + ERROR2("DAUDIO_GetAvailable: available=%d, too big at bufferSize=%d!\n",
19179 + (int) ret, (int) info->bufferSizeInBytes);
19180 + ERROR2(" devicePos=%d, transferedBytes=%d\n",
19181 + (int) pos, (int) info->transferedBytes);
19182 + ret = info->bufferSizeInBytes;
19184 + else if (ret < 0) {
19185 + ERROR1("DAUDIO_GetAvailable: available=%d, in theory not possible!\n",
19186 + (int) ret);
19187 + ERROR2(" devicePos=%d, transferedBytes=%d\n",
19188 + (int) pos, (int) info->transferedBytes);
19189 + ret = 0;
19194 + TRACE1("DAUDIO_GetAvailable returns %d bytes\n", ret);
19195 + return ret;
19198 +INT64 DAUDIO_GetBytePosition(void* id, int isSource, INT64 javaBytePos) {
19199 + SolPcmInfo* info = (SolPcmInfo*) id;
19200 + int ret;
19201 + int pos;
19202 + INT64 result = javaBytePos;
19204 + if (info) {
19205 + pos = getDevicePosition(info, isSource);
19206 + if (pos >= 0) {
19207 + result = info->positionOffset + pos;
19211 + //printf("getbyteposition: javaBytePos=%d , return=%d\n", (int) javaBytePos, (int) result);
19212 + return result;
19216 +void DAUDIO_SetBytePosition(void* id, int isSource, INT64 javaBytePos) {
19217 + SolPcmInfo* info = (SolPcmInfo*) id;
19218 + int ret;
19219 + int pos;
19221 + if (info) {
19222 + pos = getDevicePosition(info, isSource);
19223 + if (pos >= 0) {
19224 + info->positionOffset = javaBytePos - pos;
19229 +int DAUDIO_RequiresServicing(void* id, int isSource) {
19230 + // never need servicing on Solaris
19231 + return FALSE;
19234 +void DAUDIO_Service(void* id, int isSource) {
19235 + // never need servicing on Solaris
19239 +#endif // USE_DAUDIO
19240 diff -Nru jdk23u-jdk-23-36.orig/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Ports.c jdk23u-jdk-23-36/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Ports.c
19241 --- jdk23u-jdk-23-36.orig/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Ports.c 1970-01-01 01:00:00.000000000 +0100
19242 +++ jdk23u-jdk-23-36/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Ports.c 2024-08-17 19:50:33.163701688 +0200
19243 @@ -0,0 +1,600 @@
19245 + * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
19246 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
19248 + * This code is free software; you can redistribute it and/or modify it
19249 + * under the terms of the GNU General Public License version 2 only, as
19250 + * published by the Free Software Foundation. Oracle designates this
19251 + * particular file as subject to the "Classpath" exception as provided
19252 + * by Oracle in the LICENSE file that accompanied this code.
19254 + * This code is distributed in the hope that it will be useful, but WITHOUT
19255 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19256 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19257 + * version 2 for more details (a copy is included in the LICENSE file that
19258 + * accompanied this code).
19260 + * You should have received a copy of the GNU General Public License version
19261 + * 2 along with this work; if not, write to the Free Software Foundation,
19262 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19264 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19265 + * or visit www.oracle.com if you need additional information or have any
19266 + * questions.
19267 + */
19269 +#define USE_ERROR
19270 +//#define USE_TRACE
19272 +#include "Ports.h"
19273 +#include "PLATFORM_API_SolarisOS_Utils.h"
19275 +#if USE_PORTS == TRUE
19277 +#define MONITOR_GAIN_STRING "Monitor Gain"
19279 +#define ALL_TARGET_PORT_COUNT 6
19281 +// define the following to not use audio_prinfo_t.mod_ports
19282 +#define SOLARIS7_COMPATIBLE
19284 +// Solaris audio defines
19285 +static int targetPorts[ALL_TARGET_PORT_COUNT] = {
19286 + AUDIO_SPEAKER,
19287 + AUDIO_HEADPHONE,
19288 + AUDIO_LINE_OUT,
19289 + AUDIO_AUX1_OUT,
19290 + AUDIO_AUX2_OUT,
19291 + AUDIO_SPDIF_OUT
19294 +static char* targetPortNames[ALL_TARGET_PORT_COUNT] = {
19295 + "Speaker",
19296 + "Headphone",
19297 + "Line Out",
19298 + "AUX1 Out",
19299 + "AUX2 Out",
19300 + "SPDIF Out"
19303 +// defined in Ports.h
19304 +static int targetPortJavaSoundMapping[ALL_TARGET_PORT_COUNT] = {
19305 + PORT_DST_SPEAKER,
19306 + PORT_DST_HEADPHONE,
19307 + PORT_DST_LINE_OUT,
19308 + PORT_DST_UNKNOWN,
19309 + PORT_DST_UNKNOWN,
19310 + PORT_DST_UNKNOWN,
19313 +#define ALL_SOURCE_PORT_COUNT 7
19315 +// Solaris audio defines
19316 +static int sourcePorts[ALL_SOURCE_PORT_COUNT] = {
19317 + AUDIO_MICROPHONE,
19318 + AUDIO_LINE_IN,
19319 + AUDIO_CD,
19320 + AUDIO_AUX1_IN,
19321 + AUDIO_AUX2_IN,
19322 + AUDIO_SPDIF_IN,
19323 + AUDIO_CODEC_LOOPB_IN
19326 +static char* sourcePortNames[ALL_SOURCE_PORT_COUNT] = {
19327 + "Microphone In",
19328 + "Line In",
19329 + "Compact Disc In",
19330 + "AUX1 In",
19331 + "AUX2 In",
19332 + "SPDIF In",
19333 + "Internal Loopback"
19336 +// Ports.h defines
19337 +static int sourcePortJavaSoundMapping[ALL_SOURCE_PORT_COUNT] = {
19338 + PORT_SRC_MICROPHONE,
19339 + PORT_SRC_LINE_IN,
19340 + PORT_SRC_COMPACT_DISC,
19341 + PORT_SRC_UNKNOWN,
19342 + PORT_SRC_UNKNOWN,
19343 + PORT_SRC_UNKNOWN,
19344 + PORT_SRC_UNKNOWN
19347 +struct tag_PortControlID;
19349 +typedef struct tag_PortInfo {
19350 + int fd; // file descriptor of the pseudo device
19351 + audio_info_t audioInfo;
19352 + // ports
19353 + int targetPortCount;
19354 + int sourcePortCount;
19355 + // indexes to sourcePorts/targetPorts
19356 + // contains first target ports, then source ports
19357 + int ports[ALL_TARGET_PORT_COUNT + ALL_SOURCE_PORT_COUNT];
19358 + // controls
19359 + int maxControlCount; // upper bound of number of controls
19360 + int usedControlIDs; // number of items already filled in controlIDs
19361 + struct tag_PortControlID* controlIDs; // the control IDs themselves
19362 +} PortInfo;
19364 +#define PORT_CONTROL_TYPE_PLAY 0x4000000
19365 +#define PORT_CONTROL_TYPE_RECORD 0x8000000
19366 +#define PORT_CONTROL_TYPE_SELECT_PORT 1
19367 +#define PORT_CONTROL_TYPE_GAIN 2
19368 +#define PORT_CONTROL_TYPE_BALANCE 3
19369 +#define PORT_CONTROL_TYPE_MONITOR_GAIN 10
19370 +#define PORT_CONTROL_TYPE_OUTPUT_MUTED 11
19371 +#define PORT_CONTROL_TYPE_PLAYRECORD_MASK PORT_CONTROL_TYPE_PLAY | PORT_CONTROL_TYPE_RECORD
19372 +#define PORT_CONTROL_TYPE_MASK 0xFFFFFF
19375 +typedef struct tag_PortControlID {
19376 + PortInfo* portInfo;
19377 + INT32 controlType; // PORT_CONTROL_TYPE_XX
19378 + uint_t port;
19379 +} PortControlID;
19382 +///// implemented functions of Ports.h
19384 +INT32 PORT_GetPortMixerCount() {
19385 + return (INT32) getAudioDeviceCount();
19389 +INT32 PORT_GetPortMixerDescription(INT32 mixerIndex, PortMixerDescription* description) {
19390 + AudioDeviceDescription desc;
19392 + if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, TRUE)) {
19393 + strncpy(description->name, desc.name, PORT_STRING_LENGTH-1);
19394 + description->name[PORT_STRING_LENGTH-1] = 0;
19395 + strncpy(description->vendor, desc.vendor, PORT_STRING_LENGTH-1);
19396 + description->vendor[PORT_STRING_LENGTH-1] = 0;
19397 + strncpy(description->version, desc.version, PORT_STRING_LENGTH-1);
19398 + description->version[PORT_STRING_LENGTH-1] = 0;
19399 + /*strncpy(description->description, desc.description, PORT_STRING_LENGTH-1);*/
19400 + strncpy(description->description, "Solaris Ports", PORT_STRING_LENGTH-1);
19401 + description->description[PORT_STRING_LENGTH-1] = 0;
19402 + return TRUE;
19404 + return FALSE;
19408 +void* PORT_Open(INT32 mixerIndex) {
19409 + PortInfo* info = NULL;
19410 + int fd = -1;
19411 + AudioDeviceDescription desc;
19412 + int success = FALSE;
19414 + TRACE0("PORT_Open\n");
19415 + if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, FALSE)) {
19416 + fd = open(desc.pathctl, O_RDWR);
19418 + if (fd < 0) {
19419 + ERROR1("Couldn't open audio device ctl for device %d!\n", mixerIndex);
19420 + return NULL;
19423 + info = (PortInfo*) malloc(sizeof(PortInfo));
19424 + if (info != NULL) {
19425 + memset(info, 0, sizeof(PortInfo));
19426 + info->fd = fd;
19427 + success = TRUE;
19429 + if (!success) {
19430 + if (fd >= 0) {
19431 + close(fd);
19433 + PORT_Close((void*) info);
19434 + info = NULL;
19436 + return info;
19439 +void PORT_Close(void* id) {
19440 + TRACE0("PORT_Close\n");
19441 + if (id != NULL) {
19442 + PortInfo* info = (PortInfo*) id;
19443 + if (info->fd >= 0) {
19444 + close(info->fd);
19445 + info->fd = -1;
19447 + if (info->controlIDs) {
19448 + free(info->controlIDs);
19449 + info->controlIDs = NULL;
19451 + free(info);
19457 +INT32 PORT_GetPortCount(void* id) {
19458 + int ret = 0;
19459 + PortInfo* info = (PortInfo*) id;
19460 + if (info != NULL) {
19461 + if (!info->targetPortCount && !info->sourcePortCount) {
19462 + int i;
19463 + AUDIO_INITINFO(&info->audioInfo);
19464 + if (ioctl(info->fd, AUDIO_GETINFO, &info->audioInfo) >= 0) {
19465 + for (i = 0; i < ALL_TARGET_PORT_COUNT; i++) {
19466 + if (info->audioInfo.play.avail_ports & targetPorts[i]) {
19467 + info->ports[info->targetPortCount] = i;
19468 + info->targetPortCount++;
19470 +#ifdef SOLARIS7_COMPATIBLE
19471 + TRACE3("Target %d %s: avail=%d\n", i, targetPortNames[i],
19472 + info->audioInfo.play.avail_ports & targetPorts[i]);
19473 +#else
19474 + TRACE4("Target %d %s: avail=%d mod=%d\n", i, targetPortNames[i],
19475 + info->audioInfo.play.avail_ports & targetPorts[i],
19476 + info->audioInfo.play.mod_ports & targetPorts[i]);
19477 +#endif
19479 + for (i = 0; i < ALL_SOURCE_PORT_COUNT; i++) {
19480 + if (info->audioInfo.record.avail_ports & sourcePorts[i]) {
19481 + info->ports[info->targetPortCount + info->sourcePortCount] = i;
19482 + info->sourcePortCount++;
19484 +#ifdef SOLARIS7_COMPATIBLE
19485 + TRACE3("Source %d %s: avail=%d\n", i, sourcePortNames[i],
19486 + info->audioInfo.record.avail_ports & sourcePorts[i]);
19487 +#else
19488 + TRACE4("Source %d %s: avail=%d mod=%d\n", i, sourcePortNames[i],
19489 + info->audioInfo.record.avail_ports & sourcePorts[i],
19490 + info->audioInfo.record.mod_ports & sourcePorts[i]);
19491 +#endif
19495 + ret = info->targetPortCount + info->sourcePortCount;
19497 + return ret;
19500 +int isSourcePort(PortInfo* info, INT32 portIndex) {
19501 + return (portIndex >= info->targetPortCount);
19504 +INT32 PORT_GetPortType(void* id, INT32 portIndex) {
19505 + PortInfo* info = (PortInfo*) id;
19506 + if ((portIndex >= 0) && (portIndex < PORT_GetPortCount(id))) {
19507 + if (isSourcePort(info, portIndex)) {
19508 + return sourcePortJavaSoundMapping[info->ports[portIndex]];
19509 + } else {
19510 + return targetPortJavaSoundMapping[info->ports[portIndex]];
19513 + return 0;
19516 +// pre-condition: portIndex must have been verified!
19517 +char* getPortName(PortInfo* info, INT32 portIndex) {
19518 + char* ret = NULL;
19520 + if (isSourcePort(info, portIndex)) {
19521 + ret = sourcePortNames[info->ports[portIndex]];
19522 + } else {
19523 + ret = targetPortNames[info->ports[portIndex]];
19525 + return ret;
19528 +INT32 PORT_GetPortName(void* id, INT32 portIndex, char* name, INT32 len) {
19529 + PortInfo* info = (PortInfo*) id;
19530 + char* n;
19532 + if ((portIndex >= 0) && (portIndex < PORT_GetPortCount(id))) {
19533 + n = getPortName(info, portIndex);
19534 + if (n) {
19535 + strncpy(name, n, len-1);
19536 + name[len-1] = 0;
19537 + return TRUE;
19540 + return FALSE;
19543 +void createPortControl(PortInfo* info, PortControlCreator* creator, INT32 portIndex,
19544 + INT32 type, void** controlObjects, int* controlCount) {
19545 + PortControlID* controlID;
19546 + void* newControl = NULL;
19547 + int controlIndex;
19548 + char* jsType = NULL;
19549 + int isBoolean = FALSE;
19551 + TRACE0(">createPortControl\n");
19553 + // fill the ControlID structure and add this control
19554 + if (info->usedControlIDs >= info->maxControlCount) {
19555 + ERROR1("not enough free controlIDs !! maxControlIDs = %d\n", info->maxControlCount);
19556 + return;
19558 + controlID = &(info->controlIDs[info->usedControlIDs]);
19559 + controlID->portInfo = info;
19560 + controlID->controlType = type;
19561 + controlIndex = info->ports[portIndex];
19562 + if (isSourcePort(info, portIndex)) {
19563 + controlID->port = sourcePorts[controlIndex];
19564 + } else {
19565 + controlID->port = targetPorts[controlIndex];
19567 + switch (type & PORT_CONTROL_TYPE_MASK) {
19568 + case PORT_CONTROL_TYPE_SELECT_PORT:
19569 + jsType = CONTROL_TYPE_SELECT; isBoolean = TRUE; break;
19570 + case PORT_CONTROL_TYPE_GAIN:
19571 + jsType = CONTROL_TYPE_VOLUME; break;
19572 + case PORT_CONTROL_TYPE_BALANCE:
19573 + jsType = CONTROL_TYPE_BALANCE; break;
19574 + case PORT_CONTROL_TYPE_MONITOR_GAIN:
19575 + jsType = CONTROL_TYPE_VOLUME; break;
19576 + case PORT_CONTROL_TYPE_OUTPUT_MUTED:
19577 + jsType = CONTROL_TYPE_MUTE; isBoolean = TRUE; break;
19579 + if (isBoolean) {
19580 + TRACE0(" PORT_CONTROL_TYPE_BOOLEAN\n");
19581 + newControl = (creator->newBooleanControl)(creator, controlID, jsType);
19583 + else if (jsType == CONTROL_TYPE_BALANCE) {
19584 + TRACE0(" PORT_CONTROL_TYPE_BALANCE\n");
19585 + newControl = (creator->newFloatControl)(creator, controlID, jsType,
19586 + -1.0f, 1.0f, 2.0f / 65.0f, "");
19587 + } else {
19588 + TRACE0(" PORT_CONTROL_TYPE_FLOAT\n");
19589 + newControl = (creator->newFloatControl)(creator, controlID, jsType,
19590 + 0.0f, 1.0f, 1.0f / 256.0f, "");
19592 + if (newControl) {
19593 + controlObjects[*controlCount] = newControl;
19594 + (*controlCount)++;
19595 + info->usedControlIDs++;
19597 + TRACE0("<createPortControl\n");
19601 +void addCompoundControl(PortInfo* info, PortControlCreator* creator, char* name, void** controlObjects, int* controlCount) {
19602 + void* compControl;
19604 + TRACE1(">addCompoundControl %d controls\n", *controlCount);
19605 + if (*controlCount) {
19606 + // create compound control and add it to the vector
19607 + compControl = (creator->newCompoundControl)(creator, name, controlObjects, *controlCount);
19608 + if (compControl) {
19609 + TRACE1(" addCompoundControl: calling addControl %p\n", compControl);
19610 + (creator->addControl)(creator, compControl);
19612 + *controlCount = 0;
19614 + TRACE0("<addCompoundControl\n");
19617 +void addAllControls(PortInfo* info, PortControlCreator* creator, void** controlObjects, int* controlCount) {
19618 + int i = 0;
19620 + TRACE0(">addAllControl\n");
19621 + // go through all controls and add them to the vector
19622 + for (i = 0; i < *controlCount; i++) {
19623 + (creator->addControl)(creator, controlObjects[i]);
19625 + *controlCount = 0;
19626 + TRACE0("<addAllControl\n");
19629 +void PORT_GetControls(void* id, INT32 portIndex, PortControlCreator* creator) {
19630 + PortInfo* info = (PortInfo*) id;
19631 + int portCount = PORT_GetPortCount(id);
19632 + void* controls[4];
19633 + int controlCount = 0;
19634 + INT32 type;
19635 + int selectable = 1;
19636 + memset(controls, 0, sizeof(controls));
19638 + TRACE4(">PORT_GetControls(id=%p, portIndex=%d). controlIDs=%p, maxControlCount=%d\n",
19639 + id, portIndex, info->controlIDs, info->maxControlCount);
19640 + if ((portIndex >= 0) && (portIndex < portCount)) {
19641 + // if the memory isn't reserved for the control structures, allocate it
19642 + if (!info->controlIDs) {
19643 + int maxCount = 0;
19644 + TRACE0("getControl: allocate mem\n");
19645 + // get a maximum number of controls:
19646 + // each port has a select, balance, and volume control.
19647 + maxCount = 3 * portCount;
19648 + // then there is monitorGain and outputMuted
19649 + maxCount += (2 * info->targetPortCount);
19650 + info->maxControlCount = maxCount;
19651 + info->controlIDs = (PortControlID*) malloc(sizeof(PortControlID) * maxCount);
19653 + if (!isSourcePort(info, portIndex)) {
19654 + type = PORT_CONTROL_TYPE_PLAY;
19655 + // add master mute control
19656 + createPortControl(info, creator, portIndex,
19657 + type | PORT_CONTROL_TYPE_OUTPUT_MUTED,
19658 + controls, &controlCount);
19659 + addAllControls(info, creator, controls, &controlCount);
19660 +#ifdef SOLARIS7_COMPATIBLE
19661 + selectable = info->audioInfo.play.avail_ports & targetPorts[info->ports[portIndex]];
19662 +#else
19663 + selectable = info->audioInfo.play.mod_ports & targetPorts[info->ports[portIndex]];
19664 +#endif
19665 + } else {
19666 + type = PORT_CONTROL_TYPE_RECORD;
19667 +#ifdef SOLARIS7_COMPATIBLE
19668 + selectable = info->audioInfo.record.avail_ports & sourcePorts[info->ports[portIndex]];
19669 +#else
19670 + selectable = info->audioInfo.record.mod_ports & sourcePorts[info->ports[portIndex]];
19671 +#endif
19673 + // add a mixer strip with volume, ...
19674 + createPortControl(info, creator, portIndex,
19675 + type | PORT_CONTROL_TYPE_GAIN,
19676 + controls, &controlCount);
19677 + // ... balance, ...
19678 + createPortControl(info, creator, portIndex,
19679 + type | PORT_CONTROL_TYPE_BALANCE,
19680 + controls, &controlCount);
19681 + // ... and select control (if not always on)...
19682 + if (selectable) {
19683 + createPortControl(info, creator, portIndex,
19684 + type | PORT_CONTROL_TYPE_SELECT_PORT,
19685 + controls, &controlCount);
19687 + // ... packaged in a compound control.
19688 + addCompoundControl(info, creator, getPortName(info, portIndex), controls, &controlCount);
19690 + if (type == PORT_CONTROL_TYPE_PLAY) {
19691 + // add a single strip for source ports with monitor gain
19692 + createPortControl(info, creator, portIndex,
19693 + type | PORT_CONTROL_TYPE_MONITOR_GAIN,
19694 + controls, &controlCount);
19695 + // also in a compound control
19696 + addCompoundControl(info, creator, MONITOR_GAIN_STRING, controls, &controlCount);
19699 + TRACE0("< PORT_getControls\n");
19702 +INT32 PORT_GetIntValue(void* controlIDV) {
19703 + PortControlID* controlID = (PortControlID*) controlIDV;
19704 + audio_info_t audioInfo;
19705 + audio_prinfo_t* prinfo;
19707 + AUDIO_INITINFO(&audioInfo);
19708 + if (ioctl(controlID->portInfo->fd, AUDIO_GETINFO, &audioInfo) >= 0) {
19709 + if (controlID->controlType & PORT_CONTROL_TYPE_PLAY) {
19710 + prinfo = &(audioInfo.play);
19711 + } else {
19712 + prinfo = &(audioInfo.record);
19714 + switch (controlID->controlType & PORT_CONTROL_TYPE_MASK) {
19715 + case PORT_CONTROL_TYPE_SELECT_PORT:
19716 + return (prinfo->port & controlID->port)?TRUE:FALSE;
19717 + case PORT_CONTROL_TYPE_OUTPUT_MUTED:
19718 + return (audioInfo.output_muted)?TRUE:FALSE;
19719 + default:
19720 + ERROR1("PORT_GetIntValue: Wrong type %d !\n", controlID->controlType & PORT_CONTROL_TYPE_MASK);
19723 + ERROR0("PORT_GetIntValue: Could not ioctl!\n");
19724 + return 0;
19727 +void PORT_SetIntValue(void* controlIDV, INT32 value) {
19728 + PortControlID* controlID = (PortControlID*) controlIDV;
19729 + audio_info_t audioInfo;
19730 + audio_prinfo_t* prinfo;
19731 + int setPort;
19733 + if (controlID->controlType & PORT_CONTROL_TYPE_PLAY) {
19734 + prinfo = &(audioInfo.play);
19735 + } else {
19736 + prinfo = &(audioInfo.record);
19738 + switch (controlID->controlType & PORT_CONTROL_TYPE_MASK) {
19739 + case PORT_CONTROL_TYPE_SELECT_PORT:
19740 + // first try to just add this port. if that fails, set ONLY to this port.
19741 + AUDIO_INITINFO(&audioInfo);
19742 + if (ioctl(controlID->portInfo->fd, AUDIO_GETINFO, &audioInfo) >= 0) {
19743 + if (value) {
19744 + setPort = (prinfo->port | controlID->port);
19745 + } else {
19746 + setPort = (prinfo->port - controlID->port);
19748 + AUDIO_INITINFO(&audioInfo);
19749 + prinfo->port = setPort;
19750 + if (ioctl(controlID->portInfo->fd, AUDIO_SETINFO, &audioInfo) < 0) {
19751 + // didn't work. Either this line doesn't support to select several
19752 + // ports at once (e.g. record), or a real error
19753 + if (value) {
19754 + // set to ONLY this port (and disable any other currently selected ports)
19755 + AUDIO_INITINFO(&audioInfo);
19756 + prinfo->port = controlID->port;
19757 + if (ioctl(controlID->portInfo->fd, AUDIO_SETINFO, &audioInfo) < 0) {
19758 + ERROR2("Error setting output select port %d to port %d!\n", controlID->port, controlID->port);
19760 + } else {
19761 + // assume it's an error
19762 + ERROR2("Error setting output select port %d to port %d!\n", controlID->port, setPort);
19765 + break;
19766 + case PORT_CONTROL_TYPE_OUTPUT_MUTED:
19767 + AUDIO_INITINFO(&audioInfo);
19768 + audioInfo.output_muted = (value?TRUE:FALSE);
19769 + if (ioctl(controlID->portInfo->fd, AUDIO_SETINFO, &audioInfo) < 0) {
19770 + ERROR2("Error setting output muted on port %d to %d!\n", controlID->port, value);
19772 + break;
19773 + default:
19774 + ERROR1("PORT_SetIntValue: Wrong type %d !\n", controlID->controlType & PORT_CONTROL_TYPE_MASK);
19779 +float PORT_GetFloatValue(void* controlIDV) {
19780 + PortControlID* controlID = (PortControlID*) controlIDV;
19781 + audio_info_t audioInfo;
19782 + audio_prinfo_t* prinfo;
19784 + AUDIO_INITINFO(&audioInfo);
19785 + if (ioctl(controlID->portInfo->fd, AUDIO_GETINFO, &audioInfo) >= 0) {
19786 + if (controlID->controlType & PORT_CONTROL_TYPE_PLAY) {
19787 + prinfo = &(audioInfo.play);
19788 + } else {
19789 + prinfo = &(audioInfo.record);
19791 + switch (controlID->controlType & PORT_CONTROL_TYPE_MASK) {
19792 + case PORT_CONTROL_TYPE_GAIN:
19793 + return ((float) (prinfo->gain - AUDIO_MIN_GAIN))
19794 + / ((float) (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN));
19795 + case PORT_CONTROL_TYPE_BALANCE:
19796 + return ((float) ((prinfo->balance - AUDIO_LEFT_BALANCE - AUDIO_MID_BALANCE) << 1))
19797 + / ((float) (AUDIO_RIGHT_BALANCE - AUDIO_LEFT_BALANCE));
19798 + case PORT_CONTROL_TYPE_MONITOR_GAIN:
19799 + return ((float) (audioInfo.monitor_gain - AUDIO_MIN_GAIN))
19800 + / ((float) (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN));
19801 + default:
19802 + ERROR1("PORT_GetFloatValue: Wrong type %d !\n", controlID->controlType & PORT_CONTROL_TYPE_MASK);
19805 + ERROR0("PORT_GetFloatValue: Could not ioctl!\n");
19806 + return 0.0f;
19809 +void PORT_SetFloatValue(void* controlIDV, float value) {
19810 + PortControlID* controlID = (PortControlID*) controlIDV;
19811 + audio_info_t audioInfo;
19812 + audio_prinfo_t* prinfo;
19814 + AUDIO_INITINFO(&audioInfo);
19816 + if (controlID->controlType & PORT_CONTROL_TYPE_PLAY) {
19817 + prinfo = &(audioInfo.play);
19818 + } else {
19819 + prinfo = &(audioInfo.record);
19821 + switch (controlID->controlType & PORT_CONTROL_TYPE_MASK) {
19822 + case PORT_CONTROL_TYPE_GAIN:
19823 + prinfo->gain = AUDIO_MIN_GAIN
19824 + + (int) ((value * ((float) (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN))) + 0.5f);
19825 + break;
19826 + case PORT_CONTROL_TYPE_BALANCE:
19827 + prinfo->balance = AUDIO_LEFT_BALANCE + AUDIO_MID_BALANCE
19828 + + ((int) (value * ((float) ((AUDIO_RIGHT_BALANCE - AUDIO_LEFT_BALANCE) >> 1))) + 0.5f);
19829 + break;
19830 + case PORT_CONTROL_TYPE_MONITOR_GAIN:
19831 + audioInfo.monitor_gain = AUDIO_MIN_GAIN
19832 + + (int) ((value * ((float) (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN))) + 0.5f);
19833 + break;
19834 + default:
19835 + ERROR1("PORT_SetFloatValue: Wrong type %d !\n", controlID->controlType & PORT_CONTROL_TYPE_MASK);
19836 + return;
19838 + if (ioctl(controlID->portInfo->fd, AUDIO_SETINFO, &audioInfo) < 0) {
19839 + ERROR0("PORT_SetFloatValue: Could not ioctl!\n");
19843 +#endif // USE_PORTS
19844 diff -Nru jdk23u-jdk-23-36.orig/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Utils.c jdk23u-jdk-23-36/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Utils.c
19845 --- jdk23u-jdk-23-36.orig/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Utils.c 1970-01-01 01:00:00.000000000 +0100
19846 +++ jdk23u-jdk-23-36/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Utils.c 2024-08-17 19:50:33.164009118 +0200
19847 @@ -0,0 +1,193 @@
19849 + * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
19850 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
19852 + * This code is free software; you can redistribute it and/or modify it
19853 + * under the terms of the GNU General Public License version 2 only, as
19854 + * published by the Free Software Foundation. Oracle designates this
19855 + * particular file as subject to the "Classpath" exception as provided
19856 + * by Oracle in the LICENSE file that accompanied this code.
19858 + * This code is distributed in the hope that it will be useful, but WITHOUT
19859 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19860 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19861 + * version 2 for more details (a copy is included in the LICENSE file that
19862 + * accompanied this code).
19864 + * You should have received a copy of the GNU General Public License version
19865 + * 2 along with this work; if not, write to the Free Software Foundation,
19866 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19868 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19869 + * or visit www.oracle.com if you need additional information or have any
19870 + * questions.
19871 + */
19873 +#define USE_ERROR
19874 +#define USE_TRACE
19876 +#include "PLATFORM_API_SolarisOS_Utils.h"
19878 +#define MAX_AUDIO_DEVICES 20
19880 +// not thread safe...
19881 +static AudioDevicePath globalADPaths[MAX_AUDIO_DEVICES];
19882 +static int globalADCount = -1;
19883 +static int globalADCacheTime = -1;
19884 +/* how many seconds do we cache devices */
19885 +#define AD_CACHE_TIME 30
19887 +// return seconds
19888 +long getTimeInSeconds() {
19889 + struct timeval tv;
19890 + gettimeofday(&tv, NULL);
19891 + return tv.tv_sec;
19895 +int getAudioDeviceCount() {
19896 + int count = MAX_AUDIO_DEVICES;
19898 + getAudioDevices(globalADPaths, &count);
19899 + return count;
19902 +/* returns TRUE if the path exists at all */
19903 +int addAudioDevice(char* path, AudioDevicePath* adPath, int* count) {
19904 + int i;
19905 + int found = 0;
19906 + int fileExists = 0;
19907 + // not thread safe...
19908 + static struct stat statBuf;
19910 + // get stats on the file
19911 + if (stat(path, &statBuf) == 0) {
19912 + // file exists.
19913 + fileExists = 1;
19914 + // If it is not yet in the adPath array, add it to the array
19915 + for (i = 0; i < *count; i++) {
19916 + if (adPath[i].st_ino == statBuf.st_ino
19917 + && adPath[i].st_dev == statBuf.st_dev) {
19918 + found = 1;
19919 + break;
19922 + if (!found) {
19923 + adPath[*count].st_ino = statBuf.st_ino;
19924 + adPath[*count].st_dev = statBuf.st_dev;
19925 + strncpy(adPath[*count].path, path, MAX_NAME_LENGTH);
19926 + adPath[*count].path[MAX_NAME_LENGTH - 1] = 0;
19927 + (*count)++;
19928 + TRACE1("Added audio device %s\n", path);
19931 + return fileExists;
19935 +void getAudioDevices(AudioDevicePath* adPath, int* count) {
19936 + int maxCount = *count;
19937 + char* audiodev;
19938 + char devsound[15];
19939 + int i;
19940 + long timeInSeconds = getTimeInSeconds();
19942 + if (globalADCount < 0
19943 + || (getTimeInSeconds() - globalADCacheTime) > AD_CACHE_TIME
19944 + || (adPath != globalADPaths)) {
19945 + *count = 0;
19946 + // first device, if set, is AUDIODEV variable
19947 + audiodev = getenv("AUDIODEV");
19948 + if (audiodev != NULL && audiodev[0] != 0) {
19949 + addAudioDevice(audiodev, adPath, count);
19951 + // then try /dev/audio
19952 + addAudioDevice("/dev/audio", adPath, count);
19953 + // then go through all of the /dev/sound/? devices
19954 + for (i = 0; i < 100; i++) {
19955 + sprintf(devsound, "/dev/sound/%d", i);
19956 + if (!addAudioDevice(devsound, adPath, count)) {
19957 + break;
19960 + if (adPath == globalADPaths) {
19961 + /* commit cache */
19962 + globalADCount = *count;
19963 + /* set cache time */
19964 + globalADCacheTime = timeInSeconds;
19966 + } else {
19967 + /* return cache */
19968 + *count = globalADCount;
19970 + // that's it
19973 +int getAudioDeviceDescriptionByIndex(int index, AudioDeviceDescription* adDesc, int getNames) {
19974 + int count = MAX_AUDIO_DEVICES;
19975 + int ret = 0;
19977 + getAudioDevices(globalADPaths, &count);
19978 + if (index>=0 && index < count) {
19979 + ret = getAudioDeviceDescription(globalADPaths[index].path, adDesc, getNames);
19981 + return ret;
19984 +int getAudioDeviceDescription(char* path, AudioDeviceDescription* adDesc, int getNames) {
19985 + int fd;
19986 + int mixerMode;
19987 + int len;
19988 + audio_info_t info;
19989 + audio_device_t deviceInfo;
19991 + strncpy(adDesc->path, path, MAX_NAME_LENGTH);
19992 + adDesc->path[MAX_NAME_LENGTH] = 0;
19993 + strcpy(adDesc->pathctl, adDesc->path);
19994 + strcat(adDesc->pathctl, "ctl");
19995 + strcpy(adDesc->name, adDesc->path);
19996 + adDesc->vendor[0] = 0;
19997 + adDesc->version[0] = 0;
19998 + adDesc->description[0] = 0;
19999 + adDesc->maxSimulLines = 1;
20001 + // try to open the pseudo device and get more information
20002 + fd = open(adDesc->pathctl, O_WRONLY | O_NONBLOCK);
20003 + if (fd >= 0) {
20004 + close(fd);
20005 + if (getNames) {
20006 + fd = open(adDesc->pathctl, O_RDONLY);
20007 + if (fd >= 0) {
20008 + if (ioctl(fd, AUDIO_GETDEV, &deviceInfo) >= 0) {
20009 + strncpy(adDesc->vendor, deviceInfo.name, MAX_AUDIO_DEV_LEN);
20010 + adDesc->vendor[MAX_AUDIO_DEV_LEN] = 0;
20011 + strncpy(adDesc->version, deviceInfo.version, MAX_AUDIO_DEV_LEN);
20012 + adDesc->version[MAX_AUDIO_DEV_LEN] = 0;
20013 + /* add config string to the dev name
20014 + * creates a string like "/dev/audio (onboard1)"
20015 + */
20016 + len = strlen(adDesc->name) + 1;
20017 + if (MAX_NAME_LENGTH - len > 3) {
20018 + strcat(adDesc->name, " (");
20019 + strncat(adDesc->name, deviceInfo.config, MAX_NAME_LENGTH - len);
20020 + strcat(adDesc->name, ")");
20022 + adDesc->name[MAX_NAME_LENGTH-1] = 0;
20024 + if (ioctl(fd, AUDIO_MIXERCTL_GET_MODE, &mixerMode) >= 0) {
20025 + if (mixerMode == AM_MIXER_MODE) {
20026 + TRACE1(" getAudioDeviceDescription: %s is in mixer mode\n", adDesc->path);
20027 + adDesc->maxSimulLines = -1;
20029 + } else {
20030 + ERROR1("ioctl AUDIO_MIXERCTL_GET_MODE failed on %s!\n", adDesc->path);
20032 + close(fd);
20033 + } else {
20034 + ERROR1("could not open %s!\n", adDesc->pathctl);
20037 + return 1;
20039 + return 0;
20041 diff -Nru jdk23u-jdk-23-36.orig/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Utils.h jdk23u-jdk-23-36/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Utils.h
20042 --- jdk23u-jdk-23-36.orig/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Utils.h 1970-01-01 01:00:00.000000000 +0100
20043 +++ jdk23u-jdk-23-36/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Utils.h 2024-08-17 19:50:33.164271032 +0200
20044 @@ -0,0 +1,97 @@
20046 + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
20047 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
20049 + * This code is free software; you can redistribute it and/or modify it
20050 + * under the terms of the GNU General Public License version 2 only, as
20051 + * published by the Free Software Foundation. Oracle designates this
20052 + * particular file as subject to the "Classpath" exception as provided
20053 + * by Oracle in the LICENSE file that accompanied this code.
20055 + * This code is distributed in the hope that it will be useful, but WITHOUT
20056 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20057 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20058 + * version 2 for more details (a copy is included in the LICENSE file that
20059 + * accompanied this code).
20061 + * You should have received a copy of the GNU General Public License version
20062 + * 2 along with this work; if not, write to the Free Software Foundation,
20063 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20065 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20066 + * or visit www.oracle.com if you need additional information or have any
20067 + * questions.
20068 + */
20070 +#include <Utilities.h>
20071 +#include <string.h>
20072 +#include <stdlib.h>
20073 +#include <fcntl.h>
20074 +/* does not work on Solaris 2.7 */
20075 +#include <sys/audio.h>
20076 +#include <sys/mixer.h>
20077 +#include <sys/types.h>
20078 +#ifndef __linux__
20079 +#include <stropts.h>
20080 +#endif
20081 +#include <sys/conf.h>
20082 +#include <sys/stat.h>
20083 +#include <unistd.h>
20085 +#ifndef PLATFORM_API_SOLARISOS_UTILS_H_INCLUDED
20086 +#define PLATFORM_API_SOLARISOS_UTILS_H_INCLUDED
20088 +/* defines for Solaris 2.7
20089 + #ifndef AUDIO_AUX1_OUT
20090 + #define AUDIO_AUX1_OUT (0x08) // output to aux1 out
20091 + #define AUDIO_AUX2_OUT (0x10) // output to aux2 out
20092 + #define AUDIO_SPDIF_OUT (0x20) // output to SPDIF port
20093 + #define AUDIO_AUX1_IN (0x08) // input from aux1 in
20094 + #define AUDIO_AUX2_IN (0x10) // input from aux2 in
20095 + #define AUDIO_SPDIF_IN (0x20) // input from SPDIF port
20096 + #endif
20099 +/* input from Codec inter. loopback */
20100 +#ifndef AUDIO_CODEC_LOOPB_IN
20101 +#define AUDIO_CODEC_LOOPB_IN (0x40)
20102 +#endif
20105 +#define MAX_NAME_LENGTH 300
20107 +typedef struct tag_AudioDevicePath {
20108 + char path[MAX_NAME_LENGTH];
20109 + ino_t st_ino; // inode number to detect duplicate devices
20110 + dev_t st_dev; // device ID to detect duplicate audio devices
20111 +} AudioDevicePath;
20113 +typedef struct tag_AudioDeviceDescription {
20114 + INT32 maxSimulLines;
20115 + char path[MAX_NAME_LENGTH+1];
20116 + char pathctl[MAX_NAME_LENGTH+4];
20117 + char name[MAX_NAME_LENGTH+1];
20118 + char vendor[MAX_NAME_LENGTH+1];
20119 + char version[MAX_NAME_LENGTH+1];
20120 + char description[MAX_NAME_LENGTH+1];
20121 +} AudioDeviceDescription;
20123 +int getAudioDeviceCount();
20126 + * adPath is an array of AudioDevicePath structures
20127 + * count contains initially the number of elements in adPath
20128 + * and will be set to the returned number of paths.
20129 + */
20130 +void getAudioDevices(AudioDevicePath* adPath, int* count);
20133 + * fills adDesc from the audio device given in path
20134 + * returns 0 if an error occurred
20135 + * if getNames is 0, only path and pathctl are filled
20136 + */
20137 +int getAudioDeviceDescription(char* path, AudioDeviceDescription* adDesc, int getNames);
20138 +int getAudioDeviceDescriptionByIndex(int index, AudioDeviceDescription* adDesc, int getNames);
20141 +#endif // PLATFORM_API_SOLARISOS_UTILS_H_INCLUDED
20142 diff -Nru jdk23u-jdk-23-36.orig/src/java.desktop/unix/classes/sun/awt/X11FontManager.java jdk23u-jdk-23-36/src/java.desktop/unix/classes/sun/awt/X11FontManager.java
20143 --- jdk23u-jdk-23-36.orig/src/java.desktop/unix/classes/sun/awt/X11FontManager.java 2024-08-07 00:08:22.000000000 +0200
20144 +++ jdk23u-jdk-23-36/src/java.desktop/unix/classes/sun/awt/X11FontManager.java 2024-08-17 19:50:33.121145192 +0200
20145 @@ -686,7 +686,8 @@
20146 * and do the best we can.
20148 FontConfiguration mFontConfig = new MFontConfiguration(this);
20149 - if ((FontUtilities.isLinux && !mFontConfig.foundOsSpecificFile())) {
20150 + if ((FontUtilities.isLinux && !mFontConfig.foundOsSpecificFile()) ||
20151 + (FontUtilities.isSolaris && !mFontConfig.fontFilesArePresent())) {
20152 FcFontConfiguration fcFontConfig =
20153 new FcFontConfiguration(this);
20154 if (fcFontConfig.init()) {
20155 diff -Nru jdk23u-jdk-23-36.orig/src/java.desktop/unix/classes/sun/font/MFontConfiguration.java jdk23u-jdk-23-36/src/java.desktop/unix/classes/sun/font/MFontConfiguration.java
20156 --- jdk23u-jdk-23-36.orig/src/java.desktop/unix/classes/sun/font/MFontConfiguration.java 2024-08-07 00:08:22.000000000 +0200
20157 +++ jdk23u-jdk-23-36/src/java.desktop/unix/classes/sun/font/MFontConfiguration.java 2024-08-17 19:50:33.121667916 +0200
20158 @@ -68,7 +68,59 @@
20160 protected void initReorderMap() {
20161 reorderMap = new HashMap<>();
20162 + if (osName == null) { /* null means SunOS */
20163 + initReorderMapForSolaris();
20164 + } else {
20165 + initReorderMapForLinux();
20169 + private void initReorderMapForSolaris() {
20170 + /* Don't create a no-op entry, so we can optimize this case
20171 + * i.e. we don't need to do anything so can avoid slower paths in
20172 + * the code.
20173 + */
20174 +// reorderMap.put("UTF-8", "latin-1");
20175 + reorderMap.put("UTF-8.hi", "devanagari"); // NB is in Lucida.
20176 + reorderMap.put("UTF-8.ja",
20177 + new String[] {"japanese-x0201", "japanese-x0208", "japanese-x0212"});
20178 + reorderMap.put("UTF-8.ko", "korean-johab");
20179 + reorderMap.put("UTF-8.th", "thai");
20180 + reorderMap.put("UTF-8.zh.TW", "chinese-big5");
20181 + reorderMap.put("UTF-8.zh.HK", new String[] {"chinese-big5", "chinese-hkscs"});
20182 + reorderMap.put("UTF-8.zh.CN",
20183 + new String[] {"chinese-gb18030-0", "chinese-gb18030-1"});
20184 + reorderMap.put("UTF-8.zh",
20185 + new String[] {"chinese-big5", "chinese-hkscs", "chinese-gb18030-0,chinese-gb18030-1"});
20186 + reorderMap.put("Big5", "chinese-big5");
20187 + reorderMap.put("Big5-HKSCS", new String[] {"chinese-big5", "chinese-hkscs"});
20188 + reorderMap.put("GB2312", new String[] {"chinese-gbk", "chinese-gb2312"});
20189 + reorderMap.put("x-EUC-TW",
20190 + new String[] {"chinese-cns11643-1", "chinese-cns11643-2", "chinese-cns11643-3"});
20191 + reorderMap.put("GBK", "chinese-gbk");
20192 + reorderMap.put("GB18030",new String[] {"chinese-gb18030-0", "chinese-gb18030-1"});
20194 + reorderMap.put("TIS-620", "thai");
20195 + reorderMap.put("x-PCK",
20196 + new String[] {"japanese-x0201", "japanese-x0208", "japanese-x0212"});
20197 + reorderMap.put("x-eucJP-Open",
20198 + new String[] {"japanese-x0201", "japanese-x0208", "japanese-x0212"});
20199 + reorderMap.put("EUC-KR", "korean");
20200 + /* Don't create a no-op entry, so we can optimize this case */
20201 +// reorderMap.put("ISO-8859-1", "latin-1");
20202 + reorderMap.put("ISO-8859-2", "latin-2");
20203 + reorderMap.put("ISO-8859-5", "cyrillic-iso8859-5");
20204 + reorderMap.put("windows-1251", "cyrillic-cp1251");
20205 + reorderMap.put("KOI8-R", "cyrillic-koi8-r");
20206 + reorderMap.put("ISO-8859-6", "arabic");
20207 + reorderMap.put("ISO-8859-7", "greek");
20208 + reorderMap.put("ISO-8859-8", "hebrew");
20209 + reorderMap.put("ISO-8859-9", "latin-5");
20210 + reorderMap.put("ISO-8859-13", "latin-7");
20211 + reorderMap.put("ISO-8859-15", "latin-9");
20214 + private void initReorderMapForLinux() {
20215 reorderMap.put("UTF-8.ja.JP", "japanese-iso10646");
20216 reorderMap.put("UTF-8.ko.KR", "korean-iso10646");
20217 reorderMap.put("UTF-8.zh.TW", "chinese-tw-iso10646");
20218 @@ -78,7 +130,12 @@
20219 reorderMap.put("GB2312", "chinese-gb18030");
20220 reorderMap.put("Big5", "chinese-big5");
20221 reorderMap.put("EUC-KR", "korean");
20222 - reorderMap.put("GB18030", "chinese-gb18030");
20223 + if (osName.equals("Sun")){
20224 + reorderMap.put("GB18030", "chinese-cn-iso10646");
20226 + else {
20227 + reorderMap.put("GB18030", "chinese-gb18030");
20232 @@ -87,7 +144,10 @@
20233 protected void setOsNameAndVersion(){
20234 super.setOsNameAndVersion();
20236 - if (osName.equals("Linux")) {
20237 + if (osName.equals("SunOS")) {
20238 + //don't care os name on Solaris
20239 + osName = null;
20240 + } else if (osName.equals("Linux")) {
20241 try {
20242 File f;
20243 if ((f = new File("/etc/fedora-release")).canRead()) {
20244 diff -Nru jdk23u-jdk-23-36.orig/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java jdk23u-jdk-23-36/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java
20245 --- jdk23u-jdk-23-36.orig/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java 2024-08-07 00:08:22.000000000 +0200
20246 +++ jdk23u-jdk-23-36/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java 2024-08-17 19:50:33.122397889 +0200
20247 @@ -150,6 +150,10 @@
20248 return OSInfo.getOSType() == OSInfo.OSType.MACOSX;
20251 + static boolean isSysV() {
20252 + return OSInfo.getOSType() == OSInfo.OSType.SOLARIS;
20255 static boolean isLinux() {
20256 return OSInfo.getOSType() == OSInfo.OSType.LINUX;
20258 @@ -301,7 +305,7 @@
20261 } else {
20262 - if (isMac()) {
20263 + if (isMac() || isSysV()) {
20264 printers = getAllPrinterNamesSysV();
20265 } else if (isAIX()) {
20266 printers = getAllPrinterNamesAIX();
20267 @@ -485,7 +489,7 @@
20269 /* fallback if nothing not having a printer at this point */
20270 PrintService printer = null;
20271 - if (isMac()) {
20272 + if (isMac() || isSysV()) {
20273 printer = getNamedPrinterNameSysV(name);
20274 } else if (isAIX()) {
20275 printer = getNamedPrinterNameAIX(name);
20276 @@ -656,7 +660,7 @@
20277 psuri = printerInfo[1];
20279 } else {
20280 - if (isMac()) {
20281 + if (isMac() || isSysV()) {
20282 defaultPrinter = getDefaultPrinterNameSysV();
20283 } else if (isAIX()) {
20284 defaultPrinter = getDefaultPrinterNameAIX();
20285 @@ -876,7 +880,7 @@
20286 ArrayList<String> results = null;
20287 try {
20288 final String[] cmd = new String[3];
20289 - if (isAIX()) {
20290 + if (isSysV() || isAIX()) {
20291 cmd[0] = "/usr/bin/sh";
20292 cmd[1] = "-c";
20293 cmd[2] = "env LC_ALL=C " + command;
20294 diff -Nru jdk23u-jdk-23-36.orig/src/java.desktop/unix/classes/sun/print/UnixPrintJob.java jdk23u-jdk-23-36/src/java.desktop/unix/classes/sun/print/UnixPrintJob.java
20295 --- jdk23u-jdk-23-36.orig/src/java.desktop/unix/classes/sun/print/UnixPrintJob.java 2024-08-07 00:08:22.000000000 +0200
20296 +++ jdk23u-jdk-23-36/src/java.desktop/unix/classes/sun/print/UnixPrintJob.java 2024-08-17 19:50:33.122953316 +0200
20297 @@ -872,25 +872,51 @@
20298 isAttributeCategorySupported(JobSheets.class)) {
20299 ncomps+=1;
20301 - execCmd = new String[ncomps];
20302 - execCmd[n++] = "/usr/bin/lpr";
20303 - if ((pFlags & PRINTER) != 0) {
20304 - execCmd[n++] = "-P" + printer;
20306 - if ((pFlags & JOBTITLE) != 0) {
20307 - execCmd[n++] = "-J " + jobTitle;
20309 - if ((pFlags & COPIES) != 0) {
20310 - execCmd[n++] = "-#" + copies;
20312 - if ((pFlags & NOSHEET) != 0) {
20313 - execCmd[n++] = "-h";
20314 - } else if (getPrintService().
20315 - isAttributeCategorySupported(JobSheets.class)) {
20316 - execCmd[n++] = "-o job-sheets=standard";
20318 - if ((pFlags & OPTIONS) != 0) {
20319 - execCmd[n++] = "-o" + options;
20320 + if (PrintServiceLookupProvider.isSysV()) {
20321 + ncomps+=1; // lp uses 1 more arg than lpr (make a copy)
20322 + execCmd = new String[ncomps];
20323 + execCmd[n++] = "/usr/bin/lp";
20324 + execCmd[n++] = "-c"; // make a copy of the spool file
20325 + if ((pFlags & PRINTER) != 0) {
20326 + execCmd[n++] = "-d" + printer;
20328 + if ((pFlags & JOBTITLE) != 0) {
20329 + String quoteChar = "\"";
20330 + execCmd[n++] = "-t " + quoteChar+jobTitle+quoteChar;
20332 + if ((pFlags & COPIES) != 0) {
20333 + execCmd[n++] = "-n " + copies;
20335 + if ((pFlags & NOSHEET) != 0) {
20336 + execCmd[n++] = "-o nobanner";
20337 + } else if (getPrintService().
20338 + isAttributeCategorySupported(JobSheets.class)) {
20339 + execCmd[n++] = "-o job-sheets=standard";
20341 + if ((pFlags & OPTIONS) != 0) {
20342 + execCmd[n++] = "-o " + options;
20344 + } else {
20345 + execCmd = new String[ncomps];
20346 + execCmd[n++] = "/usr/bin/lpr";
20347 + if ((pFlags & PRINTER) != 0) {
20348 + execCmd[n++] = "-P" + printer;
20350 + if ((pFlags & JOBTITLE) != 0) {
20351 + execCmd[n++] = "-J " + jobTitle;
20353 + if ((pFlags & COPIES) != 0) {
20354 + execCmd[n++] = "-#" + copies;
20356 + if ((pFlags & NOSHEET) != 0) {
20357 + execCmd[n++] = "-h";
20358 + } else if (getPrintService().
20359 + isAttributeCategorySupported(JobSheets.class)) {
20360 + execCmd[n++] = "-o job-sheets=standard";
20362 + if ((pFlags & OPTIONS) != 0) {
20363 + execCmd[n++] = "-o" + options;
20366 execCmd[n++] = spoolFile;
20367 if (IPPPrintService.debugPrint) {
20368 diff -Nru jdk23u-jdk-23-36.orig/src/java.desktop/unix/classes/sun/print/UnixPrintService.java jdk23u-jdk-23-36/src/java.desktop/unix/classes/sun/print/UnixPrintService.java
20369 --- jdk23u-jdk-23-36.orig/src/java.desktop/unix/classes/sun/print/UnixPrintService.java 2024-08-07 00:08:22.000000000 +0200
20370 +++ jdk23u-jdk-23-36/src/java.desktop/unix/classes/sun/print/UnixPrintService.java 2024-08-17 19:50:33.123745046 +0200
20371 @@ -220,6 +220,31 @@
20372 return name;
20375 + private PrinterIsAcceptingJobs getPrinterIsAcceptingJobsSysV() {
20376 + String command = "/usr/bin/lpstat -a " + printer;
20377 + String[] results= PrintServiceLookupProvider.execCmd(command);
20379 + if (results != null && results.length > 0) {
20380 + if (results[0].startsWith(printer + " accepting requests")) {
20381 + return PrinterIsAcceptingJobs.ACCEPTING_JOBS;
20383 + else if (results[0].startsWith(printer)) {
20384 + /* As well as "myprinter accepting requests", look for
20385 + * "myprinter@somehost accepting requests".
20386 + */
20387 + int index = printer.length();
20388 + String str = results[0];
20389 + if (str.length() > index &&
20390 + str.charAt(index) == '@' &&
20391 + str.indexOf(" accepting requests", index) > 0 &&
20392 + str.indexOf(" not accepting requests", index) == -1) {
20393 + return PrinterIsAcceptingJobs.ACCEPTING_JOBS;
20397 + return PrinterIsAcceptingJobs.NOT_ACCEPTING_JOBS ;
20400 private PrinterIsAcceptingJobs getPrinterIsAcceptingJobsBSD() {
20401 if (PrintServiceLookupProvider.cmdIndex ==
20402 PrintServiceLookupProvider.UNINITIALIZED) {
20403 @@ -297,7 +322,9 @@
20406 private PrinterIsAcceptingJobs getPrinterIsAcceptingJobs() {
20407 - if (PrintServiceLookupProvider.isBSD()) {
20408 + if (PrintServiceLookupProvider.isSysV()) {
20409 + return getPrinterIsAcceptingJobsSysV();
20410 + } else if (PrintServiceLookupProvider.isBSD()) {
20411 return getPrinterIsAcceptingJobsBSD();
20412 } else if (PrintServiceLookupProvider.isAIX()) {
20413 return getPrinterIsAcceptingJobsAIX();
20414 @@ -324,6 +351,14 @@
20418 + private QueuedJobCount getQueuedJobCountSysV() {
20419 + String command = "/usr/bin/lpstat -R " + printer;
20420 + String[] results= PrintServiceLookupProvider.execCmd(command);
20421 + int qlen = (results == null) ? 0 : results.length;
20423 + return new QueuedJobCount(qlen);
20426 private QueuedJobCount getQueuedJobCountBSD() {
20427 if (PrintServiceLookupProvider.cmdIndex ==
20428 PrintServiceLookupProvider.UNINITIALIZED) {
20429 @@ -380,7 +415,9 @@
20432 private QueuedJobCount getQueuedJobCount() {
20433 - if (PrintServiceLookupProvider.isBSD()) {
20434 + if (PrintServiceLookupProvider.isSysV()) {
20435 + return getQueuedJobCountSysV();
20436 + } else if (PrintServiceLookupProvider.isBSD()) {
20437 return getQueuedJobCountBSD();
20438 } else if (PrintServiceLookupProvider.isAIX()) {
20439 return getQueuedJobCountAIX();
20440 @@ -389,6 +426,13 @@
20444 + private PrintServiceAttributeSet getSysVServiceAttributes() {
20445 + PrintServiceAttributeSet attrs = new HashPrintServiceAttributeSet();
20446 + attrs.add(getQueuedJobCountSysV());
20447 + attrs.add(getPrinterIsAcceptingJobsSysV());
20448 + return attrs;
20451 private PrintServiceAttributeSet getBSDServiceAttributes() {
20452 PrintServiceAttributeSet attrs = new HashPrintServiceAttributeSet();
20453 attrs.add(getQueuedJobCountBSD());
20454 @@ -427,7 +471,9 @@
20457 private PrintServiceAttributeSet getDynamicAttributes() {
20458 - if (PrintServiceLookupProvider.isAIX()) {
20459 + if (PrintServiceLookupProvider.isSysV()) {
20460 + return getSysVServiceAttributes();
20461 + } else if (PrintServiceLookupProvider.isAIX()) {
20462 return getAIXServiceAttributes();
20463 } else {
20464 return getBSDServiceAttributes();
20465 diff -Nru jdk23u-jdk-23-36.orig/src/java.desktop/unix/native/common/awt/fontpath.c jdk23u-jdk-23-36/src/java.desktop/unix/native/common/awt/fontpath.c
20466 --- jdk23u-jdk-23-36.orig/src/java.desktop/unix/native/common/awt/fontpath.c 2024-08-07 00:08:22.000000000 +0200
20467 +++ jdk23u-jdk-23-36/src/java.desktop/unix/native/common/awt/fontpath.c 2024-08-17 19:50:33.125357403 +0200
20468 @@ -57,7 +57,57 @@
20470 #define MAXFDIRS 512 /* Max number of directories that contain fonts */
20472 -#if defined( __linux__)
20473 +#if defined(__solaris__)
20475 + * This can be set in the makefile to "/usr/X11" if so desired.
20476 + */
20477 +#ifndef OPENWINHOMELIB
20478 +#define OPENWINHOMELIB "/usr/openwin/lib/"
20479 +#endif
20481 +/* This is all known Solaris X11 directories on Solaris 8, 9 and 10.
20482 + * It is ordered to give precedence to TrueType directories.
20483 + * It is needed if fontconfig is not installed or configured properly.
20484 + */
20485 +static char *fullSolarisFontPath[] = {
20486 + OPENWINHOMELIB "X11/fonts/TrueType",
20487 + OPENWINHOMELIB "locale/euro_fonts/X11/fonts/TrueType",
20488 + OPENWINHOMELIB "locale/iso_8859_2/X11/fonts/TrueType",
20489 + OPENWINHOMELIB "locale/iso_8859_5/X11/fonts/TrueType",
20490 + OPENWINHOMELIB "locale/iso_8859_7/X11/fonts/TrueType",
20491 + OPENWINHOMELIB "locale/iso_8859_8/X11/fonts/TrueType",
20492 + OPENWINHOMELIB "locale/iso_8859_9/X11/fonts/TrueType",
20493 + OPENWINHOMELIB "locale/iso_8859_13/X11/fonts/TrueType",
20494 + OPENWINHOMELIB "locale/iso_8859_15/X11/fonts/TrueType",
20495 + OPENWINHOMELIB "locale/ar/X11/fonts/TrueType",
20496 + OPENWINHOMELIB "locale/hi_IN.UTF-8/X11/fonts/TrueType",
20497 + OPENWINHOMELIB "locale/ja/X11/fonts/TT",
20498 + OPENWINHOMELIB "locale/ko/X11/fonts/TrueType",
20499 + OPENWINHOMELIB "locale/ko.UTF-8/X11/fonts/TrueType",
20500 + OPENWINHOMELIB "locale/KOI8-R/X11/fonts/TrueType",
20501 + OPENWINHOMELIB "locale/ru.ansi-1251/X11/fonts/TrueType",
20502 + OPENWINHOMELIB "locale/th_TH/X11/fonts/TrueType",
20503 + OPENWINHOMELIB "locale/zh_TW/X11/fonts/TrueType",
20504 + OPENWINHOMELIB "locale/zh_TW.BIG5/X11/fonts/TT",
20505 + OPENWINHOMELIB "locale/zh_HK.BIG5HK/X11/fonts/TT",
20506 + OPENWINHOMELIB "locale/zh_CN.GB18030/X11/fonts/TrueType",
20507 + OPENWINHOMELIB "locale/zh/X11/fonts/TrueType",
20508 + OPENWINHOMELIB "locale/zh.GBK/X11/fonts/TrueType",
20509 + OPENWINHOMELIB "X11/fonts/Type1",
20510 + OPENWINHOMELIB "X11/fonts/Type1/sun",
20511 + OPENWINHOMELIB "X11/fonts/Type1/sun/outline",
20512 + OPENWINHOMELIB "locale/iso_8859_2/X11/fonts/Type1",
20513 + OPENWINHOMELIB "locale/iso_8859_4/X11/fonts/Type1",
20514 + OPENWINHOMELIB "locale/iso_8859_5/X11/fonts/Type1",
20515 + OPENWINHOMELIB "locale/iso_8859_7/X11/fonts/Type1",
20516 + OPENWINHOMELIB "locale/iso_8859_8/X11/fonts/Type1",
20517 + OPENWINHOMELIB "locale/iso_8859_9/X11/fonts/Type1",
20518 + OPENWINHOMELIB "locale/iso_8859_13/X11/fonts/Type1",
20519 + OPENWINHOMELIB "locale/ar/X11/fonts/Type1",
20520 + NULL, /* terminates the list */
20523 +#elif defined( __linux__)
20524 /* All the known interesting locations we have discovered on
20525 * various flavors of Linux
20527 @@ -173,6 +223,14 @@
20528 if (strstr(x11Path[i], ".gnome") != NULL) {
20529 continue;
20531 +#ifdef __solaris__
20532 + if (strstr(x11Path[i], "/F3/") != NULL) {
20533 + continue;
20535 + if (strstr(x11Path[i], "bitmap") != NULL) {
20536 + continue;
20538 +#endif
20539 fontdirs[pos] = strdup(x11Path[i]);
20540 slen = strlen(fontdirs[pos]);
20541 if (slen > 0 && fontdirs[pos][slen-1] == '/') {
20542 @@ -322,6 +380,8 @@
20544 #if defined(__linux__)
20545 knowndirs = fullLinuxFontPath;
20546 +#elif defined(__solaris__)
20547 + knowndirs = fullSolarisFontPath;
20548 #elif defined(_AIX)
20549 knowndirs = fullAixFontPath;
20550 #endif
20551 diff -Nru jdk23u-jdk-23-36.orig/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c jdk23u-jdk-23-36/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c
20552 --- jdk23u-jdk-23-36.orig/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c 2024-08-07 00:08:22.000000000 +0200
20553 +++ jdk23u-jdk-23-36/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c 2024-08-17 19:50:33.126731044 +0200
20554 @@ -402,7 +402,12 @@
20555 xrenderLibHandle = dlopen("libXrender.so", RTLD_LAZY | RTLD_GLOBAL);
20558 -#if defined(_AIX)
20559 +#if defined(__solaris__)
20560 + if (xrenderLibHandle == NULL) {
20561 + xrenderLibHandle = dlopen("libXrender.so.1",
20562 + RTLD_LAZY | RTLD_GLOBAL);
20564 +#elif defined(_AIX)
20565 if (xrenderLibHandle == NULL) {
20566 xrenderLibHandle = dlopen("libXrender.a(libXrender.so.0)",
20567 RTLD_MEMBER | RTLD_LAZY | RTLD_GLOBAL);
20568 diff -Nru jdk23u-jdk-23-36.orig/src/java.desktop/unix/native/libawt_xawt/java2d/x11/XRBackendNative.c jdk23u-jdk-23-36/src/java.desktop/unix/native/libawt_xawt/java2d/x11/XRBackendNative.c
20569 --- jdk23u-jdk-23-36.orig/src/java.desktop/unix/native/libawt_xawt/java2d/x11/XRBackendNative.c 2024-08-07 00:08:22.000000000 +0200
20570 +++ jdk23u-jdk-23-36/src/java.desktop/unix/native/libawt_xawt/java2d/x11/XRBackendNative.c 2024-08-17 19:50:33.127999355 +0200
20571 @@ -61,6 +61,29 @@
20573 #include <dlfcn.h>
20575 +#if defined(__solaris__)
20576 +/* Solaris 10 will not have these symbols at compile time */
20578 +typedef Picture (*XRenderCreateLinearGradientFuncType)
20579 + (Display *dpy,
20580 + const XLinearGradient *gradient,
20581 + const XFixed *stops,
20582 + const XRenderColor *colors,
20583 + int nstops);
20585 +typedef Picture (*XRenderCreateRadialGradientFuncType)
20586 + (Display *dpy,
20587 + const XRadialGradient *gradient,
20588 + const XFixed *stops,
20589 + const XRenderColor *colors,
20590 + int nstops);
20592 +static
20593 +XRenderCreateLinearGradientFuncType XRenderCreateLinearGradientFunc = NULL;
20594 +static
20595 + XRenderCreateRadialGradientFuncType XRenderCreateRadialGradientFunc = NULL;
20596 +#endif
20598 #define BUILD_TRANSFORM_MATRIX(TRANSFORM, M00, M01, M02, M10, M11, M12) \
20600 TRANSFORM.matrix[0][0] = M00; \
20601 @@ -128,6 +151,27 @@
20602 } else {
20603 available = JNI_FALSE;
20605 +#elif defined(__solaris__)
20606 + xrenderlib = dlopen("libXrender.so",RTLD_GLOBAL|RTLD_LAZY);
20607 + if (xrenderlib != NULL) {
20609 + XRenderCreateLinearGradientFunc =
20610 + (XRenderCreateLinearGradientFuncType)
20611 + dlsym(xrenderlib, "XRenderCreateLinearGradient");
20613 + XRenderCreateRadialGradientFunc =
20614 + (XRenderCreateRadialGradientFuncType)
20615 + dlsym(xrenderlib, "XRenderCreateRadialGradient");
20617 + if (XRenderCreateLinearGradientFunc == NULL ||
20618 + XRenderCreateRadialGradientFunc == NULL)
20620 + available = JNI_FALSE;
20622 + dlclose(xrenderlib);
20623 + } else {
20624 + available = JNI_FALSE;
20626 #else
20627 Dl_info info;
20628 jboolean versionInfoIsFound = JNI_FALSE;
20629 @@ -534,7 +578,13 @@
20630 colors[i].green = pixels[i*4 + 2];
20631 colors[i].blue = pixels[i*4 + 3];
20633 +#ifdef __solaris__
20634 + if (XRenderCreateLinearGradientFunc!=NULL) {
20635 + gradient = (*XRenderCreateLinearGradientFunc)(awt_display, &grad, stops, colors, numStops);
20637 +#else
20638 gradient = XRenderCreateLinearGradient(awt_display, &grad, stops, colors, numStops);
20639 +#endif
20640 free(colors);
20641 free(stops);
20643 @@ -612,7 +662,13 @@
20644 colors[i].green = pixels[i*4 + 2];
20645 colors[i].blue = pixels[i*4 + 3];
20647 +#ifdef __solaris__
20648 + if (XRenderCreateRadialGradientFunc != NULL) {
20649 + gradient = (jint) (*XRenderCreateRadialGradientFunc)(awt_display, &grad, stops, colors, numStops);
20651 +#else
20652 gradient = (jint) XRenderCreateRadialGradient(awt_display, &grad, stops, colors, numStops);
20653 +#endif
20654 free(colors);
20655 free(stops);
20657 diff -Nru jdk23u-jdk-23-36.orig/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/SunNativeProvider.java jdk23u-jdk-23-36/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/SunNativeProvider.java
20658 --- jdk23u-jdk-23-36.orig/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/SunNativeProvider.java 2024-08-07 00:08:22.000000000 +0200
20659 +++ jdk23u-jdk-23-36/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/SunNativeProvider.java 2024-08-17 19:50:33.128566902 +0200
20660 @@ -91,6 +91,9 @@
20661 = System.getProperty("sun.security.jgss.lib");
20662 if (defaultLib == null || defaultLib.trim().equals("")) {
20663 gssLibs = switch (OperatingSystem.current()) {
20664 + case SOLARIS -> new String[]{
20665 + "libgss.so",
20666 + };
20667 case LINUX -> new String[]{
20668 "libgssapi.so",
20669 "libgssapi_krb5.so",
20670 diff -Nru jdk23u-jdk-23-36.orig/src/java.security.jgss/share/classes/sun/security/krb5/Config.java jdk23u-jdk-23-36/src/java.security.jgss/share/classes/sun/security/krb5/Config.java
20671 --- jdk23u-jdk-23-36.orig/src/java.security.jgss/share/classes/sun/security/krb5/Config.java 2024-08-07 00:08:22.000000000 +0200
20672 +++ jdk23u-jdk-23-36/src/java.security.jgss/share/classes/sun/security/krb5/Config.java 2024-08-17 19:50:33.129217740 +0200
20673 @@ -930,6 +930,8 @@
20674 if (name == null) {
20675 name = "c:\\winnt\\krb5.ini";
20677 + } else if (OperatingSystem.isSolaris()) {
20678 + name = "/etc/krb5/krb5.conf";
20679 } else if (OperatingSystem.isMacOS()) {
20680 name = findMacosConfigFile();
20681 } else {
20682 diff -Nru jdk23u-jdk-23-36.orig/src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/DflCache.java jdk23u-jdk-23-36/src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/DflCache.java
20683 --- jdk23u-jdk-23-36.orig/src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/DflCache.java 2024-08-07 00:08:22.000000000 +0200
20684 +++ jdk23u-jdk-23-36/src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/DflCache.java 2024-08-17 19:50:33.129741596 +0200
20685 @@ -107,7 +107,7 @@
20687 private static long uid;
20688 static {
20689 - // Available on Linux and Mac. Otherwise, -1 and no _euid suffix
20690 + // Available on Solaris, Linux and Mac. Otherwise, -1 and no _euid suffix
20691 uid = jdk.internal.misc.VM.geteuid();
20694 diff -Nru jdk23u-jdk-23-36.orig/src/java.smartcardio/unix/classes/sun/security/smartcardio/PlatformPCSC.java jdk23u-jdk-23-36/src/java.smartcardio/unix/classes/sun/security/smartcardio/PlatformPCSC.java
20695 --- jdk23u-jdk-23-36.orig/src/java.smartcardio/unix/classes/sun/security/smartcardio/PlatformPCSC.java 2024-08-07 00:08:22.000000000 +0200
20696 +++ jdk23u-jdk-23-36/src/java.smartcardio/unix/classes/sun/security/smartcardio/PlatformPCSC.java 2024-08-17 19:50:33.130264480 +0200
20697 @@ -86,8 +86,12 @@
20698 if (k != -1) {
20699 String libDir;
20700 if ("64".equals(System.getProperty("sun.arch.data.model"))) {
20701 - // assume Linux convention
20702 - libDir = "lib64";
20703 + if ("SunOS".equals(System.getProperty("os.name"))) {
20704 + libDir = "lib/64";
20705 + } else {
20706 + // assume Linux convention
20707 + libDir = "lib64";
20709 } else {
20710 // must be 32-bit
20711 libDir = "lib";
20712 diff -Nru jdk23u-jdk-23-36.orig/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/output/WriterOutputBuffer.java jdk23u-jdk-23-36/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/output/WriterOutputBuffer.java
20713 --- jdk23u-jdk-23-36.orig/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/output/WriterOutputBuffer.java 2024-08-07 00:08:22.000000000 +0200
20714 +++ jdk23u-jdk-23-36/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/output/WriterOutputBuffer.java 2024-08-17 19:50:33.130883399 +0200
20715 @@ -33,12 +33,21 @@
20716 private static final int KB = 1024;
20717 private static int BUFFER_SIZE = 4 * KB;
20719 + static {
20720 + // Set a larger buffer size for Solaris
20721 + final String osName = SecuritySupport.getSystemProperty("os.name");
20722 + if (osName.equalsIgnoreCase("solaris")) {
20723 + BUFFER_SIZE = 32 * KB;
20727 private Writer _writer;
20730 * Initializes a WriterOutputBuffer by creating an instance of a
20731 * BufferedWriter. The size of the buffer in this writer may have
20732 - * a significant impact on throughput.
20733 + * a significant impact on throughput. Solaris prefers a larger
20734 + * buffer, while Linux works better with a smaller one.
20736 public WriterOutputBuffer(Writer writer) {
20737 _writer = new BufferedWriter(writer, BUFFER_SIZE);
20738 diff -Nru jdk23u-jdk-23-36.orig/src/jdk.attach/solaris/classes/sun/tools/attach/AttachProviderImpl.java jdk23u-jdk-23-36/src/jdk.attach/solaris/classes/sun/tools/attach/AttachProviderImpl.java
20739 --- jdk23u-jdk-23-36.orig/src/jdk.attach/solaris/classes/sun/tools/attach/AttachProviderImpl.java 1970-01-01 01:00:00.000000000 +0100
20740 +++ jdk23u-jdk-23-36/src/jdk.attach/solaris/classes/sun/tools/attach/AttachProviderImpl.java 2024-08-17 19:50:33.164817184 +0200
20741 @@ -0,0 +1,79 @@
20743 + * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
20744 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
20746 + * This code is free software; you can redistribute it and/or modify it
20747 + * under the terms of the GNU General Public License version 2 only, as
20748 + * published by the Free Software Foundation. Oracle designates this
20749 + * particular file as subject to the "Classpath" exception as provided
20750 + * by Oracle in the LICENSE file that accompanied this code.
20752 + * This code is distributed in the hope that it will be useful, but WITHOUT
20753 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20754 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20755 + * version 2 for more details (a copy is included in the LICENSE file that
20756 + * accompanied this code).
20758 + * You should have received a copy of the GNU General Public License version
20759 + * 2 along with this work; if not, write to the Free Software Foundation,
20760 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20762 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20763 + * or visit www.oracle.com if you need additional information or have any
20764 + * questions.
20765 + */
20766 +package sun.tools.attach;
20768 +import com.sun.tools.attach.VirtualMachine;
20769 +import com.sun.tools.attach.VirtualMachineDescriptor;
20770 +import com.sun.tools.attach.AttachNotSupportedException;
20771 +import java.io.IOException;
20774 + * An AttachProvider implementation for Solaris that use the doors
20775 + * interface to the VM.
20776 + */
20777 +public class AttachProviderImpl extends HotSpotAttachProvider {
20779 + public AttachProviderImpl() {
20782 + public String name() {
20783 + return "sun";
20786 + public String type() {
20787 + return "doors";
20790 + public VirtualMachine attachVirtualMachine(String vmid)
20791 + throws AttachNotSupportedException, IOException
20793 + checkAttachPermission();
20795 + // AttachNotSupportedException will be thrown if the target VM can be determined
20796 + // to be not attachable.
20797 + testAttachable(vmid);
20799 + return new VirtualMachineImpl(this, vmid);
20802 + public VirtualMachine attachVirtualMachine(VirtualMachineDescriptor vmd)
20803 + throws AttachNotSupportedException, IOException
20805 + if (vmd.provider() != this) {
20806 + throw new AttachNotSupportedException("provider mismatch");
20808 + // To avoid re-checking if the VM if attachable, we check if the descriptor
20809 + // is for a hotspot VM - these descriptors are created by the listVirtualMachines
20810 + // implementation which only returns a list of attachable VMs.
20811 + if (vmd instanceof HotSpotVirtualMachineDescriptor) {
20812 + assert ((HotSpotVirtualMachineDescriptor)vmd).isAttachable();
20813 + checkAttachPermission();
20814 + return new VirtualMachineImpl(this, vmd.id());
20815 + } else {
20816 + return attachVirtualMachine(vmd.id());
20821 diff -Nru jdk23u-jdk-23-36.orig/src/jdk.attach/solaris/classes/sun/tools/attach/VirtualMachineImpl.java jdk23u-jdk-23-36/src/jdk.attach/solaris/classes/sun/tools/attach/VirtualMachineImpl.java
20822 --- jdk23u-jdk-23-36.orig/src/jdk.attach/solaris/classes/sun/tools/attach/VirtualMachineImpl.java 1970-01-01 01:00:00.000000000 +0100
20823 +++ jdk23u-jdk-23-36/src/jdk.attach/solaris/classes/sun/tools/attach/VirtualMachineImpl.java 2024-08-17 19:50:33.165157975 +0200
20824 @@ -0,0 +1,272 @@
20826 + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
20827 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
20829 + * This code is free software; you can redistribute it and/or modify it
20830 + * under the terms of the GNU General Public License version 2 only, as
20831 + * published by the Free Software Foundation. Oracle designates this
20832 + * particular file as subject to the "Classpath" exception as provided
20833 + * by Oracle in the LICENSE file that accompanied this code.
20835 + * This code is distributed in the hope that it will be useful, but WITHOUT
20836 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20837 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20838 + * version 2 for more details (a copy is included in the LICENSE file that
20839 + * accompanied this code).
20841 + * You should have received a copy of the GNU General Public License version
20842 + * 2 along with this work; if not, write to the Free Software Foundation,
20843 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20845 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20846 + * or visit www.oracle.com if you need additional information or have any
20847 + * questions.
20848 + */
20849 +package sun.tools.attach;
20851 +import com.sun.tools.attach.AttachOperationFailedException;
20852 +import com.sun.tools.attach.AgentLoadException;
20853 +import com.sun.tools.attach.AttachNotSupportedException;
20854 +import com.sun.tools.attach.spi.AttachProvider;
20856 +import java.io.InputStream;
20857 +import java.io.IOException;
20858 +import java.io.File;
20859 +import java.io.FileNotFoundException;
20862 + * Solaris implementation of HotSpotVirtualMachine.
20863 + */
20864 +public class VirtualMachineImpl extends HotSpotVirtualMachine {
20865 + // "/tmp" is used as a global well-known location for the files
20866 + // .java_pid<pid>. and .attach_pid<pid>. It is important that this
20867 + // location is the same for all processes, otherwise the tools
20868 + // will not be able to find all Hotspot processes.
20869 + // Any changes to this needs to be synchronized with HotSpot.
20870 + private static final String tmpdir = "/tmp";
20872 + // door descriptor;
20873 + private int fd = -1;
20874 + String socket_path;
20876 + /**
20877 + * Attaches to the target VM
20878 + */
20879 + VirtualMachineImpl(AttachProvider provider, String vmid)
20880 + throws AttachNotSupportedException, IOException
20882 + super(provider, vmid);
20883 + // This provider only understands process-ids (pids).
20884 + int pid;
20885 + try {
20886 + pid = Integer.parseInt(vmid);
20887 + if (pid < 1) {
20888 + throw new NumberFormatException();
20890 + } catch (NumberFormatException x) {
20891 + throw new AttachNotSupportedException("Invalid process identifier: " + vmid);
20894 + // Opens the door file to the target VM. If the file is not
20895 + // found it might mean that the attach mechanism isn't started in the
20896 + // target VM so we attempt to start it and retry.
20897 + try {
20898 + fd = openDoor(pid);
20899 + } catch (FileNotFoundException fnf1) {
20900 + File f = createAttachFile(pid);
20901 + try {
20902 + sigquit(pid);
20904 + // give the target VM time to start the attach mechanism
20905 + final int delay_step = 100;
20906 + final long timeout = attachTimeout();
20907 + long time_spend = 0;
20908 + long delay = 0;
20909 + do {
20910 + // Increase timeout on each attempt to reduce polling
20911 + delay += delay_step;
20912 + try {
20913 + Thread.sleep(delay);
20914 + } catch (InterruptedException x) { }
20915 + try {
20916 + fd = openDoor(pid);
20917 + } catch (FileNotFoundException fnf2) {
20918 + // pass
20921 + time_spend += delay;
20922 + if (time_spend > timeout/2 && fd == -1) {
20923 + // Send QUIT again to give target VM the last chance to react
20924 + sigquit(pid);
20926 + } while (time_spend <= timeout && fd == -1);
20927 + if (fd == -1) {
20928 + throw new AttachNotSupportedException(
20929 + String.format("Unable to open door %s: " +
20930 + "target process %d doesn't respond within %dms " +
20931 + "or HotSpot VM not loaded", socket_path, pid, time_spend));
20933 + } finally {
20934 + f.delete();
20937 + assert fd >= 0;
20940 + /**
20941 + * Detach from the target VM
20942 + */
20943 + public void detach() throws IOException {
20944 + synchronized (this) {
20945 + if (fd != -1) {
20946 + close(fd);
20947 + fd = -1;
20952 + /**
20953 + * Execute the given command in the target VM.
20954 + */
20955 + InputStream execute(String cmd, Object ... args) throws AgentLoadException, IOException {
20956 + assert args.length <= 3; // includes null
20958 + // first check that we are still attached
20959 + int door;
20960 + synchronized (this) {
20961 + if (fd == -1) {
20962 + throw new IOException("Detached from target VM");
20964 + door = fd;
20967 + // enqueue the command via a door call
20968 + int s = enqueue(door, cmd, args);
20969 + assert s >= 0; // valid file descriptor
20971 + // The door call returns a file descriptor (one end of a socket pair).
20972 + // Create an input stream around it.
20973 + SocketInputStream sis = new SocketInputStream(s);
20975 + // Read the command completion status
20976 + int completionStatus;
20977 + try {
20978 + completionStatus = readInt(sis);
20979 + } catch (IOException ioe) {
20980 + sis.close();
20981 + throw ioe;
20984 + // If non-0 it means an error but we need to special-case the
20985 + // "load" command to ensure that the right exception is thrown.
20986 + if (completionStatus != 0) {
20987 + // read from the stream and use that as the error message
20988 + String message = readErrorMessage(sis);
20989 + sis.close();
20990 + if (cmd.equals("load")) {
20991 + String msg = "Failed to load agent library";
20992 + if (!message.isEmpty())
20993 + msg += ": " + message;
20994 + throw new AgentLoadException(msg);
20995 + } else {
20996 + if (message.isEmpty())
20997 + message = "Command failed in target VM";
20998 + throw new AttachOperationFailedException(message);
21002 + // Return the input stream so that the command output can be read
21003 + return sis;
21006 + // InputStream over a socket
21007 + private class SocketInputStream extends InputStream {
21008 + int s;
21010 + public SocketInputStream(int s) {
21011 + this.s = s;
21014 + public synchronized int read() throws IOException {
21015 + byte b[] = new byte[1];
21016 + int n = this.read(b, 0, 1);
21017 + if (n == 1) {
21018 + return b[0] & 0xff;
21019 + } else {
21020 + return -1;
21024 + public synchronized int read(byte[] bs, int off, int len) throws IOException {
21025 + if ((off < 0) || (off > bs.length) || (len < 0) ||
21026 + ((off + len) > bs.length) || ((off + len) < 0)) {
21027 + throw new IndexOutOfBoundsException();
21028 + } else if (len == 0)
21029 + return 0;
21031 + return VirtualMachineImpl.read(s, bs, off, len);
21034 + public synchronized void close() throws IOException {
21035 + if (s != -1) {
21036 + int toClose = s;
21037 + s = -1;
21038 + VirtualMachineImpl.close(toClose);
21043 + // The door is attached to .java_pid<pid> in the temporary directory.
21044 + private int openDoor(int pid) throws IOException {
21045 + socket_path = tmpdir + "/.java_pid" + pid;
21046 + fd = open(socket_path);
21048 + // Check that the file owner/permission to avoid attaching to
21049 + // bogus process
21050 + try {
21051 + checkPermissions(socket_path);
21052 + } catch (IOException ioe) {
21053 + close(fd);
21054 + throw ioe;
21056 + return fd;
21059 + // On Solaris a simple handshake is used to start the attach mechanism
21060 + // if not already started. The client creates a .attach_pid<pid> file in the
21061 + // target VM's working directory (or temporary directory), and the SIGQUIT
21062 + // handler checks for the file.
21063 + private File createAttachFile(int pid) throws IOException {
21064 + String fn = ".attach_pid" + pid;
21065 + String path = "/proc/" + pid + "/cwd/" + fn;
21066 + File f = new File(path);
21067 + try {
21068 + f = f.getCanonicalFile();
21069 + f.createNewFile();
21070 + } catch (IOException x) {
21071 + f = new File(tmpdir, fn);
21072 + f.createNewFile();
21074 + return f;
21077 + //-- native methods
21079 + static native int open(String path) throws IOException;
21081 + static native void close(int fd) throws IOException;
21083 + static native int read(int fd, byte buf[], int off, int buflen) throws IOException;
21085 + static native void checkPermissions(String path) throws IOException;
21087 + static native void sigquit(int pid) throws IOException;
21089 + // enqueue a command (and arguments) to the given door
21090 + static native int enqueue(int fd, String cmd, Object ... args)
21091 + throws IOException;
21093 + static {
21094 + System.loadLibrary("attach");
21097 diff -Nru jdk23u-jdk-23-36.orig/src/jdk.attach/solaris/native/libattach/VirtualMachineImpl.c jdk23u-jdk-23-36/src/jdk.attach/solaris/native/libattach/VirtualMachineImpl.c
21098 --- jdk23u-jdk-23-36.orig/src/jdk.attach/solaris/native/libattach/VirtualMachineImpl.c 1970-01-01 01:00:00.000000000 +0100
21099 +++ jdk23u-jdk-23-36/src/jdk.attach/solaris/native/libattach/VirtualMachineImpl.c 2024-08-17 19:50:33.165610346 +0200
21100 @@ -0,0 +1,389 @@
21102 + * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
21103 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
21105 + * This code is free software; you can redistribute it and/or modify it
21106 + * under the terms of the GNU General Public License version 2 only, as
21107 + * published by the Free Software Foundation. Oracle designates this
21108 + * particular file as subject to the "Classpath" exception as provided
21109 + * by Oracle in the LICENSE file that accompanied this code.
21111 + * This code is distributed in the hope that it will be useful, but WITHOUT
21112 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21113 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21114 + * version 2 for more details (a copy is included in the LICENSE file that
21115 + * accompanied this code).
21117 + * You should have received a copy of the GNU General Public License version
21118 + * 2 along with this work; if not, write to the Free Software Foundation,
21119 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21121 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21122 + * or visit www.oracle.com if you need additional information or have any
21123 + * questions.
21124 + */
21126 +#include "jni_util.h"
21128 +#include <sys/stat.h>
21129 +#include <sys/types.h>
21130 +#include <door.h>
21131 +#include <errno.h>
21132 +#include <fcntl.h>
21133 +#include <limits.h>
21134 +#include <signal.h>
21135 +#include <stdlib.h>
21136 +#include <string.h>
21137 +#include <unistd.h>
21139 +#include "sun_tools_attach_VirtualMachineImpl.h"
21141 +#define ROOT_UID 0
21143 +#define RESTARTABLE(_cmd, _result) do { \
21144 + do { \
21145 + _result = _cmd; \
21146 + } while((_result == -1) && (errno == EINTR)); \
21147 +} while(0)
21150 + * Declare library specific JNI_Onload entry if static build
21151 + */
21152 +DEF_STATIC_JNI_OnLoad
21155 + * Class: sun_tools_attach_VirtualMachineImpl
21156 + * Method: open
21157 + * Signature: (Ljava/lang/String;)I
21158 + */
21159 +JNIEXPORT jint JNICALL Java_sun_tools_attach_VirtualMachineImpl_open
21160 + (JNIEnv *env, jclass cls, jstring path)
21162 + jboolean isCopy;
21163 + const char* p = GetStringPlatformChars(env, path, &isCopy);
21164 + if (p == NULL) {
21165 + return 0;
21166 + } else {
21167 + int fd;
21168 + int err = 0;
21170 + fd = open(p, O_RDWR);
21171 + if (fd == -1) {
21172 + err = errno;
21175 + if (isCopy) {
21176 + JNU_ReleaseStringPlatformChars(env, path, p);
21179 + if (fd == -1) {
21180 + if (err == ENOENT) {
21181 + JNU_ThrowByName(env, "java/io/FileNotFoundException", NULL);
21182 + } else {
21183 + char* msg = strdup(strerror(err));
21184 + JNU_ThrowIOException(env, msg);
21185 + if (msg != NULL) {
21186 + free(msg);
21190 + return fd;
21195 + * Class: sun_tools_attach_VirtualMachineImpl
21196 + * Method: checkPermissions
21197 + * Signature: (Ljava/lang/String;)V
21198 + */
21199 +JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_checkPermissions
21200 + (JNIEnv *env, jclass cls, jstring path)
21202 + jboolean isCopy;
21203 + const char* p = GetStringPlatformChars(env, path, &isCopy);
21204 + if (p != NULL) {
21205 + struct stat64 sb;
21206 + uid_t uid, gid;
21207 + int res;
21209 + memset(&sb, 0, sizeof(struct stat64));
21211 + /*
21212 + * Check that the path is owned by the effective uid/gid of this
21213 + * process. Also check that group/other access is not allowed.
21214 + */
21215 + uid = geteuid();
21216 + gid = getegid();
21218 + res = stat64(p, &sb);
21219 + if (res != 0) {
21220 + /* save errno */
21221 + res = errno;
21224 + if (res == 0) {
21225 + char msg[100];
21226 + jboolean isError = JNI_FALSE;
21227 + if (sb.st_uid != uid && uid != ROOT_UID) {
21228 + snprintf(msg, sizeof(msg),
21229 + "file should be owned by the current user (which is %d) but is owned by %d", uid, sb.st_uid);
21230 + isError = JNI_TRUE;
21231 + } else if (sb.st_gid != gid && uid != ROOT_UID) {
21232 + snprintf(msg, sizeof(msg),
21233 + "file's group should be the current group (which is %d) but the group is %d", gid, sb.st_gid);
21234 + isError = JNI_TRUE;
21235 + } else if ((sb.st_mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) != 0) {
21236 + snprintf(msg, sizeof(msg),
21237 + "file should only be readable and writable by the owner but has 0%03o access", sb.st_mode & 0777);
21238 + isError = JNI_TRUE;
21240 + if (isError) {
21241 + char buf[256];
21242 + snprintf(buf, sizeof(buf), "well-known file %s is not secure: %s", p, msg);
21243 + JNU_ThrowIOException(env, buf);
21245 + } else {
21246 + char* msg = strdup(strerror(res));
21247 + JNU_ThrowIOException(env, msg);
21248 + if (msg != NULL) {
21249 + free(msg);
21253 + if (isCopy) {
21254 + JNU_ReleaseStringPlatformChars(env, path, p);
21260 + * Class: sun_tools_attach_VirtualMachineImpl
21261 + * Method: close
21262 + * Signature: (I)V
21263 + */
21264 +JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_close
21265 + (JNIEnv *env, jclass cls, jint fd)
21267 + int ret;
21268 + RESTARTABLE(close(fd), ret);
21272 + * Class: sun_tools_attach_VirtualMachineImpl
21273 + * Method: read
21274 + * Signature: (I[BI)I
21275 + */
21276 +JNIEXPORT jint JNICALL Java_sun_tools_attach_VirtualMachineImpl_read
21277 + (JNIEnv *env, jclass cls, jint fd, jbyteArray ba, jint off, jint baLen)
21279 + unsigned char buf[128];
21280 + size_t len = sizeof(buf);
21281 + ssize_t n;
21283 + size_t remaining = (size_t)(baLen - off);
21284 + if (len > remaining) {
21285 + len = remaining;
21288 + RESTARTABLE(read(fd, buf, len), n);
21289 + if (n == -1) {
21290 + JNU_ThrowIOExceptionWithLastError(env, "read");
21291 + } else {
21292 + if (n == 0) {
21293 + n = -1; // EOF
21294 + } else {
21295 + (*env)->SetByteArrayRegion(env, ba, off, (jint)n, (jbyte *)(buf));
21298 + return n;
21302 + * Class: sun_tools_attach_VirtualMachineImpl
21303 + * Method: sigquit
21304 + * Signature: (I)V
21305 + */
21306 +JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_sigquit
21307 + (JNIEnv *env, jclass cls, jint pid)
21309 + if (kill((pid_t)pid, SIGQUIT) == -1) {
21310 + JNU_ThrowIOExceptionWithLastError(env, "kill");
21315 + * A simple table to translate some known errors into reasonable
21316 + * error messages
21317 + */
21318 +static struct {
21319 + jint err;
21320 + const char* msg;
21321 +} const error_messages[] = {
21322 + { 100, "Bad request" },
21323 + { 101, "Protocol mismatch" },
21324 + { 102, "Resource failure" },
21325 + { 103, "Internal error" },
21326 + { 104, "Permission denied" },
21330 + * Lookup the given error code and return the appropriate
21331 + * message. If not found return NULL.
21332 + */
21333 +static const char* translate_error(jint err) {
21334 + int table_size = sizeof(error_messages) / sizeof(error_messages[0]);
21335 + int i;
21337 + for (i = 0; i < table_size; i++) {
21338 + if (err == error_messages[i].err) {
21339 + return error_messages[i].msg;
21342 + return NULL;
21346 + * Current protocol version
21347 + */
21348 +static const char* PROTOCOL_VERSION = "1";
21351 + * Class: sun_tools_attach_VirtualMachineImpl
21352 + * Method: enqueue
21353 + * Signature: (JILjava/lang/String;[Ljava/lang/Object;)V
21354 + */
21355 +JNIEXPORT jint JNICALL Java_sun_tools_attach_VirtualMachineImpl_enqueue
21356 + (JNIEnv *env, jclass cls, jint fd, jstring cmd, jobjectArray args)
21358 + jint arg_count, i;
21359 + size_t size;
21360 + jboolean isCopy;
21361 + door_arg_t door_args;
21362 + char res_buffer[128];
21363 + jint result = -1;
21364 + int rc;
21365 + const char* cstr;
21366 + char* buf;
21368 + /*
21369 + * First we get the command string and create the start of the
21370 + * argument string to send to the target VM:
21371 + * <ver>\0<cmd>\0
21372 + */
21373 + cstr = JNU_GetStringPlatformChars(env, cmd, &isCopy);
21374 + if (cstr == NULL) {
21375 + return -1; /* pending exception */
21377 + size = strlen(PROTOCOL_VERSION) + strlen(cstr) + 2;
21378 + buf = (char*)malloc(size);
21379 + if (buf != NULL) {
21380 + char* pos = buf;
21381 + strcpy(buf, PROTOCOL_VERSION);
21382 + pos += strlen(PROTOCOL_VERSION)+1;
21383 + strcpy(pos, cstr);
21385 + if (isCopy) {
21386 + JNU_ReleaseStringPlatformChars(env, cmd, cstr);
21388 + if (buf == NULL) {
21389 + JNU_ThrowOutOfMemoryError(env, "malloc failed");
21390 + return -1;
21393 + /*
21394 + * Next we iterate over the arguments and extend the buffer
21395 + * to include them.
21396 + */
21397 + arg_count = (*env)->GetArrayLength(env, args);
21399 + for (i = 0; i < arg_count; i++) {
21400 + jobject obj = (*env)->GetObjectArrayElement(env, args, i);
21401 + if (obj != NULL) {
21402 + cstr = JNU_GetStringPlatformChars(env, obj, &isCopy);
21403 + if (cstr != NULL) {
21404 + size_t len = strlen(cstr);
21405 + char* newbuf = (char*)realloc(buf, size+len+1);
21406 + if (newbuf != NULL) {
21407 + buf = newbuf;
21408 + strcpy(buf+size, cstr);
21409 + size += len+1;
21411 + if (isCopy) {
21412 + JNU_ReleaseStringPlatformChars(env, obj, cstr);
21414 + if (newbuf == NULL) {
21415 + free(buf);
21416 + JNU_ThrowOutOfMemoryError(env, "realloc failed");
21417 + return -1;
21420 + } else {
21421 + char* newbuf = (char*)realloc(buf, size + 1);
21422 + if (newbuf == NULL) {
21423 + free(buf);
21424 + JNU_ThrowOutOfMemoryError(env, "realloc failed");
21425 + return -1;
21427 + buf = newbuf;
21428 + buf[size++] = 0;
21430 + if ((*env)->ExceptionOccurred(env)) {
21431 + free(buf);
21432 + return -1;
21436 + /*
21437 + * The arguments to the door function are in 'buf' so we now
21438 + * do the door call
21439 + */
21440 + door_args.data_ptr = buf;
21441 + door_args.data_size = size;
21442 + door_args.desc_ptr = NULL;
21443 + door_args.desc_num = 0;
21444 + door_args.rbuf = (char*)&res_buffer;
21445 + door_args.rsize = sizeof(res_buffer);
21447 + RESTARTABLE(door_call(fd, &door_args), rc);
21449 + /*
21450 + * door_call failed
21451 + */
21452 + if (rc == -1) {
21453 + JNU_ThrowIOExceptionWithLastError(env, "door_call");
21454 + } else {
21455 + /*
21456 + * door_call succeeded but the call didn't return the expected jint.
21457 + */
21458 + if (door_args.data_size < sizeof(jint)) {
21459 + JNU_ThrowIOException(env, "Enqueue error - reason unknown as result is truncated!");
21460 + } else {
21461 + jint* res = (jint*)(door_args.data_ptr);
21462 + if (*res != JNI_OK) {
21463 + const char* msg = translate_error(*res);
21464 + char buf[255];
21465 + if (msg == NULL) {
21466 + sprintf(buf, "Unable to enqueue command to target VM: %d", *res);
21467 + } else {
21468 + sprintf(buf, "Unable to enqueue command to target VM: %s", msg);
21470 + JNU_ThrowIOException(env, buf);
21471 + } else {
21472 + /*
21473 + * The door call should return a file descriptor to one end of
21474 + * a socket pair
21475 + */
21476 + if ((door_args.desc_ptr != NULL) &&
21477 + (door_args.desc_num == 1) &&
21478 + (door_args.desc_ptr->d_attributes & DOOR_DESCRIPTOR)) {
21479 + result = door_args.desc_ptr->d_data.d_desc.d_descriptor;
21480 + } else {
21481 + JNU_ThrowIOException(env, "Reply from enqueue missing descriptor!");
21487 + free(buf);
21488 + return result;
21490 diff -Nru jdk23u-jdk-23-36.orig/src/jdk.charsets/share/classes/sun/nio/cs/ext/JISAutoDetect.java jdk23u-jdk-23-36/src/jdk.charsets/share/classes/sun/nio/cs/ext/JISAutoDetect.java
21491 --- jdk23u-jdk-23-36.orig/src/jdk.charsets/share/classes/sun/nio/cs/ext/JISAutoDetect.java 2024-08-07 00:08:22.000000000 +0200
21492 +++ jdk23u-jdk-23-36/src/jdk.charsets/share/classes/sun/nio/cs/ext/JISAutoDetect.java 2024-08-17 19:50:33.131473645 +0200
21493 @@ -95,7 +95,7 @@
21494 private static class Decoder extends CharsetDecoder {
21496 private static final String SJISName = getSJISName();
21497 - private static final String EUCJPName = "EUC_JP";
21498 + private static final String EUCJPName = getEUCJPName();
21499 private DelegatableDecoder detectedDecoder = null;
21501 public Decoder(Charset cs) {
21502 @@ -223,11 +223,24 @@
21503 * Returned Shift_JIS Charset name is OS dependent
21505 private static String getSJISName() {
21506 - if (OperatingSystem.isWindows())
21507 + if (OperatingSystem.isSolaris())
21508 + return("PCK");
21509 + else if (OperatingSystem.isWindows())
21510 return("windows-31J");
21511 else
21512 return("Shift_JIS");
21515 + /**
21516 + * Returned EUC-JP Charset name is OS dependent
21517 + */
21519 + private static String getEUCJPName() {
21520 + if (OperatingSystem.isSolaris())
21521 + return("x-eucjp-open");
21522 + else
21523 + return("EUC_JP");
21528 diff -Nru jdk23u-jdk-23-36.orig/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java jdk23u-jdk-23-36/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java
21529 --- jdk23u-jdk-23-36.orig/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java 2024-08-07 00:08:22.000000000 +0200
21530 +++ jdk23u-jdk-23-36/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java 2024-08-17 19:50:33.132178947 +0200
21531 @@ -720,10 +720,15 @@
21532 lib = expand(lib);
21533 int i = lib.indexOf("/$ISA/");
21534 if (i != -1) {
21535 - // replace "/$ISA/" with "/"
21536 + // replace "/$ISA/" with "/amd64/" on Solaris AMD64.
21537 + // On all other platforms, just turn it into a "/"
21538 String prefix = lib.substring(0, i);
21539 String suffix = lib.substring(i + 5);
21540 - lib = prefix + suffix;
21541 + if (osName.equals("SunOS") && osArch.equals("amd64")) {
21542 + lib = prefix + "/amd64" + suffix;
21543 + } else {
21544 + lib = prefix + suffix;
21547 if (DEBUG) {
21548 System.out.println(keyword + ": " + lib);
21549 diff -Nru jdk23u-jdk-23-36.orig/src/jdk.crypto.cryptoki/solaris/conf/security/sunpkcs11-solaris.cfg jdk23u-jdk-23-36/src/jdk.crypto.cryptoki/solaris/conf/security/sunpkcs11-solaris.cfg
21550 --- jdk23u-jdk-23-36.orig/src/jdk.crypto.cryptoki/solaris/conf/security/sunpkcs11-solaris.cfg 1970-01-01 01:00:00.000000000 +0100
21551 +++ jdk23u-jdk-23-36/src/jdk.crypto.cryptoki/solaris/conf/security/sunpkcs11-solaris.cfg 2024-08-17 19:50:33.166039839 +0200
21552 @@ -0,0 +1,23 @@
21554 +# Configuration file to allow the SunPKCS11 provider to utilize
21555 +# the Solaris Cryptographic Framework, if it is available
21558 +name = Solaris
21560 +description = SunPKCS11 accessing Solaris Cryptographic Framework
21562 +library = /usr/lib/$ISA/libpkcs11.so
21564 +handleStartupErrors = ignoreAll
21566 +# Use the X9.63 encoding for EC points (do not wrap in an ASN.1 OctetString).
21567 +useEcX963Encoding = true
21569 +attributes = compatibility
21571 +disabledMechanisms = {
21572 + CKM_DSA_KEY_PAIR_GEN
21573 + SecureRandom
21576 diff -Nru jdk23u-jdk-23-36.orig/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HotSpotSolarisVtblAccess.java jdk23u-jdk-23-36/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HotSpotSolarisVtblAccess.java
21577 --- jdk23u-jdk-23-36.orig/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HotSpotSolarisVtblAccess.java 1970-01-01 01:00:00.000000000 +0100
21578 +++ jdk23u-jdk-23-36/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HotSpotSolarisVtblAccess.java 2024-08-17 19:50:33.166288927 +0200
21579 @@ -0,0 +1,65 @@
21581 + * Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
21582 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
21584 + * This code is free software; you can redistribute it and/or modify it
21585 + * under the terms of the GNU General Public License version 2 only, as
21586 + * published by the Free Software Foundation.
21588 + * This code is distributed in the hope that it will be useful, but WITHOUT
21589 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21590 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21591 + * version 2 for more details (a copy is included in the LICENSE file that
21592 + * accompanied this code).
21594 + * You should have received a copy of the GNU General Public License version
21595 + * 2 along with this work; if not, write to the Free Software Foundation,
21596 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21598 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21599 + * or visit www.oracle.com if you need additional information or have any
21600 + * questions.
21602 + */
21604 +package sun.jvm.hotspot;
21606 +import java.util.*;
21607 +import sun.jvm.hotspot.debugger.*;
21608 +import sun.jvm.hotspot.types.*;
21609 +import sun.jvm.hotspot.types.basic.*;
21611 +/** This class implements the compiler-specific access to the vtbl for
21612 + a given C++ type. */
21613 +public class HotSpotSolarisVtblAccess extends BasicVtblAccess {
21615 + public HotSpotSolarisVtblAccess(SymbolLookup symbolLookup,
21616 + String[] jvmLibNames) {
21617 + super(symbolLookup, jvmLibNames);
21620 + protected String vtblSymbolForType(Type type) {
21621 + String demangledSymbol = type.getName() + "::__vtbl";
21622 + return mangle(demangledSymbol);
21625 + //--------------------------------------------------------------------------------
21626 + // Internals only below this point
21627 + //
21629 + private String mangle(String symbol) {
21630 + String[] parts = symbol.split("::");
21631 + StringBuffer mangled = new StringBuffer("__1c");
21632 + for (int i = 0; i < parts.length; i++) {
21633 + int len = parts[i].length();
21634 + if (len >= 26) {
21635 + mangled.append((char)('a' + (len / 26)));
21636 + len = len % 26;
21638 + mangled.append((char)('A' + len));
21639 + mangled.append(parts[i]);
21641 + mangled.append("_");
21642 + return mangled.toString();
21645 diff -Nru jdk23u-jdk-23-36.orig/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/solaris_amd64/SolarisAMD64JavaThreadPDAccess.java jdk23u-jdk-23-36/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/solaris_amd64/SolarisAMD64JavaThreadPDAccess.java
21646 --- jdk23u-jdk-23-36.orig/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/solaris_amd64/SolarisAMD64JavaThreadPDAccess.java 1970-01-01 01:00:00.000000000 +0100
21647 +++ jdk23u-jdk-23-36/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/solaris_amd64/SolarisAMD64JavaThreadPDAccess.java 2024-08-17 19:50:33.166652251 +0200
21648 @@ -0,0 +1,140 @@
21650 + * Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved.
21651 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
21653 + * This code is free software; you can redistribute it and/or modify it
21654 + * under the terms of the GNU General Public License version 2 only, as
21655 + * published by the Free Software Foundation.
21657 + * This code is distributed in the hope that it will be useful, but WITHOUT
21658 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21659 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21660 + * version 2 for more details (a copy is included in the LICENSE file that
21661 + * accompanied this code).
21663 + * You should have received a copy of the GNU General Public License version
21664 + * 2 along with this work; if not, write to the Free Software Foundation,
21665 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21667 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21668 + * or visit www.oracle.com if you need additional information or have any
21669 + * questions.
21671 + */
21673 +package sun.jvm.hotspot.runtime.solaris_amd64;
21675 +import java.io.*;
21676 +import java.util.*;
21677 +import sun.jvm.hotspot.debugger.*;
21678 +import sun.jvm.hotspot.debugger.amd64.*;
21679 +import sun.jvm.hotspot.runtime.*;
21680 +import sun.jvm.hotspot.runtime.amd64.*;
21681 +import sun.jvm.hotspot.runtime.x86.*;
21682 +import sun.jvm.hotspot.types.*;
21683 +import sun.jvm.hotspot.utilities.*;
21684 +import sun.jvm.hotspot.utilities.Observable;
21685 +import sun.jvm.hotspot.utilities.Observer;
21687 +public class SolarisAMD64JavaThreadPDAccess implements JavaThreadPDAccess {
21688 + private static AddressField lastJavaFPField;
21689 + private static AddressField osThreadField;
21690 + private static AddressField baseOfStackPointerField;
21692 + // Field from OSThread
21693 + private static CIntegerField osThreadThreadIDField;
21695 + // This is currently unneeded but is being kept in case we change
21696 + // the currentFrameGuess algorithm
21697 + private static final long GUESS_SCAN_RANGE = 128 * 1024;
21700 + static {
21701 + VM.registerVMInitializedObserver(new Observer() {
21702 + public void update(Observable o, Object data) {
21703 + initialize(VM.getVM().getTypeDataBase());
21705 + });
21708 + private static synchronized void initialize(TypeDataBase db) {
21709 + Type type = db.lookupType("JavaThread");
21710 + Type anchorType = db.lookupType("JavaFrameAnchor");
21712 + lastJavaFPField = anchorType.getAddressField("_last_Java_fp");
21713 + osThreadField = type.getAddressField("_osthread");
21715 + type = db.lookupType("OSThread");
21716 + osThreadThreadIDField = type.getCIntegerField("_thread_id");
21719 + public Address getLastJavaFP(Address addr) {
21720 + return lastJavaFPField.getValue(addr.addOffsetTo(sun.jvm.hotspot.runtime.JavaThread.getAnchorField().getOffset()));
21723 + public Address getLastJavaPC(Address addr) {
21724 + return null;
21727 + public Address getBaseOfStackPointer(Address addr) {
21728 + return null;
21731 + public Frame getLastFramePD(JavaThread thread, Address addr) {
21732 + Address fp = thread.getLastJavaFP();
21733 + if (fp == null) {
21734 + return null; // no information
21736 + Address pc = thread.getLastJavaPC();
21737 + if ( pc != null ) {
21738 + return new X86Frame(thread.getLastJavaSP(), fp, pc);
21739 + } else {
21740 + return new X86Frame(thread.getLastJavaSP(), fp);
21744 + public RegisterMap newRegisterMap(JavaThread thread, boolean updateMap) {
21745 + return new X86RegisterMap(thread, updateMap);
21748 + public Frame getCurrentFrameGuess(JavaThread thread, Address addr) {
21749 + ThreadProxy t = getThreadProxy(addr);
21750 + AMD64ThreadContext context = (AMD64ThreadContext) t.getContext();
21751 + AMD64CurrentFrameGuess guesser = new AMD64CurrentFrameGuess(context, thread);
21752 + if (!guesser.run(GUESS_SCAN_RANGE)) {
21753 + return null;
21755 + if (guesser.getPC() == null) {
21756 + return new X86Frame(guesser.getSP(), guesser.getFP());
21757 + } else {
21758 + return new X86Frame(guesser.getSP(), guesser.getFP(), guesser.getPC());
21763 + public void printThreadIDOn(Address addr, PrintStream tty) {
21764 + tty.print(getThreadProxy(addr));
21768 + public void printInfoOn(Address threadAddr, PrintStream tty) {
21771 + public Address getLastSP(Address addr) {
21772 + ThreadProxy t = getThreadProxy(addr);
21773 + AMD64ThreadContext context = (AMD64ThreadContext) t.getContext();
21774 + return context.getRegisterAsAddress(AMD64ThreadContext.RSP);
21777 + public ThreadProxy getThreadProxy(Address addr) {
21778 + // Fetch the OSThread (for now and for simplicity, not making a
21779 + // separate "OSThread" class in this package)
21780 + Address osThreadAddr = osThreadField.getValue(addr);
21781 + // Get the address of the thread ID from the OSThread
21782 + Address tidAddr = osThreadAddr.addOffsetTo(osThreadThreadIDField.getOffset());
21784 + JVMDebugger debugger = VM.getVM().getDebugger();
21785 + return debugger.getThreadForIdentifierAddress(tidAddr);
21789 diff -Nru jdk23u-jdk-23-36.orig/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/solaris_x86/SolarisX86JavaThreadPDAccess.java jdk23u-jdk-23-36/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/solaris_x86/SolarisX86JavaThreadPDAccess.java
21790 --- jdk23u-jdk-23-36.orig/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/solaris_x86/SolarisX86JavaThreadPDAccess.java 1970-01-01 01:00:00.000000000 +0100
21791 +++ jdk23u-jdk-23-36/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/solaris_x86/SolarisX86JavaThreadPDAccess.java 2024-08-17 19:50:33.167034425 +0200
21792 @@ -0,0 +1,142 @@
21794 + * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
21795 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
21797 + * This code is free software; you can redistribute it and/or modify it
21798 + * under the terms of the GNU General Public License version 2 only, as
21799 + * published by the Free Software Foundation.
21801 + * This code is distributed in the hope that it will be useful, but WITHOUT
21802 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21803 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21804 + * version 2 for more details (a copy is included in the LICENSE file that
21805 + * accompanied this code).
21807 + * You should have received a copy of the GNU General Public License version
21808 + * 2 along with this work; if not, write to the Free Software Foundation,
21809 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21811 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21812 + * or visit www.oracle.com if you need additional information or have any
21813 + * questions.
21815 + */
21817 +package sun.jvm.hotspot.runtime.solaris_x86;
21819 +import java.io.*;
21820 +import java.util.*;
21821 +import sun.jvm.hotspot.debugger.*;
21822 +import sun.jvm.hotspot.debugger.x86.*;
21823 +import sun.jvm.hotspot.runtime.*;
21824 +import sun.jvm.hotspot.runtime.x86.*;
21825 +import sun.jvm.hotspot.types.*;
21826 +import sun.jvm.hotspot.utilities.*;
21827 +import sun.jvm.hotspot.utilities.Observable;
21828 +import sun.jvm.hotspot.utilities.Observer;
21830 +/** Placeholder for now to allow us to start the SA without support
21831 + for stack traces */
21833 +public class SolarisX86JavaThreadPDAccess implements JavaThreadPDAccess {
21834 + private static AddressField lastJavaFPField;
21835 + private static AddressField osThreadField;
21836 + private static AddressField baseOfStackPointerField;
21838 + // Field from OSThread
21839 + private static CIntegerField osThreadThreadIDField;
21841 + // This is currently unneeded but is being kept in case we change
21842 + // the currentFrameGuess algorithm
21843 + private static final long GUESS_SCAN_RANGE = 128 * 1024;
21846 + static {
21847 + VM.registerVMInitializedObserver(new Observer() {
21848 + public void update(Observable o, Object data) {
21849 + initialize(VM.getVM().getTypeDataBase());
21851 + });
21854 + private static synchronized void initialize(TypeDataBase db) {
21855 + Type type = db.lookupType("JavaThread");
21856 + Type anchorType = db.lookupType("JavaFrameAnchor");
21858 + lastJavaFPField = anchorType.getAddressField("_last_Java_fp");
21859 + osThreadField = type.getAddressField("_osthread");
21861 + type = db.lookupType("OSThread");
21862 + osThreadThreadIDField = type.getCIntegerField("_thread_id");
21865 + public Address getLastJavaFP(Address addr) {
21866 + return lastJavaFPField.getValue(addr.addOffsetTo(sun.jvm.hotspot.runtime.JavaThread.getAnchorField().getOffset()));
21869 + public Address getLastJavaPC(Address addr) {
21870 + return null;
21873 + public Address getBaseOfStackPointer(Address addr) {
21874 + return null;
21877 + public Frame getLastFramePD(JavaThread thread, Address addr) {
21878 + Address fp = thread.getLastJavaFP();
21879 + if (fp == null) {
21880 + return null; // no information
21882 + Address pc = thread.getLastJavaPC();
21883 + if ( pc != null ) {
21884 + return new X86Frame(thread.getLastJavaSP(), fp, pc);
21885 + } else {
21886 + return new X86Frame(thread.getLastJavaSP(), fp);
21890 + public RegisterMap newRegisterMap(JavaThread thread, boolean updateMap) {
21891 + return new X86RegisterMap(thread, updateMap);
21894 + public Frame getCurrentFrameGuess(JavaThread thread, Address addr) {
21895 + ThreadProxy t = getThreadProxy(addr);
21896 + X86ThreadContext context = (X86ThreadContext) t.getContext();
21897 + X86CurrentFrameGuess guesser = new X86CurrentFrameGuess(context, thread);
21898 + if (!guesser.run(GUESS_SCAN_RANGE)) {
21899 + return null;
21901 + if (guesser.getPC() == null) {
21902 + return new X86Frame(guesser.getSP(), guesser.getFP());
21903 + } else {
21904 + return new X86Frame(guesser.getSP(), guesser.getFP(), guesser.getPC());
21909 + public void printThreadIDOn(Address addr, PrintStream tty) {
21910 + tty.print(getThreadProxy(addr));
21914 + public void printInfoOn(Address threadAddr, PrintStream tty) {
21917 + public Address getLastSP(Address addr) {
21918 + ThreadProxy t = getThreadProxy(addr);
21919 + X86ThreadContext context = (X86ThreadContext) t.getContext();
21920 + return context.getRegisterAsAddress(X86ThreadContext.ESP);
21923 + public ThreadProxy getThreadProxy(Address addr) {
21924 + // Fetch the OSThread (for now and for simplicity, not making a
21925 + // separate "OSThread" class in this package)
21926 + Address osThreadAddr = osThreadField.getValue(addr);
21927 + // Get the address of the thread ID from the OSThread
21928 + Address tidAddr = osThreadAddr.addOffsetTo(osThreadThreadIDField.getOffset());
21930 + JVMDebugger debugger = VM.getVM().getDebugger();
21931 + return debugger.getThreadForIdentifierAddress(tidAddr);
21935 diff -Nru jdk23u-jdk-23-36.orig/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java jdk23u-jdk-23-36/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java
21936 --- jdk23u-jdk-23-36.orig/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java 2024-08-07 00:08:22.000000000 +0200
21937 +++ jdk23u-jdk-23-36/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java 2024-08-17 19:50:33.132870142 +0200
21938 @@ -28,6 +28,8 @@
21940 import sun.jvm.hotspot.debugger.*;
21941 import sun.jvm.hotspot.types.*;
21942 +import sun.jvm.hotspot.runtime.solaris_x86.SolarisX86JavaThreadPDAccess;
21943 +import sun.jvm.hotspot.runtime.solaris_amd64.SolarisAMD64JavaThreadPDAccess;
21944 import sun.jvm.hotspot.runtime.win32_x86.Win32X86JavaThreadPDAccess;
21945 import sun.jvm.hotspot.runtime.win32_amd64.Win32AMD64JavaThreadPDAccess;
21946 import sun.jvm.hotspot.runtime.win32_aarch64.Win32AARCH64JavaThreadPDAccess;
21947 @@ -97,7 +99,13 @@
21949 access = null;
21950 // FIXME: find the platform specific PD class by reflection?
21951 - if (os.equals("win32")) {
21952 + if (os.equals("solaris")) {
21953 + if (cpu.equals("x86")) {
21954 + access = new SolarisX86JavaThreadPDAccess();
21955 + } else if (cpu.equals("amd64")) {
21956 + access = new SolarisAMD64JavaThreadPDAccess();
21958 + } else if (os.equals("win32")) {
21959 if (cpu.equals("x86")) {
21960 access = new Win32X86JavaThreadPDAccess();
21961 } else if (cpu.equals("amd64")) {
21962 diff -Nru jdk23u-jdk-23-36.orig/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java jdk23u-jdk-23-36/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java
21963 --- jdk23u-jdk-23-36.orig/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java 2024-08-07 00:08:22.000000000 +0200
21964 +++ jdk23u-jdk-23-36/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java 2024-08-17 19:50:33.133301067 +0200
21965 @@ -28,10 +28,14 @@
21966 system. */
21968 public class PlatformInfo {
21969 - /* Returns "win32" if Windows; "linux" if Linux. */
21970 + /* Returns "solaris" if on Solaris; "win32" if Windows; "linux" if
21971 + Linux. Used to determine location of dbx and import module, or
21972 + possible debugger agent on win32. */
21973 public static String getOS() throws UnsupportedPlatformException {
21974 String os = System.getProperty("os.name");
21975 - if (os.equals("Linux")) {
21976 + if (os.equals("SunOS")) {
21977 + return "solaris";
21978 + } else if (os.equals("Linux")) {
21979 return "linux";
21980 } else if (os.equals("FreeBSD")) {
21981 return "bsd";
21982 diff -Nru jdk23u-jdk-23-36.orig/src/jdk.hotspot.agent/share/native/libsaproc/ps_core_common.c jdk23u-jdk-23-36/src/jdk.hotspot.agent/share/native/libsaproc/ps_core_common.c
21983 --- jdk23u-jdk-23-36.orig/src/jdk.hotspot.agent/share/native/libsaproc/ps_core_common.c 2024-08-07 00:08:22.000000000 +0200
21984 +++ jdk23u-jdk-23-36/src/jdk.hotspot.agent/share/native/libsaproc/ps_core_common.c 2024-08-17 19:50:33.133783422 +0200
21985 @@ -22,6 +22,8 @@
21989 +#include <jni.h> // just include something, or else solaris compiler will complain that this file is empty
21991 #if defined(LINUX) || defined(__APPLE__)
21992 #include <unistd.h>
21993 #include <fcntl.h>
21994 diff -Nru jdk23u-jdk-23-36.orig/src/jdk.hotspot.agent/test/libproc/libproctest.sh jdk23u-jdk-23-36/src/jdk.hotspot.agent/test/libproc/libproctest.sh
21995 --- jdk23u-jdk-23-36.orig/src/jdk.hotspot.agent/test/libproc/libproctest.sh 2024-08-07 00:08:22.000000000 +0200
21996 +++ jdk23u-jdk-23-36/src/jdk.hotspot.agent/test/libproc/libproctest.sh 2024-08-17 19:50:33.134195002 +0200
21997 @@ -59,8 +59,10 @@
21998 kill -9 $pid
22001 +OPTIONS="-Djava.library.path=$STARTDIR/../src/os/solaris/proc/`uname -p`:$STARTDIR/../solaris/`uname -p`"
22003 # run libproc client
22004 -$SA_JAVA -showversion -cp $STARTDIR/../../build/classes::$STARTDIR/../sa.jar:$STARTDIR LibprocClient x core.$pid
22005 +$SA_JAVA -showversion ${OPTIONS} -cp $STARTDIR/../../build/classes::$STARTDIR/../sa.jar:$STARTDIR LibprocClient x core.$pid
22007 # delete core
22008 rm -f core.$pid
22009 diff -Nru jdk23u-jdk-23-36.orig/src/jdk.jdwp.agent/unix/native/libdt_socket/socket_md.c jdk23u-jdk-23-36/src/jdk.jdwp.agent/unix/native/libdt_socket/socket_md.c
22010 --- jdk23u-jdk-23-36.orig/src/jdk.jdwp.agent/unix/native/libdt_socket/socket_md.c 2024-08-07 00:08:22.000000000 +0200
22011 +++ jdk23u-jdk-23-36/src/jdk.jdwp.agent/unix/native/libdt_socket/socket_md.c 2024-08-17 19:50:33.134787646 +0200
22012 @@ -33,8 +33,12 @@
22013 #include <errno.h>
22014 #include <string.h>
22015 #include <sys/time.h>
22016 +#ifdef __solaris__
22017 +#include <thread.h>
22018 +#else
22019 #include <pthread.h>
22020 #include <poll.h>
22021 +#endif
22023 #include "socket_md.h"
22024 #include "sysSocket.h"
22025 @@ -271,6 +275,35 @@
22026 return 0;
22029 +#ifdef __solaris__
22030 +int
22031 +dbgsysTlsAlloc() {
22032 + thread_key_t tk;
22033 + if (thr_keycreate(&tk, NULL)) {
22034 + perror("thr_keycreate");
22035 + exit(-1);
22037 + return (int)tk;
22040 +void
22041 +dbgsysTlsFree(int index) {
22042 + /* no-op */
22045 +void
22046 +dbgsysTlsPut(int index, void *value) {
22047 + thr_setspecific((thread_key_t)index, value) ;
22050 +void *
22051 +dbgsysTlsGet(int index) {
22052 + void* r = NULL;
22053 + thr_getspecific((thread_key_t)index, &r);
22054 + return r;
22057 +#else
22059 dbgsysTlsAlloc() {
22060 pthread_key_t key;
22061 @@ -296,6 +329,8 @@
22062 return pthread_getspecific((pthread_key_t)index);
22065 +#endif
22067 long
22068 dbgsysCurrentTimeMillis() {
22069 struct timeval t;
22070 diff -Nru jdk23u-jdk-23-36.orig/src/jdk.management/solaris/native/libmanagement_ext/UnixOperatingSystem.c jdk23u-jdk-23-36/src/jdk.management/solaris/native/libmanagement_ext/UnixOperatingSystem.c
22071 --- jdk23u-jdk-23-36.orig/src/jdk.management/solaris/native/libmanagement_ext/UnixOperatingSystem.c 1970-01-01 01:00:00.000000000 +0100
22072 +++ jdk23u-jdk-23-36/src/jdk.management/solaris/native/libmanagement_ext/UnixOperatingSystem.c 2024-08-17 19:50:33.167504749 +0200
22073 @@ -0,0 +1,254 @@
22075 + * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
22076 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
22078 + * This code is free software; you can redistribute it and/or modify it
22079 + * under the terms of the GNU General Public License version 2 only, as
22080 + * published by the Free Software Foundation. Oracle designates this
22081 + * particular file as subject to the "Classpath" exception as provided
22082 + * by Oracle in the LICENSE file that accompanied this code.
22084 + * This code is distributed in the hope that it will be useful, but WITHOUT
22085 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
22086 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22087 + * version 2 for more details (a copy is included in the LICENSE file that
22088 + * accompanied this code).
22090 + * You should have received a copy of the GNU General Public License version
22091 + * 2 along with this work; if not, write to the Free Software Foundation,
22092 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
22094 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22095 + * or visit www.oracle.com if you need additional information or have any
22096 + * questions.
22097 + */
22099 +#include <fcntl.h>
22100 +#include <kstat.h>
22101 +#include <procfs.h>
22102 +#include <unistd.h>
22103 +#include <stdlib.h>
22104 +#include <stdio.h>
22105 +#include <string.h>
22106 +#include <sys/sysinfo.h>
22107 +#include <sys/lwp.h>
22108 +#include <pthread.h>
22109 +#include <utmpx.h>
22110 +#include <dlfcn.h>
22111 +#include <sys/loadavg.h>
22112 +#include <jni.h>
22113 +#include "jvm.h"
22114 +#include "com_sun_management_internal_OperatingSystemImpl.h"
22116 +typedef struct {
22117 + kstat_t *kstat;
22118 + uint64_t last_idle;
22119 + uint64_t last_total;
22120 + double last_ratio;
22121 +} cpuload_t;
22123 +static cpuload_t *cpu_loads = NULL;
22124 +static unsigned int num_cpus;
22125 +static kstat_ctl_t *kstat_ctrl = NULL;
22127 +static void map_cpu_kstat_counters() {
22128 + kstat_t *kstat;
22129 + int i;
22131 + // Get number of CPU(s)
22132 + if ((num_cpus = sysconf(_SC_NPROCESSORS_ONLN)) == -1) {
22133 + num_cpus = 1;
22136 + // Data structure for saving CPU load
22137 + if ((cpu_loads = calloc(num_cpus,sizeof(cpuload_t))) == NULL) {
22138 + return;
22141 + // Get kstat cpu_stat counters for every CPU
22142 + // (loop over kstat to find our cpu_stat(s)
22143 + i = 0;
22144 + for (kstat = kstat_ctrl->kc_chain; kstat != NULL; kstat = kstat->ks_next) {
22145 + if (strncmp(kstat->ks_module, "cpu_stat", 8) == 0) {
22147 + if (kstat_read(kstat_ctrl, kstat, NULL) == -1) {
22148 + // Failed to initialize kstat for this CPU so ignore it
22149 + continue;
22152 + if (i == num_cpus) {
22153 + // Found more cpu_stats than reported CPUs
22154 + break;
22157 + cpu_loads[i++].kstat = kstat;
22162 +static int init_cpu_kstat_counters() {
22163 + static int initialized = 0;
22165 + // Concurrence in this method is prevented by the lock in
22166 + // the calling method get_cpu_load();
22167 + if(!initialized) {
22168 + if ((kstat_ctrl = kstat_open()) != NULL) {
22169 + map_cpu_kstat_counters();
22170 + initialized = 1;
22173 + return initialized ? 0 : -1;
22176 +static void update_cpu_kstat_counters() {
22177 + if(kstat_chain_update(kstat_ctrl) != 0) {
22178 + free(cpu_loads);
22179 + map_cpu_kstat_counters();
22183 +int read_cpustat(cpuload_t *load, cpu_stat_t *cpu_stat) {
22184 + if (load->kstat == NULL) {
22185 + // no handle.
22186 + return -1;
22188 + if (kstat_read(kstat_ctrl, load->kstat, cpu_stat) == -1) {
22189 + // disabling for now, a kstat chain update is likely to happen next time
22190 + load->kstat = NULL;
22191 + return -1;
22193 + return 0;
22196 +double get_single_cpu_load(unsigned int n) {
22197 + cpuload_t *load;
22198 + cpu_stat_t cpu_stat;
22199 + uint_t *usage;
22200 + uint64_t c_idle;
22201 + uint64_t c_total;
22202 + uint64_t d_idle;
22203 + uint64_t d_total;
22204 + int i;
22206 + if (n >= num_cpus) {
22207 + return -1.0;
22210 + load = &cpu_loads[n];
22211 + if (read_cpustat(load, &cpu_stat) < 0) {
22212 + return -1.0;
22215 + usage = cpu_stat.cpu_sysinfo.cpu;
22216 + c_idle = usage[CPU_IDLE];
22218 + for (c_total = 0, i = 0; i < CPU_STATES; i++) {
22219 + c_total += usage[i];
22222 + // Calculate diff against previous snapshot
22223 + d_idle = c_idle - load->last_idle;
22224 + d_total = c_total - load->last_total;
22226 + /** update if weve moved */
22227 + if (d_total > 0) {
22228 + // Save current values for next time around
22229 + load->last_idle = c_idle;
22230 + load->last_total = c_total;
22231 + load->last_ratio = (double) (d_total - d_idle) / d_total;
22234 + return load->last_ratio;
22237 +int get_info(const char *path, void *info, size_t s, off_t o) {
22238 + int fd;
22239 + int ret = 0;
22240 + if ((fd = open(path, O_RDONLY)) < 0) {
22241 + return -1;
22243 + if (pread(fd, info, s, o) != s) {
22244 + ret = -1;
22246 + close(fd);
22247 + return ret;
22250 +#define MIN(a, b) ((a < b) ? a : b)
22252 +static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
22254 +/**
22255 + * Return the cpu load (0-1) for proc number 'which' (or average all if which == -1)
22256 + */
22257 +double get_cpu_load(int which) {
22258 + double load =.0;
22260 + pthread_mutex_lock(&lock);
22261 + if(init_cpu_kstat_counters()==0) {
22263 + update_cpu_kstat_counters();
22265 + if (which == -1) {
22266 + unsigned int i;
22267 + double t;
22269 + for (t = .0, i = 0; i < num_cpus; i++) {
22270 + t += get_single_cpu_load(i);
22273 + // Cap total systemload to 1.0
22274 + load = MIN((t / num_cpus), 1.0);
22275 + } else {
22276 + load = MIN(get_single_cpu_load(which), 1.0);
22278 + } else {
22279 + load = -1.0;
22281 + pthread_mutex_unlock(&lock);
22283 + return load;
22286 +/**
22287 + * Return the cpu load (0-1) for the current process (i.e the JVM)
22288 + * or -1.0 if the get_info() call failed
22289 + */
22290 +double get_process_load(void) {
22291 + psinfo_t info;
22293 + // Get the percentage of "recent cpu usage" from all the lwp:s in the JVM:s
22294 + // process. This is returned as a value between 0.0 and 1.0 multiplied by 0x8000.
22295 + if (get_info("/proc/self/psinfo",&info.pr_pctcpu, sizeof(info.pr_pctcpu), offsetof(psinfo_t, pr_pctcpu)) == 0) {
22296 + return (double) info.pr_pctcpu / 0x8000;
22298 + return -1.0;
22301 +JNIEXPORT jdouble JNICALL
22302 +Java_com_sun_management_internal_OperatingSystemImpl_getCpuLoad0
22303 +(JNIEnv *env, jobject dummy)
22305 + return get_cpu_load(-1);
22308 +JNIEXPORT jdouble JNICALL
22309 +Java_com_sun_management_internal_OperatingSystemImpl_getProcessCpuLoad0
22310 +(JNIEnv *env, jobject dummy)
22312 + return get_process_load();
22315 +JNIEXPORT jdouble JNICALL
22316 +Java_com_sun_management_internal_OperatingSystemImpl_getSingleCpuLoad0
22317 +(JNIEnv *env, jobject mbean, jint cpu_number)
22319 + return -1.0;
22322 +JNIEXPORT jint JNICALL
22323 +Java_com_sun_management_internal_OperatingSystemImpl_getHostConfiguredCpuCount0
22324 +(JNIEnv *env, jobject mbean)
22326 + return -1;
22328 diff -Nru jdk23u-jdk-23-36.orig/src/jdk.management/unix/native/libmanagement_ext/OperatingSystemImpl.c jdk23u-jdk-23-36/src/jdk.management/unix/native/libmanagement_ext/OperatingSystemImpl.c
22329 --- jdk23u-jdk-23-36.orig/src/jdk.management/unix/native/libmanagement_ext/OperatingSystemImpl.c 2024-08-07 00:08:22.000000000 +0200
22330 +++ jdk23u-jdk-23-36/src/jdk.management/unix/native/libmanagement_ext/OperatingSystemImpl.c 2024-08-17 19:50:33.135377981 +0200
22331 @@ -77,7 +77,63 @@
22332 // true = get available swap in bytes
22333 // false = get total swap in bytes
22334 static jlong get_total_or_available_swap_space_size(JNIEnv* env, jboolean available) {
22335 -#if defined(__linux__)
22336 +#ifdef __solaris__
22337 + long total, avail;
22338 + int nswap, i, count;
22339 + swaptbl_t *stbl;
22340 + char *strtab;
22342 + // First get the number of swap resource entries
22343 + if ((nswap = swapctl(SC_GETNSWP, NULL)) == -1) {
22344 + throw_internal_error(env, "swapctl failed to get nswap");
22345 + return -1;
22347 + if (nswap == 0) {
22348 + return 0;
22351 + // Allocate storage for resource entries
22352 + stbl = (swaptbl_t*) malloc(nswap * sizeof(swapent_t) +
22353 + sizeof(struct swaptable));
22354 + if (stbl == NULL) {
22355 + JNU_ThrowOutOfMemoryError(env, 0);
22356 + return -1;
22359 + // Allocate storage for the table
22360 + strtab = (char*) malloc((nswap + 1) * MAXPATHLEN);
22361 + if (strtab == NULL) {
22362 + free(stbl);
22363 + JNU_ThrowOutOfMemoryError(env, 0);
22364 + return -1;
22367 + for (i = 0; i < (nswap + 1); i++) {
22368 + stbl->swt_ent[i].ste_path = strtab + (i * MAXPATHLEN);
22370 + stbl->swt_n = nswap + 1;
22372 + // Get the entries
22373 + if ((count = swapctl(SC_LIST, stbl)) < 0) {
22374 + free(stbl);
22375 + free(strtab);
22376 + throw_internal_error(env, "swapctl failed to get swap list");
22377 + return -1;
22380 + // Sum the entries to get total and free swap
22381 + total = 0;
22382 + avail = 0;
22383 + for (i = 0; i < count; i++) {
22384 + total += stbl->swt_ent[i].ste_pages;
22385 + avail += stbl->swt_ent[i].ste_free;
22388 + free(stbl);
22389 + free(strtab);
22390 + return available ? ((jlong)avail * page_size) :
22391 + ((jlong)total * page_size);
22392 +#elif defined(__linux__)
22393 int ret;
22394 jlong total = 0, avail = 0;
22396 @@ -126,7 +182,37 @@
22397 Java_com_sun_management_internal_OperatingSystemImpl_getCommittedVirtualMemorySize0
22398 (JNIEnv *env, jobject mbean)
22400 -#if defined(__APPLE__)
22401 +#ifdef __solaris__
22402 + psinfo_t psinfo;
22403 + ssize_t result;
22404 + size_t remaining;
22405 + char* addr;
22406 + int fd;
22408 + fd = open64("/proc/self/psinfo", O_RDONLY, 0);
22409 + if (fd < 0) {
22410 + throw_internal_error(env, "Unable to open /proc/self/psinfo");
22411 + return -1;
22414 + addr = (char *)&psinfo;
22415 + for (remaining = sizeof(psinfo_t); remaining > 0;) {
22416 + result = read(fd, addr, remaining);
22417 + if (result < 0) {
22418 + if (errno != EINTR) {
22419 + close(fd);
22420 + throw_internal_error(env, "Unable to read /proc/self/psinfo");
22421 + return -1;
22423 + } else {
22424 + remaining -= result;
22425 + addr += result;
22429 + close(fd);
22430 + return (jlong) psinfo.pr_size * 1024;
22431 +#elif defined(__APPLE__)
22432 struct task_basic_info t_info;
22433 mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;
22435 @@ -182,7 +268,7 @@
22436 * BSDNOTE: FreeBSD implements _SC_CLK_TCK since FreeBSD 5, so
22437 * add a magic to handle it
22439 -#if defined(_SC_CLK_TCK)
22440 +#if defined(__solaris__) || defined(_SC_CLK_TCK)
22441 clk_tck = (jlong) sysconf(_SC_CLK_TCK);
22442 #elif defined(__linux__) || defined(_ALLBSD_SOURCE)
22443 clk_tck = 100;
22444 diff -Nru jdk23u-jdk-23-36.orig/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpNet.java jdk23u-jdk-23-36/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpNet.java
22445 --- jdk23u-jdk-23-36.orig/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpNet.java 2024-08-07 00:08:22.000000000 +0200
22446 +++ jdk23u-jdk-23-36/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpNet.java 2024-08-17 19:50:33.135937459 +0200
22447 @@ -44,6 +44,12 @@
22448 /* -- Miscellaneous SCTP utilities -- */
22450 private static boolean IPv4MappedAddresses() {
22451 + if (true) {
22452 + /* FIXME - nonportable hack */
22453 + /* Solaris supports IPv4Mapped Addresses with bindx */
22454 + return true;
22455 + } /* else { //other OS/implementations */
22457 /* lksctp/linux requires Ipv4 addresses */
22458 return false;
22460 diff -Nru jdk23u-jdk-23-36.orig/src/jdk.sctp/unix/native/libsctp/Sctp.h jdk23u-jdk-23-36/src/jdk.sctp/unix/native/libsctp/Sctp.h
22461 --- jdk23u-jdk-23-36.orig/src/jdk.sctp/unix/native/libsctp/Sctp.h 2024-08-07 00:08:22.000000000 +0200
22462 +++ jdk23u-jdk-23-36/src/jdk.sctp/unix/native/libsctp/Sctp.h 2024-08-17 19:50:33.136429996 +0200
22463 @@ -26,6 +26,48 @@
22464 #ifndef SUN_NIO_CH_SCTP_H
22465 #define SUN_NIO_CH_SCTP_H
22467 +#ifdef __solaris__
22469 +#define _XPG4_2
22470 +#define __EXTENSIONS__
22471 +#include <sys/socket.h>
22472 +#include <netinet/sctp.h>
22473 +#include "jni.h"
22475 +/* Current Solaris headers don't comply with draft rfc */
22476 +#ifndef SCTP_EOF
22477 +#define SCTP_EOF MSG_EOF
22478 +#endif
22480 +#ifndef SCTP_UNORDERED
22481 +#define SCTP_UNORDERED MSG_UNORDERED
22482 +#endif
22484 +/* The current version of the socket API extension shipped with Solaris does
22485 + * not define the following options that the Java API (optionally) supports */
22486 +#ifndef SCTP_EXPLICIT_EOR
22487 +#define SCTP_EXPLICIT_EOR -1
22488 +#endif
22489 +#ifndef SCTP_FRAGMENT_INTERLEAVE
22490 +#define SCTP_FRAGMENT_INTERLEAVE -1
22491 +#endif
22492 +#ifndef SCTP_SET_PEER_PRIMARY_ADDR
22493 +#define SCTP_SET_PEER_PRIMARY_ADDR -1
22494 +#endif
22496 +/* Function types to support dynamic linking of socket API extension functions
22497 + * for SCTP. This is so that there is no linkage depandancy during build or
22498 + * runtime for libsctp.*/
22499 +typedef int sctp_getladdrs_func(int sock, sctp_assoc_t id, void **addrs);
22500 +typedef int sctp_freeladdrs_func(void* addrs);
22501 +typedef int sctp_getpaddrs_func(int sock, sctp_assoc_t id, void **addrs);
22502 +typedef int sctp_freepaddrs_func(void *addrs);
22503 +typedef int sctp_bindx_func(int sock, void *addrs, int addrcnt, int flags);
22504 +typedef int sctp_peeloff_func(int sock, sctp_assoc_t id);
22508 +#else /* __linux__ */
22509 #include <stdint.h>
22510 #include <linux/types.h>
22511 #include <sys/socket.h>
22512 @@ -278,6 +320,8 @@
22513 typedef int sctp_peeloff_func(int sock, sctp_assoc_t id);
22516 +#endif /* __linux__ */
22518 extern sctp_getladdrs_func* nio_sctp_getladdrs;
22519 extern sctp_freeladdrs_func* nio_sctp_freeladdrs;
22520 extern sctp_getpaddrs_func* nio_sctp_getpaddrs;
22521 diff -Nru jdk23u-jdk-23-36.orig/src/jdk.sctp/unix/native/libsctp/SctpChannelImpl.c jdk23u-jdk-23-36/src/jdk.sctp/unix/native/libsctp/SctpChannelImpl.c
22522 --- jdk23u-jdk-23-36.orig/src/jdk.sctp/unix/native/libsctp/SctpChannelImpl.c 2024-08-07 00:08:22.000000000 +0200
22523 +++ jdk23u-jdk-23-36/src/jdk.sctp/unix/native/libsctp/SctpChannelImpl.c 2024-08-17 19:50:33.136853149 +0200
22524 @@ -331,11 +331,10 @@
22525 break;
22526 case SCTP_ADDR_MADE_PRIM :
22527 event = sun_nio_ch_sctp_PeerAddrChange_SCTP_ADDR_MADE_PRIM;
22528 +#ifdef __linux__ /* Solaris currently doesn't support SCTP_ADDR_CONFIRMED */
22529 break;
22530 -#ifdef __linux__
22531 case SCTP_ADDR_CONFIRMED :
22532 event = sun_nio_ch_sctp_PeerAddrChange_SCTP_ADDR_CONFIRMED;
22533 - break;
22534 #endif /* __linux__ */
22537 diff -Nru jdk23u-jdk-23-36.orig/src/jdk.sctp/unix/native/libsctp/SctpNet.c jdk23u-jdk-23-36/src/jdk.sctp/unix/native/libsctp/SctpNet.c
22538 --- jdk23u-jdk-23-36.orig/src/jdk.sctp/unix/native/libsctp/SctpNet.c 2024-08-07 00:08:22.000000000 +0200
22539 +++ jdk23u-jdk-23-36/src/jdk.sctp/unix/native/libsctp/SctpNet.c 2024-08-17 19:50:33.137324354 +0200
22540 @@ -371,7 +371,11 @@
22541 int i, addrCount;
22542 jobjectArray isaa;
22544 +#ifdef __solaris__
22545 + if ((addrCount = nio_sctp_getladdrs(fd, 0, (void **)&addr_buf)) == -1) {
22546 +#else /* __linux__ */
22547 if ((addrCount = nio_sctp_getladdrs(fd, 0, (struct sockaddr **)&addr_buf)) == -1) {
22548 +#endif
22549 sctpHandleSocketError(env, errno);
22550 return NULL;
22552 @@ -416,7 +420,11 @@
22553 int i, addrCount;
22554 jobjectArray isaa;
22556 +#if defined(__solaris__)
22557 + if ((addrCount = nio_sctp_getpaddrs(fd, id, (void **)&addr_buf)) == -1) {
22558 +#else /* __linux__ */
22559 if ((addrCount = nio_sctp_getpaddrs(fd, id, (struct sockaddr **)&addr_buf)) == -1) {
22560 +#endif
22561 sctpHandleSocketError(env, errno);
22562 return NULL;
22564 diff -Nru jdk23u-jdk-23-36.orig/src/jdk.security.auth/unix/native/libjaas/Unix.c jdk23u-jdk-23-36/src/jdk.security.auth/unix/native/libjaas/Unix.c
22565 --- jdk23u-jdk-23-36.orig/src/jdk.security.auth/unix/native/libjaas/Unix.c 2024-08-07 00:08:22.000000000 +0200
22566 +++ jdk23u-jdk-23-36/src/jdk.security.auth/unix/native/libjaas/Unix.c 2024-08-17 19:50:33.137801899 +0200
22567 @@ -32,6 +32,10 @@
22568 #include <stdlib.h>
22569 #include <string.h>
22571 +/* For POSIX-compliant getpwuid_r on Solaris */
22572 +#if defined(__solaris__)
22573 +#define _POSIX_PTHREAD_SEMANTICS
22574 +#endif
22575 #include <pwd.h>