rust/cargo-c: update to 0.10.7+cargo-0.84.0
[oi-userland.git] / components / runtime / openjdk-22 / patches / 1_java-solaris-sparc.patch
blobba54367a664f416acd4080f0f39e79f93f64f498
1 diff -Nru jdk22u-jdk-22.0.2-ga.orig/bin/unshuffle_list.txt jdk22u-jdk-22.0.2-ga/bin/unshuffle_list.txt
2 --- jdk22u-jdk-22.0.2-ga.orig/bin/unshuffle_list.txt 2024-06-04 18:47:50.000000000 +0200
3 +++ jdk22u-jdk-22.0.2-ga/bin/unshuffle_list.txt 2024-08-17 19:34:03.827106654 +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 jdk22u-jdk-22.0.2-ga.orig/make/autoconf/basic_tools.m4 jdk22u-jdk-22.0.2-ga/make/autoconf/basic_tools.m4
29 --- jdk22u-jdk-22.0.2-ga.orig/make/autoconf/basic_tools.m4 2024-06-04 18:47:50.000000000 +0200
30 +++ jdk22u-jdk-22.0.2-ga/make/autoconf/basic_tools.m4 2024-08-17 19:34:03.828581195 +0200
31 @@ -289,6 +289,8 @@
32 TAR_TYPE="bsd"
33 elif test "x$($TAR --version | $GREP "busybox")" != "x"; then
34 TAR_TYPE="busybox"
35 + elif test "x$OPENJDK_BUILD_OS" = "xsolaris"; then
36 + TAR_TYPE="solaris"
37 elif test "x$OPENJDK_BUILD_OS" = "xaix"; then
38 TAR_TYPE="aix"
40 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/autoconf/build-aux/config.guess jdk22u-jdk-22.0.2-ga/make/autoconf/build-aux/config.guess
41 --- jdk22u-jdk-22.0.2-ga.orig/make/autoconf/build-aux/config.guess 2024-06-04 18:47:50.000000000 +0200
42 +++ jdk22u-jdk-22.0.2-ga/make/autoconf/build-aux/config.guess 2024-08-17 19:34:03.828943220 +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 jdk22u-jdk-22.0.2-ga.orig/make/autoconf/build-performance.m4 jdk22u-jdk-22.0.2-ga/make/autoconf/build-performance.m4
59 --- jdk22u-jdk-22.0.2-ga.orig/make/autoconf/build-performance.m4 2024-06-04 18:47:50.000000000 +0200
60 +++ jdk22u-jdk-22.0.2-ga/make/autoconf/build-performance.m4 2024-08-17 19:34:03.829416806 +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 jdk22u-jdk-22.0.2-ga.orig/make/autoconf/flags-cflags.m4 jdk22u-jdk-22.0.2-ga/make/autoconf/flags-cflags.m4
81 --- jdk22u-jdk-22.0.2-ga.orig/make/autoconf/flags-cflags.m4 2024-06-04 18:47:50.000000000 +0200
82 +++ jdk22u-jdk-22.0.2-ga/make/autoconf/flags-cflags.m4 2024-08-17 19:34:03.830026551 +0200
83 @@ -433,6 +433,9 @@
84 if test "x$OPENJDK_TARGET_OS" = xlinux; then
85 CFLAGS_OS_DEF_JVM="-DLINUX -D_FILE_OFFSET_BITS=64"
86 CFLAGS_OS_DEF_JDK="-D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE"
87 + elif test "x$OPENJDK_TARGET_OS" = xsolaris; then
88 + CFLAGS_OS_DEF_JVM="-DSOLARIS"
89 + CFLAGS_OS_DEF_JDK="-D__solaris__"
90 elif test "x$OPENJDK_TARGET_OS" = xmacosx; then
91 CFLAGS_OS_DEF_JVM="-D_ALLBSD_SOURCE -D_DARWIN_C_SOURCE -D_XOPEN_SOURCE"
92 CFLAGS_OS_DEF_JDK="-D_ALLBSD_SOURCE -D_DARWIN_UNLIMITED_SELECT"
93 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/autoconf/jdk-options.m4 jdk22u-jdk-22.0.2-ga/make/autoconf/jdk-options.m4
94 --- jdk22u-jdk-22.0.2-ga.orig/make/autoconf/jdk-options.m4 2024-06-04 18:47:50.000000000 +0200
95 +++ jdk22u-jdk-22.0.2-ga/make/autoconf/jdk-options.m4 2024-08-17 19:34:03.830557733 +0200
96 @@ -285,7 +285,7 @@
97 ZIP_EXTERNAL_DEBUG_SYMBOLS=false
98 elif test "x$with_native_debug_symbols" = xexternal; then
100 - if test "x$OPENJDK_TARGET_OS" = xlinux; then
101 + if test "x$OPENJDK_TARGET_OS" = xsolaris || test "x$OPENJDK_TARGET_OS" = xlinux; then
102 if test "x$OBJCOPY" = x; then
103 # enabling of enable-debug-symbols and can't find objcopy
104 # this is an error
105 @@ -298,7 +298,7 @@
106 ZIP_EXTERNAL_DEBUG_SYMBOLS=false
107 elif test "x$with_native_debug_symbols" = xzipped; then
109 - if test "x$OPENJDK_TARGET_OS" = xlinux; then
110 + if test "x$OPENJDK_TARGET_OS" = xsolaris || test "x$OPENJDK_TARGET_OS" = xlinux; then
111 if test "x$OBJCOPY" = x; then
112 # enabling of enable-debug-symbols and can't find objcopy
113 # this is an error
114 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/autoconf/libraries.m4 jdk22u-jdk-22.0.2-ga/make/autoconf/libraries.m4
115 --- jdk22u-jdk-22.0.2-ga.orig/make/autoconf/libraries.m4 2024-06-04 18:47:50.000000000 +0200
116 +++ jdk22u-jdk-22.0.2-ga/make/autoconf/libraries.m4 2024-08-17 19:34:03.830976044 +0200
117 @@ -139,13 +139,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 @@ -162,6 +164,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 jdk22u-jdk-22.0.2-ga.orig/make/autoconf/platform.m4 jdk22u-jdk-22.0.2-ga/make/autoconf/platform.m4
148 --- jdk22u-jdk-22.0.2-ga.orig/make/autoconf/platform.m4 2024-06-04 18:47:50.000000000 +0200
149 +++ jdk22u-jdk-22.0.2-ga/make/autoconf/platform.m4 2024-08-17 19:34:03.831577179 +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 jdk22u-jdk-22.0.2-ga.orig/make/autoconf/toolchain.m4 jdk22u-jdk-22.0.2-ga/make/autoconf/toolchain.m4
190 --- jdk22u-jdk-22.0.2-ga.orig/make/autoconf/toolchain.m4 2024-06-04 18:47:50.000000000 +0200
191 +++ jdk22u-jdk-22.0.2-ga/make/autoconf/toolchain.m4 2024-08-17 19:34:03.832169765 +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="xlc clang"
199 VALID_TOOLCHAINS_windows="microsoft"
200 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/common/MakeBase.gmk jdk22u-jdk-22.0.2-ga/make/common/MakeBase.gmk
201 --- jdk22u-jdk-22.0.2-ga.orig/make/common/MakeBase.gmk 2024-06-04 18:47:50.000000000 +0200
202 +++ jdk22u-jdk-22.0.2-ga/make/common/MakeBase.gmk 2024-08-17 19:34:03.832677265 +0200
203 @@ -263,7 +263,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 jdk22u-jdk-22.0.2-ga.orig/make/common/modules/LauncherCommon.gmk jdk22u-jdk-22.0.2-ga/make/common/modules/LauncherCommon.gmk
239 --- jdk22u-jdk-22.0.2-ga.orig/make/common/modules/LauncherCommon.gmk 2024-06-04 18:47:50.000000000 +0200
240 +++ jdk22u-jdk-22.0.2-ga/make/common/modules/LauncherCommon.gmk 2024-08-17 19:34:03.833728396 +0200
241 @@ -163,6 +163,7 @@
242 -DLAUNCHER_NAME='"$$(LAUNCHER_NAME)"' \
243 -DPROGNAME='"$1"' \
244 $$($1_CFLAGS), \
245 + CFLAGS_solaris := -fPIC, \
246 CFLAGS_windows := $$($1_CFLAGS_windows), \
247 DISABLED_WARNINGS_gcc := unused-function, \
248 LDFLAGS := $$(LDFLAGS_JDKEXE) \
249 @@ -172,11 +173,14 @@
250 -L$(call FindLibDirForModule, java.base), \
251 LDFLAGS_macosx := $$(call SET_EXECUTABLE_ORIGIN,/../lib) \
252 -L$(call FindLibDirForModule, java.base), \
253 + LDFLAGS_solaris := $$(call SET_EXECUTABLE_ORIGIN,/../lib) \
254 + -L$(call FindLibDirForModule, java.base), \
255 LDFLAGS_aix := -L$(SUPPORT_OUTPUTDIR)/native/java.base, \
256 LIBS := $(JDKEXE_LIBS) $$($1_LIBS), \
257 LIBS_linux := -ljli -lpthread $(LIBDL), \
258 LIBS_macosx := -ljli -framework Cocoa -framework Security \
259 -framework ApplicationServices, \
260 + LIBS_solaris := -ljli -lthread $(LIBDL), \
261 LIBS_aix := -ljli_static, \
262 LIBS_windows := $$($1_WINDOWS_JLI_LIB) \
263 $(SUPPORT_OUTPUTDIR)/native/java.base/libjava/java.lib, \
264 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/common/NativeCompilation.gmk jdk22u-jdk-22.0.2-ga/make/common/NativeCompilation.gmk
265 --- jdk22u-jdk-22.0.2-ga.orig/make/common/NativeCompilation.gmk 2024-06-04 18:47:50.000000000 +0200
266 +++ jdk22u-jdk-22.0.2-ga/make/common/NativeCompilation.gmk 2024-08-17 19:34:03.833257814 +0200
267 @@ -1081,7 +1081,7 @@
268 $1_DEBUGINFO_FILES := $$($1_SYMBOLS_DIR)/$$($1_BASENAME).pdb \
269 $$($1_SYMBOLS_DIR)/$$($1_BASENAME).map
271 - else ifeq ($(call isTargetOs, linux), true)
272 + else ifeq ($(call isTargetOs, linux solaris), true)
273 $1_DEBUGINFO_FILES := $$($1_SYMBOLS_DIR)/$$($1_NOSUFFIX).debuginfo
274 # Setup the command line creating debuginfo files, to be run after linking.
275 # It cannot be run separately since it updates the original target file
276 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/hotspot/gensrc/GensrcAdlc.gmk jdk22u-jdk-22.0.2-ga/make/hotspot/gensrc/GensrcAdlc.gmk
277 --- jdk22u-jdk-22.0.2-ga.orig/make/hotspot/gensrc/GensrcAdlc.gmk 2024-06-04 18:47:50.000000000 +0200
278 +++ jdk22u-jdk-22.0.2-ga/make/hotspot/gensrc/GensrcAdlc.gmk 2024-08-17 19:34:03.834183102 +0200
279 @@ -36,6 +36,9 @@
280 # NOTE: No optimization or debug flags set here
281 ifeq ($(call isBuildOs, linux), true)
282 ADLC_CFLAGS := -fno-exceptions -DLINUX
283 + else ifeq ($(call isBuildOs, solaris), true)
284 + ADLC_LDFLAGS := -m64
285 + ADLC_CFLAGS := -m64 -fpermissive
286 else ifeq ($(call isBuildOs, aix), true)
287 ifeq ($(TOOLCHAIN_TYPE), clang)
288 ADLC_LDFLAGS += -m64
289 @@ -95,6 +98,8 @@
290 # ADLC flags depending on target OS
291 ifeq ($(call isTargetOs, linux), true)
292 ADLCFLAGS += -DLINUX=1 -D_GNU_SOURCE=1
293 + else ifeq ($(call isTargetOs, solaris), true)
294 + ADLCFLAGS += -DSOLARIS=1
295 else ifeq ($(call isTargetOs, aix), true)
296 ADLCFLAGS += -DAIX=1
297 else ifeq ($(call isTargetOs, macosx), true)
298 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/hotspot/gensrc/GensrcDtrace.gmk jdk22u-jdk-22.0.2-ga/make/hotspot/gensrc/GensrcDtrace.gmk
299 --- jdk22u-jdk-22.0.2-ga.orig/make/hotspot/gensrc/GensrcDtrace.gmk 2024-06-04 18:47:50.000000000 +0200
300 +++ jdk22u-jdk-22.0.2-ga/make/hotspot/gensrc/GensrcDtrace.gmk 2024-08-17 19:34:03.834592828 +0200
301 @@ -28,7 +28,10 @@
303 ifeq ($(call check-jvm-feature, dtrace), true)
305 - ifeq ($(call isTargetOs, macosx), true)
306 + ifeq ($(call isTargetOs, solaris), true)
307 + DTRACE_FLAGS := -64
308 + DTRACE_CPP_FLAGS := -D_LP64 -x c
309 + else ifeq ($(call isTargetOs, macosx), true)
310 DTRACE_CPP_FLAGS := -D_LP64 -x c
311 else ifeq ($(call isTargetOs, linux), true)
312 DTRACE_CPP_FLAGS := -x c
313 @@ -51,4 +54,59 @@
314 TARGETS += $(patsubst $(DTRACE_SOURCE_DIR)/%.d, \
315 $(DTRACE_GENSRC_DIR)/%.h, $(wildcard $(DTRACE_SOURCE_DIR)/*.d))
317 + ifeq ($(call isTargetOs, solaris), true)
318 + ############################################################################
319 + # First we need to generate the dtraceGenOffsets tool. When run, this will
320 + # produce two header files and a C++ file. Note that generateJvmOffsets.cpp
321 + # is using the same JVM_CFLAGS as libjvm.so.
323 + # Include support files that will setup JVM compiler flags.
324 + include lib/JvmFeatures.gmk
325 + include lib/JvmFlags.gmk
327 + # We cannot compile until the JVMTI and JFR gensrc has finished.
328 + # JFR_FILES is defined in GensrcJfr.gmk.
329 + JVMTI_H := $(JVM_VARIANT_OUTPUTDIR)/gensrc/jvmtifiles/jvmti.h
331 + $(eval $(call SetupNativeCompilation, BUILD_DTRACE_GEN_OFFSETS, \
332 + NAME := dtraceGenOffsets, \
333 + TYPE := EXECUTABLE, \
334 + SRC := $(TOPDIR)/make/hotspot/src/native/dtrace, \
335 + TOOLCHAIN := $(TOOLCHAIN_BUILD), \
336 + LDFLAGS := -m64, \
337 + CFLAGS := -m64 $(JVM_CFLAGS), \
338 + EXTRA_DEPS := $(JVMTI_H) $(JFR_FILES), \
339 + OBJECT_DIR := $(JVM_VARIANT_OUTPUTDIR)/tools/dtrace-gen-offsets/objs, \
340 + OUTPUT_DIR := $(JVM_VARIANT_OUTPUTDIR)/tools/dtrace-gen-offsets, \
341 + ))
343 + DTRACE_GEN_OFFSETS_TOOL := $(BUILD_DTRACE_GEN_OFFSETS_TARGET)
345 + # Argument 1: Output filename
346 + # Argument 2: dtrace-gen-offset tool command line option
347 + define SetupDtraceOffsetsGeneration
348 + $$(eval $$(call SetupExecute, dtrace_offset_$$(strip $2), \
349 + INFO := Generating dtrace $2 file, \
350 + DEPS := $$(BUILD_DTRACE_GEN_OFFSETS), \
351 + OUTPUT_FILE := $1, \
352 + COMMAND := ( $$(DTRACE_GEN_OFFSETS_TOOL) -$$(strip $2) > $1 ), \
353 + ))
355 + TARGETS += $$(dtrace_offset_$$(strip $2)_TARGET)
356 + endef
358 + JVM_OFFSETS_H := $(DTRACE_GENSRC_DIR)/JvmOffsets.h
359 + JVM_OFFSETS_CPP := $(DTRACE_GENSRC_DIR)/JvmOffsets.cpp
360 + JVM_OFFSETS_INDEX_H := $(DTRACE_GENSRC_DIR)/JvmOffsetsIndex.h
362 + ############################################################################
363 + # Run the dtrace-gen-offset tool to generate these three files.
364 + # The generated JvmOffsets.cpp is compiled with the rest of libjvm.
365 + # The header files are used by libjvm_db and jhelper.d, respectively.
367 + $(eval $(call SetupDtraceOffsetsGeneration, $(JVM_OFFSETS_H), header))
368 + $(eval $(call SetupDtraceOffsetsGeneration, $(JVM_OFFSETS_INDEX_H), index))
369 + $(eval $(call SetupDtraceOffsetsGeneration, $(JVM_OFFSETS_CPP), table))
370 + endif
372 endif
373 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/hotspot/lib/CompileDtraceLibraries.gmk jdk22u-jdk-22.0.2-ga/make/hotspot/lib/CompileDtraceLibraries.gmk
374 --- jdk22u-jdk-22.0.2-ga.orig/make/hotspot/lib/CompileDtraceLibraries.gmk 1970-01-01 01:00:00.000000000 +0100
375 +++ jdk22u-jdk-22.0.2-ga/make/hotspot/lib/CompileDtraceLibraries.gmk 2024-08-17 19:34:03.892724818 +0200
376 @@ -0,0 +1,62 @@
378 +# Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
379 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
381 +# This code is free software; you can redistribute it and/or modify it
382 +# under the terms of the GNU General Public License version 2 only, as
383 +# published by the Free Software Foundation. Oracle designates this
384 +# particular file as subject to the "Classpath" exception as provided
385 +# by Oracle in the LICENSE file that accompanied this code.
387 +# This code is distributed in the hope that it will be useful, but WITHOUT
388 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
389 +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
390 +# version 2 for more details (a copy is included in the LICENSE file that
391 +# accompanied this code).
393 +# You should have received a copy of the GNU General Public License version
394 +# 2 along with this work; if not, write to the Free Software Foundation,
395 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
397 +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
398 +# or visit www.oracle.com if you need additional information or have any
399 +# questions.
402 +ifeq ($(call check-jvm-feature, dtrace), true)
403 + ifeq ($(call isTargetOs, solaris), true)
404 + JNI_INCLUDE_FLAGS := \
405 + -I$(SUPPORT_OUTPUTDIR)/modules_include/java.base \
406 + -I$(SUPPORT_OUTPUTDIR)/modules_include/java.base/$(OPENJDK_TARGET_OS_INCLUDE_SUBDIR) \
409 + ############################################################################
410 + # Build the stand-alone dtrace libraries.
412 + LIBJVM_DTRACE_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/libjvm_dtrace
413 + $(eval $(call SetupNativeCompilation, BUILD_LIBJVM_DTRACE, \
414 + NAME := jvm_dtrace, \
415 + OUTPUT_DIR := $(JVM_LIB_OUTPUTDIR), \
416 + SRC := $(TOPDIR)/src/java.base/solaris/native/libjvm_dtrace, \
417 + CFLAGS := $(JNI_INCLUDE_FLAGS) -m64 -G -mt -KPIC -xldscope=hidden, \
418 + LDFLAGS := -m64 -mt -xnolib $(SHARED_LIBRARY_FLAGS), \
419 + LIBS := $(LIBDL) -lthread -ldoor, \
420 + OBJECT_DIR := $(LIBJVM_DTRACE_OUTPUTDIR)/objs, \
421 + ))
423 + # Note that libjvm_db.c has tests for COMPILER2, but this was never set by
424 + # the old build.
425 + LIBJVM_DB_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/libjvm_db
426 + $(eval $(call SetupNativeCompilation, BUILD_LIBJVM_DB, \
427 + NAME := jvm_db, \
428 + OUTPUT_DIR := $(JVM_LIB_OUTPUTDIR), \
429 + SRC := $(TOPDIR)/src/java.base/solaris/native/libjvm_db, \
430 + CFLAGS := -I$(DTRACE_GENSRC_DIR) $(JNI_INCLUDE_FLAGS) -m64 -G -mt -KPIC -xldscope=hidden, \
431 + LDFLAGS := -m64 -mt -xnolib $(SHARED_LIBRARY_FLAGS), \
432 + OBJECT_DIR := $(LIBJVM_DB_OUTPUTDIR)/objs, \
433 + ))
435 + TARGETS += $(BUILD_LIBJVM_DTRACE) $(BUILD_LIBJVM_DB)
437 + endif
438 +endif
439 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/hotspot/lib/CompileJvm.gmk jdk22u-jdk-22.0.2-ga/make/hotspot/lib/CompileJvm.gmk
440 --- jdk22u-jdk-22.0.2-ga.orig/make/hotspot/lib/CompileJvm.gmk 2024-06-04 18:47:50.000000000 +0200
441 +++ jdk22u-jdk-22.0.2-ga/make/hotspot/lib/CompileJvm.gmk 2024-08-17 19:34:03.835007074 +0200
442 @@ -29,6 +29,9 @@
443 include lib/JvmOverrideFiles.gmk
444 include lib/JvmFlags.gmk
446 +# Include support files that will setup DTRACE_EXTRA_OBJECT_FILES.
447 +include lib/JvmDtraceObjects.gmk
449 ################################################################################
450 # Setup compilation of the main Hotspot native library (libjvm).
452 @@ -157,6 +160,7 @@
453 EXCLUDES := $(JVM_EXCLUDES), \
454 EXCLUDE_FILES := $(JVM_EXCLUDE_FILES), \
455 EXCLUDE_PATTERNS := $(JVM_EXCLUDE_PATTERNS), \
456 + EXTRA_OBJECT_FILES := $(DTRACE_EXTRA_OBJECT_FILES), \
457 CFLAGS := $(JVM_CFLAGS), \
458 abstract_vm_version.cpp_CXXFLAGS := $(CFLAGS_VM_VERSION), \
459 arguments.cpp_CXXFLAGS := $(CFLAGS_VM_VERSION), \
460 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/hotspot/lib/CompileLibraries.gmk jdk22u-jdk-22.0.2-ga/make/hotspot/lib/CompileLibraries.gmk
461 --- jdk22u-jdk-22.0.2-ga.orig/make/hotspot/lib/CompileLibraries.gmk 2024-06-04 18:47:50.000000000 +0200
462 +++ jdk22u-jdk-22.0.2-ga/make/hotspot/lib/CompileLibraries.gmk 2024-08-17 19:34:03.835331308 +0200
463 @@ -32,6 +32,7 @@
464 include HotspotCommon.gmk
466 include lib/CompileJvm.gmk
467 +include lib/CompileDtraceLibraries.gmk
469 ifneq ($(GTEST_FRAMEWORK_SRC), )
470 ifneq ($(CREATING_BUILDJDK), true)
471 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/hotspot/lib/JvmDtraceObjects.gmk jdk22u-jdk-22.0.2-ga/make/hotspot/lib/JvmDtraceObjects.gmk
472 --- jdk22u-jdk-22.0.2-ga.orig/make/hotspot/lib/JvmDtraceObjects.gmk 1970-01-01 01:00:00.000000000 +0100
473 +++ jdk22u-jdk-22.0.2-ga/make/hotspot/lib/JvmDtraceObjects.gmk 2024-08-17 19:34:03.893023770 +0200
474 @@ -0,0 +1,122 @@
476 +# Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
477 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
479 +# This code is free software; you can redistribute it and/or modify it
480 +# under the terms of the GNU General Public License version 2 only, as
481 +# published by the Free Software Foundation. Oracle designates this
482 +# particular file as subject to the "Classpath" exception as provided
483 +# by Oracle in the LICENSE file that accompanied this code.
485 +# This code is distributed in the hope that it will be useful, but WITHOUT
486 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
487 +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
488 +# version 2 for more details (a copy is included in the LICENSE file that
489 +# accompanied this code).
491 +# You should have received a copy of the GNU General Public License version
492 +# 2 along with this work; if not, write to the Free Software Foundation,
493 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
495 +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
496 +# or visit www.oracle.com if you need additional information or have any
497 +# questions.
500 +ifeq ($(call check-jvm-feature, dtrace), true)
501 + ifeq ($(call isTargetOs, solaris), true)
503 + ############################################################################
504 + # Integrate with libjvm. Here we generate two object files which are
505 + # linked with libjvm.so. This step is complicated from a dependency
506 + # perspective. We add these two files to the linking of libjvm using
507 + # EXTRA_OBJECT_FILES, but they need to be created outside the call to
508 + # SetupNativeCompilation. Also, one of the files is dependent on compiled
509 + # object files from the libjvm compilation, so this generation must happen
510 + # as a part of the libjvm compilation.
512 + DTRACE_OBJ := $(JVM_OUTPUTDIR)/objs/dtrace.o
513 + DTRACE_JHELPER_OBJ := $(JVM_OUTPUTDIR)/objs/dtrace_jhelper.o
515 + DTRACE_EXTRA_OBJECT_FILES := $(DTRACE_OBJ) $(DTRACE_JHELPER_OBJ)
517 + ############################################################################
518 + # Generate DTRACE_OBJ which is linked with libjvm.so. It depends on a set of
519 + # object files from the compilation.
521 + # Concatenate all *.d files into a single file
522 + DTRACE_SOURCE_FILES := $(addprefix $(TOPDIR)/src/hotspot/os/posix/dtrace/, \
523 + hotspot_jni.d \
524 + hotspot.d \
525 + hs_private.d \
528 + # *.d in the objs dir is used for generated make dependency files, so use
529 + # *.dt for dtrace files to avoid clashes.
530 + $(JVM_OUTPUTDIR)/objs/dtrace.dt: $(DTRACE_SOURCE_FILES)
531 + $(call LogInfo, Generating $(@F))
532 + $(call MakeDir, $(@D))
533 + $(CAT) $^ > $@
535 + DTRACE_INSTRUMENTED_OBJS := $(addprefix $(JVM_OUTPUTDIR)/objs/, \
536 + ciEnv.o \
537 + classLoadingService.o \
538 + compileBroker.o \
539 + gcVMOperations.o \
540 + hashtable.o \
541 + instanceKlass.o \
542 + java.o \
543 + jni.o \
544 + jvm.o \
545 + memoryManager.o \
546 + nmethod.o \
547 + objectMonitor.o \
548 + runtimeService.o \
549 + sharedRuntime.o \
550 + synchronizer.o \
551 + thread.o \
552 + unsafe.o \
553 + vmThread.o \
556 + ifeq ($(call check-jvm-feature, parallelgc), true)
557 + DTRACE_INSTRUMENTED_OBJS += $(addprefix $(JVM_OUTPUTDIR)/objs/, \
558 + psVMOperations.o \
560 + endif
562 + DTRACE_FLAGS := -64 -G
563 + DTRACE_CPP_FLAGS := -D_LP64
565 + # Make sure we run our selected compiler for preprocessing instead of letting
566 + # the dtrace tool pick it on it's own.
567 + $(DTRACE_OBJ): $(JVM_OUTPUTDIR)/objs/dtrace.dt $(DTRACE_INSTRUMENTED_OBJS)
568 + $(call LogInfo, Generating $(@F) from $(<F) and object files)
569 + $(call MakeDir, $(DTRACE_SUPPORT_DIR))
570 + $(call ExecuteWithLog, $(DTRACE_SUPPORT_DIR)/$(@F).dt, \
571 + ($(CPP) $(DTRACE_CPP_FLAGS) $< > $(DTRACE_SUPPORT_DIR)/$(@F).dt))
572 + $(call ExecuteWithLog, $@, $(DTRACE) $(DTRACE_FLAGS) -xlazyload -o $@ \
573 + -s $(DTRACE_SUPPORT_DIR)/$(@F).dt $(sort $(DTRACE_INSTRUMENTED_OBJS)))
575 + ############################################################################
576 + # Generate DTRACE_JHELPER_OBJ which is linked with libjvm.so.
578 + JHELPER_DTRACE_SRC := $(TOPDIR)/src/hotspot/os/solaris/dtrace/jhelper.d
580 + # jhelper.d includes JvmOffsetsIndex.h which was created by the gensrc step.
581 + DTRACE_GENSRC_DIR := $(JVM_VARIANT_OUTPUTDIR)/gensrc/dtracefiles
582 + JVM_OFFSETS_INDEX_H := $(DTRACE_GENSRC_DIR)/JvmOffsetsIndex.h
584 + # Make sure we run our selected compiler for preprocessing instead of letting
585 + # the dtrace tool pick it on it's own.
586 + $(DTRACE_JHELPER_OBJ): $(JHELPER_DTRACE_SRC) $(JVM_OFFSETS_INDEX_H)
587 + $(call LogInfo, Running dtrace for $(<F))
588 + $(call MakeDir, $(DTRACE_SUPPORT_DIR))
589 + $(call ExecuteWithLog, $(DTRACE_SUPPORT_DIR)/$(@F).dt, \
590 + ($(CPP) $(DTRACE_CPP_FLAGS) -I$(DTRACE_GENSRC_DIR) $^ \
591 + > $(DTRACE_SUPPORT_DIR)/$(@F).dt))
592 + $(call ExecuteWithLog, $@, $(DTRACE) $(DTRACE_FLAGS) -o $@ \
593 + -s $(DTRACE_SUPPORT_DIR)/$(@F).dt)
595 + endif
596 +endif
597 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/hotspot/lib/JvmMapfile.gmk jdk22u-jdk-22.0.2-ga/make/hotspot/lib/JvmMapfile.gmk
598 --- jdk22u-jdk-22.0.2-ga.orig/make/hotspot/lib/JvmMapfile.gmk 2024-06-04 18:47:50.000000000 +0200
599 +++ jdk22u-jdk-22.0.2-ga/make/hotspot/lib/JvmMapfile.gmk 2024-08-17 19:34:03.835712968 +0200
600 @@ -48,6 +48,18 @@
601 endif
602 endif
604 +ifeq ($(call isTargetOs, solaris), true)
605 + ifeq ($(call check-jvm-feature, dtrace), true)
606 + # Additional mapfiles that are only used when dtrace is enabled
607 + ifeq ($(call check-jvm-feature, compiler2), true)
608 + # This also covers the case of compiler1+compiler2.
609 + SYMBOLS_SRC += $(TOPDIR)/make/hotspot/symbols/symbols-solaris-dtrace-compiler2
610 + else ifeq ($(call check-jvm-feature, compiler1), true)
611 + SYMBOLS_SRC += $(TOPDIR)/make/hotspot/symbols/symbols-solaris-dtrace-compiler1
612 + endif
613 + endif
614 +endif
616 ################################################################################
617 # Create a dynamic list of symbols from the built object files. This is highly
618 # platform dependent.
619 @@ -64,6 +76,20 @@
620 if ($$3 ~ /$(FILTER_SYMBOLS_PATTERN)/) print $$3; \
623 +else ifeq ($(call isTargetOs, solaris), true)
624 + DUMP_SYMBOLS_CMD := $(NM) -p *.o
625 + ifneq ($(FILTER_SYMBOLS_PATTERN), )
626 + FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)|
627 + endif
628 + FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)^__1c.*__vtbl_$$|^gHotSpotVM
629 + FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)|^UseSharedSpaces$$
630 + FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)|^__1cJArgumentsRSharedArchivePath_$$
631 + FILTER_SYMBOLS_AWK_SCRIPT := \
632 + '{ \
633 + if ($$2 == "U") next; \
634 + if ($$3 ~ /$(FILTER_SYMBOLS_PATTERN)/) print $$3; \
635 + }'
637 else ifeq ($(call isTargetOs, macosx), true)
638 # nm on macosx prints out "warning: nm: no name list" to stderr for
639 # files without symbols. Hide this, even at the expense of hiding real errors.
640 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/hotspot/src/native/dtrace/generateJvmOffsets.cpp jdk22u-jdk-22.0.2-ga/make/hotspot/src/native/dtrace/generateJvmOffsets.cpp
641 --- jdk22u-jdk-22.0.2-ga.orig/make/hotspot/src/native/dtrace/generateJvmOffsets.cpp 1970-01-01 01:00:00.000000000 +0100
642 +++ jdk22u-jdk-22.0.2-ga/make/hotspot/src/native/dtrace/generateJvmOffsets.cpp 2024-08-17 19:34:03.893548967 +0200
643 @@ -0,0 +1,316 @@
645 + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
646 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
648 + * This code is free software; you can redistribute it and/or modify it
649 + * under the terms of the GNU General Public License version 2 only, as
650 + * published by the Free Software Foundation.
652 + * This code is distributed in the hope that it will be useful, but WITHOUT
653 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
654 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
655 + * version 2 for more details (a copy is included in the LICENSE file that
656 + * accompanied this code).
658 + * You should have received a copy of the GNU General Public License version
659 + * 2 along with this work; if not, write to the Free Software Foundation,
660 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
662 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
663 + * or visit www.oracle.com if you need additional information or have any
664 + * questions.
666 + */
669 + * This is to provide sanity check in jhelper.d which compares SCCS
670 + * versions of generateJvmOffsets.cpp used to create and extract
671 + * contents of __JvmOffsets[] table.
672 + * The __JvmOffsets[] table is located in generated JvmOffsets.cpp.
674 + * GENOFFS_SCCS_VER 34
675 + */
677 +#include <stdio.h>
678 +#include <strings.h>
680 +/* A workaround for private and protected fields */
681 +#define private public
682 +#define protected public
684 +#include <proc_service.h>
685 +#include "gc/shared/collectedHeap.hpp"
686 +#include "memory/heap.hpp"
687 +#include "oops/compressedOops.hpp"
688 +#include "runtime/vmStructs.hpp"
690 +typedef enum GEN_variant {
691 + GEN_OFFSET = 0,
692 + GEN_INDEX = 1,
693 + GEN_TABLE = 2
694 +} GEN_variant;
696 +#ifdef COMPILER1
697 +#ifdef ASSERT
700 + * To avoid the most part of potential link errors
701 + * we link this program with -z nodefs .
703 + * But for 'debug1' and 'fastdebug1' we still have to provide
704 + * a particular workaround for the following symbols below.
705 + * It will be good to find out a generic way in the future.
706 + */
708 +#pragma weak tty
710 +#if defined(i386) || defined(__i386) || defined(__amd64)
711 +#pragma weak noreg
712 +#endif /* i386 */
714 +LIR_Opr LIR_OprFact::illegalOpr = (LIR_Opr) 0;
716 +address StubRoutines::_call_stub_return_address = NULL;
718 +StubQueue* AbstractInterpreter::_code = NULL;
720 +#endif /* ASSERT */
721 +#endif /* COMPILER1 */
723 +#define GEN_OFFS_NAME(Type,Name,OutputType) \
724 + switch(gen_variant) { \
725 + case GEN_OFFSET: \
726 + printf("#define OFFSET_%-33s %ld\n", \
727 + #OutputType #Name, offset_of(Type, Name)); \
728 + break; \
729 + case GEN_INDEX: \
730 + printf("#define IDX_OFFSET_%-33s %d\n", \
731 + #OutputType #Name, index++); \
732 + break; \
733 + case GEN_TABLE: \
734 + printf("\tOFFSET_%s,\n", #OutputType #Name); \
735 + break; \
738 +#define GEN_OFFS(Type,Name) \
739 + GEN_OFFS_NAME(Type,Name,Type)
741 +#define GEN_SIZE(Type) \
742 + switch(gen_variant) { \
743 + case GEN_OFFSET: \
744 + printf("#define SIZE_%-35s %ld\n", \
745 + #Type, sizeof(Type)); \
746 + break; \
747 + case GEN_INDEX: \
748 + printf("#define IDX_SIZE_%-35s %d\n", \
749 + #Type, index++); \
750 + break; \
751 + case GEN_TABLE: \
752 + printf("\tSIZE_%s,\n", #Type); \
753 + break; \
756 +#define GEN_VALUE(String,Value) \
757 + switch(gen_variant) { \
758 + case GEN_OFFSET: \
759 + printf("#define %-40s %d\n", #String, Value); \
760 + break; \
761 + case GEN_INDEX: \
762 + printf("#define IDX_%-40s %d\n", #String, index++); \
763 + break; \
764 + case GEN_TABLE: \
765 + printf("\t" #String ",\n"); \
766 + break; \
769 +void gen_prologue(GEN_variant gen_variant) {
770 + const char *suffix = "Undefined-Suffix";
772 + switch(gen_variant) {
773 + case GEN_OFFSET: suffix = ".h"; break;
774 + case GEN_INDEX: suffix = "Index.h"; break;
775 + case GEN_TABLE: suffix = ".cpp"; break;
778 + printf("/*\n");
779 + printf(" * JvmOffsets%s !!!DO NOT EDIT!!! \n", suffix);
780 + printf(" * The generateJvmOffsets program generates this file!\n");
781 + printf(" */\n\n");
782 + switch(gen_variant) {
784 + case GEN_OFFSET:
785 + case GEN_INDEX:
786 + break;
788 + case GEN_TABLE:
789 + printf("#include \"JvmOffsets.h\"\n");
790 + printf("\n");
791 + printf("int __JvmOffsets[] = {\n");
792 + break;
796 +void gen_epilogue(GEN_variant gen_variant) {
797 + if (gen_variant != GEN_TABLE) {
798 + return;
800 + printf("};\n\n");
801 + return;
804 +int generateJvmOffsets(GEN_variant gen_variant) {
805 + int index = 0; /* It is used to generate JvmOffsetsIndex.h */
806 + int pointer_size = sizeof(void *);
807 + int data_model = (pointer_size == 4) ? PR_MODEL_ILP32 : PR_MODEL_LP64;
809 + gen_prologue(gen_variant);
811 + GEN_VALUE(DATA_MODEL, data_model);
812 + GEN_VALUE(POINTER_SIZE, pointer_size);
813 +#if COMPILER1_AND_COMPILER2
814 + GEN_VALUE(COMPILER, 3);
815 +#elif COMPILER1
816 + GEN_VALUE(COMPILER, 1);
817 +#elif COMPILER2
818 + GEN_VALUE(COMPILER, 2);
819 +#else
820 + GEN_VALUE(COMPILER, 0);
821 +#endif // COMPILER1 && COMPILER2
822 + printf("\n");
824 + GEN_OFFS(CollectedHeap, _reserved);
825 + GEN_OFFS(MemRegion, _start);
826 + GEN_OFFS(MemRegion, _word_size);
827 + GEN_SIZE(HeapWord);
828 + printf("\n");
830 + GEN_OFFS(VMStructEntry, typeName);
831 + GEN_OFFS(VMStructEntry, fieldName);
832 + GEN_OFFS(VMStructEntry, address);
833 + GEN_SIZE(VMStructEntry);
834 + printf("\n");
836 + GEN_VALUE(MAX_METHOD_CODE_SIZE, max_method_code_size);
837 +#if defined(i386) || defined(__i386) || defined(__amd64)
838 + GEN_VALUE(OFFSET_interpreter_frame_sender_sp, -1 * pointer_size);
839 + GEN_VALUE(OFFSET_interpreter_frame_method, -3 * pointer_size);
840 + GEN_VALUE(OFFSET_interpreter_frame_bcp_offset, -7 * pointer_size);
841 +#endif
843 + GEN_OFFS(Klass, _name);
844 + GEN_OFFS(ConstantPool, _pool_holder);
845 + printf("\n");
847 + GEN_VALUE(OFFSET_HeapBlockHeader_used, (int) offset_of(HeapBlock::Header, _used));
848 + GEN_OFFS(oopDesc, _metadata);
849 + printf("\n");
851 + GEN_VALUE(AccessFlags_NATIVE, JVM_ACC_NATIVE);
852 + GEN_VALUE(ConstMethod_has_linenumber_table, ConstMethod::_has_linenumber_table);
853 + GEN_OFFS(AccessFlags, _flags);
854 + GEN_OFFS(Symbol, _length);
855 + GEN_OFFS(Symbol, _body);
856 + printf("\n");
858 + GEN_OFFS(Method, _constMethod);
859 + GEN_OFFS(Method, _access_flags);
860 + printf("\n");
862 + GEN_OFFS(ConstMethod, _constants);
863 + GEN_OFFS(ConstMethod, _flags);
864 + GEN_OFFS(ConstMethod, _code_size);
865 + GEN_OFFS(ConstMethod, _name_index);
866 + GEN_OFFS(ConstMethod, _signature_index);
867 + printf("\n");
869 + GEN_OFFS(CodeHeap, _memory);
870 + GEN_OFFS(CodeHeap, _segmap);
871 + GEN_OFFS(CodeHeap, _log2_segment_size);
872 + printf("\n");
874 + GEN_OFFS(VirtualSpace, _low_boundary);
875 + GEN_OFFS(VirtualSpace, _high_boundary);
876 + GEN_OFFS(VirtualSpace, _low);
877 + GEN_OFFS(VirtualSpace, _high);
878 + printf("\n");
880 + /* We need to use different names here because of the template parameter */
881 + GEN_OFFS_NAME(GrowableArray<CodeHeap*>, _data, GrowableArray_CodeHeap);
882 + GEN_OFFS_NAME(GrowableArray<CodeHeap*>, _len, GrowableArray_CodeHeap);
883 + printf("\n");
885 + GEN_OFFS(CodeBlob, _name);
886 + GEN_OFFS(CodeBlob, _header_size);
887 + GEN_OFFS(CodeBlob, _content_begin);
888 + GEN_OFFS(CodeBlob, _code_begin);
889 + GEN_OFFS(CodeBlob, _code_end);
890 + GEN_OFFS(CodeBlob, _data_offset);
891 + GEN_OFFS(CodeBlob, _frame_size);
892 + printf("\n");
894 + GEN_OFFS(nmethod, _method);
895 + GEN_OFFS(nmethod, _dependencies_offset);
896 + GEN_OFFS(nmethod, _metadata_offset);
897 + GEN_OFFS(nmethod, _scopes_data_begin);
898 + GEN_OFFS(nmethod, _scopes_pcs_offset);
899 + GEN_OFFS(nmethod, _handler_table_offset);
900 + GEN_OFFS(nmethod, _deopt_handler_begin);
901 + GEN_OFFS(nmethod, _orig_pc_offset);
903 + GEN_OFFS(PcDesc, _pc_offset);
904 + GEN_OFFS(PcDesc, _scope_decode_offset);
906 + printf("\n");
908 + GEN_OFFS(NarrowPtrStruct, _base);
909 + GEN_OFFS(NarrowPtrStruct, _shift);
910 + printf("\n");
912 + GEN_VALUE(SIZE_HeapBlockHeader, (int) sizeof(HeapBlock::Header));
913 + GEN_SIZE(oopDesc);
914 + GEN_SIZE(ConstantPool);
915 + printf("\n");
917 + GEN_SIZE(PcDesc);
918 + GEN_SIZE(Method);
919 + GEN_SIZE(ConstMethod);
920 + GEN_SIZE(nmethod);
921 + GEN_SIZE(CodeBlob);
922 + GEN_SIZE(BufferBlob);
923 + GEN_SIZE(SingletonBlob);
924 + GEN_SIZE(RuntimeStub);
925 + GEN_SIZE(SafepointBlob);
927 + gen_epilogue(gen_variant);
928 + printf("\n");
930 + fflush(stdout);
931 + return 0;
934 +const char *HELP =
935 + "HELP: generateJvmOffsets {-header | -index | -table} \n";
937 +int main(int argc, const char *argv[]) {
938 + GEN_variant gen_var;
940 + if (argc != 2) {
941 + printf("%s", HELP);
942 + return 1;
945 + if (0 == strcmp(argv[1], "-header")) {
946 + gen_var = GEN_OFFSET;
948 + else if (0 == strcmp(argv[1], "-index")) {
949 + gen_var = GEN_INDEX;
951 + else if (0 == strcmp(argv[1], "-table")) {
952 + gen_var = GEN_TABLE;
954 + else {
955 + printf("%s", HELP);
956 + return 1;
958 + return generateJvmOffsets(gen_var);
960 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/hotspot/symbols/symbols-solaris jdk22u-jdk-22.0.2-ga/make/hotspot/symbols/symbols-solaris
961 --- jdk22u-jdk-22.0.2-ga.orig/make/hotspot/symbols/symbols-solaris 1970-01-01 01:00:00.000000000 +0100
962 +++ jdk22u-jdk-22.0.2-ga/make/hotspot/symbols/symbols-solaris 2024-08-17 19:34:03.893855021 +0200
963 @@ -0,0 +1,25 @@
965 +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
966 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
968 +# This code is free software; you can redistribute it and/or modify it
969 +# under the terms of the GNU General Public License version 2 only, as
970 +# published by the Free Software Foundation.
972 +# This code is distributed in the hope that it will be useful, but WITHOUT
973 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
974 +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
975 +# version 2 for more details (a copy is included in the LICENSE file that
976 +# accompanied this code).
978 +# You should have received a copy of the GNU General Public License version
979 +# 2 along with this work; if not, write to the Free Software Foundation,
980 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
982 +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
983 +# or visit www.oracle.com if you need additional information or have any
984 +# questions.
987 +JVM_handle_solaris_signal
988 +sysThreadAvailableStackWithSlack
989 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/hotspot/symbols/symbols-solaris-dtrace-compiler1 jdk22u-jdk-22.0.2-ga/make/hotspot/symbols/symbols-solaris-dtrace-compiler1
990 --- jdk22u-jdk-22.0.2-ga.orig/make/hotspot/symbols/symbols-solaris-dtrace-compiler1 1970-01-01 01:00:00.000000000 +0100
991 +++ jdk22u-jdk-22.0.2-ga/make/hotspot/symbols/symbols-solaris-dtrace-compiler1 2024-08-17 19:34:03.894107089 +0200
992 @@ -0,0 +1,34 @@
994 +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
995 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
997 +# This code is free software; you can redistribute it and/or modify it
998 +# under the terms of the GNU General Public License version 2 only, as
999 +# published by the Free Software Foundation.
1001 +# This code is distributed in the hope that it will be useful, but WITHOUT
1002 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1003 +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1004 +# version 2 for more details (a copy is included in the LICENSE file that
1005 +# accompanied this code).
1007 +# You should have received a copy of the GNU General Public License version
1008 +# 2 along with this work; if not, write to the Free Software Foundation,
1009 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1011 +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1012 +# or visit www.oracle.com if you need additional information or have any
1013 +# questions.
1016 +__1cGMethodG__vtbl_
1017 +__1cHnmethodG__vtbl_
1018 +__1cICodeBlobG__vtbl_
1019 +__1cIUniverseO_collectedHeap_
1020 +__1cJCodeCacheG_heaps_
1021 +__1cKBufferBlobG__vtbl_
1022 +__1cLRuntimeStubG__vtbl_
1023 +__1cNSafepointBlobG__vtbl_
1024 +__1cSDeoptimizationBlobG__vtbl_
1026 +__JvmOffsets
1027 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/hotspot/symbols/symbols-solaris-dtrace-compiler2 jdk22u-jdk-22.0.2-ga/make/hotspot/symbols/symbols-solaris-dtrace-compiler2
1028 --- jdk22u-jdk-22.0.2-ga.orig/make/hotspot/symbols/symbols-solaris-dtrace-compiler2 1970-01-01 01:00:00.000000000 +0100
1029 +++ jdk22u-jdk-22.0.2-ga/make/hotspot/symbols/symbols-solaris-dtrace-compiler2 2024-08-17 19:34:03.894353026 +0200
1030 @@ -0,0 +1,36 @@
1032 +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
1033 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1035 +# This code is free software; you can redistribute it and/or modify it
1036 +# under the terms of the GNU General Public License version 2 only, as
1037 +# published by the Free Software Foundation.
1039 +# This code is distributed in the hope that it will be useful, but WITHOUT
1040 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1041 +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1042 +# version 2 for more details (a copy is included in the LICENSE file that
1043 +# accompanied this code).
1045 +# You should have received a copy of the GNU General Public License version
1046 +# 2 along with this work; if not, write to the Free Software Foundation,
1047 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1049 +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1050 +# or visit www.oracle.com if you need additional information or have any
1051 +# questions.
1054 +__1cGMethodG__vtbl_
1055 +__1cHnmethodG__vtbl_
1056 +__1cICodeBlobG__vtbl_
1057 +__1cIUniverseO_collectedHeap_
1058 +__1cJCodeCacheG_heaps_
1059 +__1cKBufferBlobG__vtbl_
1060 +__1cLRuntimeStubG__vtbl_
1061 +__1cNSafepointBlobG__vtbl_
1062 +__1cSDeoptimizationBlobG__vtbl_
1063 +__1cNExceptionBlobG__vtbl_
1064 +__1cQUncommonTrapBlobG__vtbl_
1066 +__JvmOffsets
1067 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/ide/visualstudio/hotspot/CreateVSProject.gmk jdk22u-jdk-22.0.2-ga/make/ide/visualstudio/hotspot/CreateVSProject.gmk
1068 --- jdk22u-jdk-22.0.2-ga.orig/make/ide/visualstudio/hotspot/CreateVSProject.gmk 2024-06-04 18:47:50.000000000 +0200
1069 +++ jdk22u-jdk-22.0.2-ga/make/ide/visualstudio/hotspot/CreateVSProject.gmk 2024-08-17 19:34:03.836120403 +0200
1070 @@ -76,6 +76,7 @@
1071 -ignorePath linux \
1072 -ignorePath posix \
1073 -ignorePath ppc \
1074 + -ignorePath solaris \
1075 -ignorePath x86_32 \
1076 -ignorePath zero \
1078 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/langtools/build.xml jdk22u-jdk-22.0.2-ga/make/langtools/build.xml
1079 --- jdk22u-jdk-22.0.2-ga.orig/make/langtools/build.xml 2024-06-04 18:47:50.000000000 +0200
1080 +++ jdk22u-jdk-22.0.2-ga/make/langtools/build.xml 2024-08-17 19:34:03.836550883 +0200
1081 @@ -100,7 +100,7 @@
1082 <property name="xpatch.noquotes.cmd" value="--patch-module=${xpatch.noquotes.rest}"/>
1084 <!-- java.marker is set to a marker file to check for within a Java install dir.
1085 - The best file to check for across Linux/Windows/MacOS is one of the
1086 + The best file to check for across Solaris/Linux/Windows/MacOS is one of the
1087 executables; regrettably, that is OS-specific. -->
1088 <condition property="java.marker" value="bin/java">
1089 <os family="unix"/>
1090 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/modules/java.base/Copy.gmk jdk22u-jdk-22.0.2-ga/make/modules/java.base/Copy.gmk
1091 --- jdk22u-jdk-22.0.2-ga.orig/make/modules/java.base/Copy.gmk 2024-06-04 18:47:50.000000000 +0200
1092 +++ jdk22u-jdk-22.0.2-ga/make/modules/java.base/Copy.gmk 2024-08-17 19:34:03.836951019 +0200
1093 @@ -190,7 +190,7 @@
1095 TARGETS += $(NET_PROPERTIES_DST)
1097 -ifeq ($(call isTargetOs, linux), true)
1098 +ifeq ($(call isTargetOs, solaris linux), true)
1099 $(eval $(call SetupCopyFiles, COPY_SDP_CONF, \
1100 FILES := $(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/conf/sdp/sdp.conf.template, \
1101 DEST := $(CONF_DST_DIR)/sdp, \
1102 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/modules/java.base/gensrc/GensrcMisc.gmk jdk22u-jdk-22.0.2-ga/make/modules/java.base/gensrc/GensrcMisc.gmk
1103 --- jdk22u-jdk-22.0.2-ga.orig/make/modules/java.base/gensrc/GensrcMisc.gmk 2024-06-04 18:47:50.000000000 +0200
1104 +++ jdk22u-jdk-22.0.2-ga/make/modules/java.base/gensrc/GensrcMisc.gmk 2024-08-17 19:34:03.838214571 +0200
1105 @@ -136,6 +136,21 @@
1107 endif
1109 +################################################################################
1111 +ifeq ($(call isTargetOs, solaris), true)
1113 + GENSRC_SC_FILE := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/fs/SolarisConstants.java
1115 + $(GENSRC_SC_FILE): \
1116 + $(TOPDIR)/src/java.base/solaris/classes/sun/nio/fs/SolarisConstants.java.template
1117 + $(generate-preproc-src)
1119 + TARGETS += $(GENSRC_SC_FILE)
1121 +endif
1123 +################################################################################
1124 # Create the javax/crypto/JceSecurity.class, using the build default.
1126 ifeq ($(UNLIMITED_CRYPTO), true)
1127 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/modules/java.base/Launcher.gmk jdk22u-jdk-22.0.2-ga/make/modules/java.base/Launcher.gmk
1128 --- jdk22u-jdk-22.0.2-ga.orig/make/modules/java.base/Launcher.gmk 2024-06-04 18:47:50.000000000 +0200
1129 +++ jdk22u-jdk-22.0.2-ga/make/modules/java.base/Launcher.gmk 2024-08-17 19:34:03.837333177 +0200
1130 @@ -64,6 +64,7 @@
1131 CFLAGS := $(CFLAGS_JDKEXE) \
1132 -I$(TOPDIR)/src/$(MODULE)/share/native/libjli, \
1133 CFLAGS_linux := -fPIC, \
1134 + CFLAGS_solaris := -KPIC, \
1135 LDFLAGS := $(LDFLAGS_JDKEXE), \
1136 OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/modules_libs/$(MODULE), \
1138 @@ -73,7 +74,7 @@
1140 ################################################################################
1142 -ifeq ($(call isTargetOs, macosx aix linux), true)
1143 +ifeq ($(call isTargetOs, macosx solaris aix linux), true)
1144 $(eval $(call SetupJdkExecutable, BUILD_JSPAWNHELPER, \
1145 NAME := jspawnhelper, \
1146 SRC := $(TOPDIR)/src/$(MODULE)/unix/native/jspawnhelper, \
1147 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/modules/java.base/lib/CoreLibraries.gmk jdk22u-jdk-22.0.2-ga/make/modules/java.base/lib/CoreLibraries.gmk
1148 --- jdk22u-jdk-22.0.2-ga.orig/make/modules/java.base/lib/CoreLibraries.gmk 2024-06-04 18:47:50.000000000 +0200
1149 +++ jdk22u-jdk-22.0.2-ga/make/modules/java.base/lib/CoreLibraries.gmk 2024-08-17 19:34:03.838694193 +0200
1150 @@ -26,7 +26,7 @@
1151 ##########################################################################################
1153 LIBVERIFY_OPTIMIZATION := HIGH
1154 -ifeq ($(call isTargetOs, linux), true)
1155 +ifeq ($(call isTargetOs, solaris linux), true)
1156 ifeq ($(COMPILE_WITH_DEBUG_SYMBOLS), true)
1157 LIBVERIFY_OPTIMIZATION := LOW
1158 endif
1159 @@ -67,6 +67,7 @@
1160 LDFLAGS_macosx := -L$(SUPPORT_OUTPUTDIR)/native/$(MODULE)/, \
1161 LIBS_unix := -ljvm, \
1162 LIBS_linux := $(LIBDL), \
1163 + LIBS_solaris := -lsocket -lnsl -lscf $(LIBDL), \
1164 LIBS_aix := $(LIBDL) $(LIBM),\
1165 LIBS_macosx := -framework CoreFoundation \
1166 -framework Foundation \
1167 @@ -181,6 +182,7 @@
1168 $(call SET_SHARED_LIBRARY_ORIGIN), \
1169 LIBS_unix := $(LIBZ_LIBS), \
1170 LIBS_linux := $(LIBDL) -lpthread, \
1171 + LIBS_solaris := $(LIBDL), \
1172 LIBS_aix := $(LIBDL),\
1173 LIBS_macosx := -framework Cocoa -framework Security -framework ApplicationServices, \
1174 LIBS_windows := advapi32.lib comctl32.lib user32.lib, \
1175 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/modules/java.base/Lib.gmk jdk22u-jdk-22.0.2-ga/make/modules/java.base/Lib.gmk
1176 --- jdk22u-jdk-22.0.2-ga.orig/make/modules/java.base/Lib.gmk 2024-06-04 18:47:50.000000000 +0200
1177 +++ jdk22u-jdk-22.0.2-ga/make/modules/java.base/Lib.gmk 2024-08-17 19:34:03.837796021 +0200
1178 @@ -56,6 +56,7 @@
1179 -delayload:winhttp.dll, \
1180 LIBS_unix := -ljvm -ljava, \
1181 LIBS_linux := $(LIBDL), \
1182 + LIBS_solaris := -lnsl -lsocket $(LIBDL), \
1183 LIBS_aix := $(LIBDL),\
1184 LIBS_windows := ws2_32.lib jvm.lib secur32.lib iphlpapi.lib winhttp.lib \
1185 delayimp.lib $(WIN_JAVA_LIB) advapi32.lib, \
1186 @@ -82,6 +83,8 @@
1187 $(call SET_SHARED_LIBRARY_ORIGIN), \
1188 LIBS_unix := -ljava -lnet, \
1189 LIBS_linux := -lpthread $(LIBDL), \
1190 + LIBS_solaris := -ljvm -lsocket -lposix4 $(LIBDL) \
1191 + -lsendfile, \
1192 LIBS_aix := $(LIBDL), \
1193 LIBS_macosx := \
1194 -framework CoreFoundation -framework CoreServices, \
1195 @@ -134,6 +137,7 @@
1196 LDFLAGS := $(LDFLAGS_JDKLIB) \
1197 $(call SET_SHARED_LIBRARY_ORIGIN), \
1198 LIBS_linux := $(LIBDL), \
1199 + LIBS_solaris := $(LIBDL), \
1200 LIBS_aix := $(LIBDL), \
1203 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/modules/java.desktop/Gensrc.gmk jdk22u-jdk-22.0.2-ga/make/modules/java.desktop/Gensrc.gmk
1204 --- jdk22u-jdk-22.0.2-ga.orig/make/modules/java.desktop/Gensrc.gmk 2024-06-04 18:47:50.000000000 +0200
1205 +++ jdk22u-jdk-22.0.2-ga/make/modules/java.desktop/Gensrc.gmk 2024-08-17 19:34:03.839072559 +0200
1206 @@ -32,7 +32,7 @@
1207 include gensrc/GensrcIcons.gmk
1208 endif
1210 -ifeq ($(call isTargetOs, linux aix), true)
1211 +ifeq ($(call isTargetOs, linux solaris aix), true)
1212 include gensrc/GensrcX11Wrappers.gmk
1213 endif
1215 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/modules/java.desktop/lib/Awt2dLibraries.gmk jdk22u-jdk-22.0.2-ga/make/modules/java.desktop/lib/Awt2dLibraries.gmk
1216 --- jdk22u-jdk-22.0.2-ga.orig/make/modules/java.desktop/lib/Awt2dLibraries.gmk 2024-06-04 18:47:50.000000000 +0200
1217 +++ jdk22u-jdk-22.0.2-ga/make/modules/java.desktop/lib/Awt2dLibraries.gmk 2024-08-17 19:34:03.840111167 +0200
1218 @@ -77,7 +77,7 @@
1220 endif
1222 -ifeq ($(call isTargetOs, linux macosx aix), true)
1223 +ifeq ($(call isTargetOs, solaris linux macosx aix), true)
1224 LIBAWT_EXFILES += awt_Font.c CUPSfuncs.c fontpath.c X11Color.c
1225 endif
1227 @@ -155,6 +155,7 @@
1228 -delayload:comctl32.dll -delayload:shlwapi.dll, \
1229 LIBS_unix := -ljvm -ljava $(LIBM), \
1230 LIBS_linux := $(LIBDL), \
1231 + LIBS_solaris := $(LIBDL), \
1232 LIBS_aix := $(LIBDL),\
1233 LIBS_macosx := -lmlib_image \
1234 -framework Cocoa \
1235 @@ -420,6 +421,7 @@
1236 LDFLAGS_unix := -L$(INSTALL_LIBRARIES_HERE), \
1237 LIBS_unix := -lawt -ljvm -ljava, \
1238 LIBS_linux := $(LIBM) $(LIBDL), \
1239 + LIBS_solaris := $(LIBM) $(LIBDL) $(LIBCXX), \
1240 STATIC_LIB_EXCLUDE_OBJS := $(LIBAWT_HEADLESS_STATIC_EXCLUDE_OBJS), \
1243 @@ -478,7 +480,7 @@
1244 -DHAVE_SYSCONF -DHAVE_SYS_MMAN_H -DHAVE_UNISTD_H \
1245 -DHB_NO_PRAGMA_GCC_DIAGNOSTIC
1246 endif
1247 - ifeq ($(call isTargetOs, linux macosx), true)
1248 + ifeq ($(call isTargetOs, solaris linux macosx), true)
1249 HARFBUZZ_CFLAGS += -DHAVE_INTEL_ATOMIC_PRIMITIVES -DHB_NO_VISIBILITY
1250 endif
1252 @@ -654,7 +656,10 @@
1253 ifeq ($(call isTargetOs, macosx), true)
1254 JAWT_LIBS := -lawt_lwawt
1255 else
1256 - JAWT_LIBS := -lawt
1257 + JAWT_LIBS :=
1258 + ifeq ($(call isTargetOs, solaris), false)
1259 + JAWT_LIBS += -lawt
1260 + endif
1261 ifeq ($(ENABLE_HEADLESS_ONLY), false)
1262 JAWT_LIBS += -lawt_xawt
1263 else
1264 @@ -681,6 +686,7 @@
1265 LDFLAGS_unix := -L$(INSTALL_LIBRARIES_HERE), \
1266 LDFLAGS_macosx := -Wl$(COMMA)-rpath$(COMMA)@loader_path, \
1267 LIBS_unix := $(JAWT_LIBS) $(JDKLIB_LIBS), \
1268 + LIBS_solaris := $(X_LIBS) -lXrender, \
1269 LIBS_macosx := -framework Cocoa, \
1272 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/modules/java.desktop/Lib.gmk jdk22u-jdk-22.0.2-ga/make/modules/java.desktop/Lib.gmk
1273 --- jdk22u-jdk-22.0.2-ga.orig/make/modules/java.desktop/Lib.gmk 2024-06-04 18:47:50.000000000 +0200
1274 +++ jdk22u-jdk-22.0.2-ga/make/modules/java.desktop/Lib.gmk 2024-08-17 19:34:03.839387326 +0200
1275 @@ -47,10 +47,15 @@
1276 -DX_PLATFORM=X_$(OPENJDK_TARGET_OS_UPPERCASE) \
1277 -DUSE_PORTS=TRUE \
1278 -DUSE_DAUDIO=TRUE \
1279 - -DUSE_PLATFORM_MIDI_OUT=TRUE \
1280 - -DUSE_PLATFORM_MIDI_IN=TRUE \
1283 + ifeq ($(call isTargetOs, solaris), false)
1284 + LIBJSOUND_CFLAGS += \
1285 + -DUSE_PLATFORM_MIDI_OUT=TRUE \
1286 + -DUSE_PLATFORM_MIDI_IN=TRUE \
1288 + endif
1290 ifeq ($(call isTargetOs, macosx), true)
1291 LIBJSOUND_TOOLCHAIN := TOOLCHAIN_LINK_CXX
1292 endif
1293 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/modules/java.instrument/Lib.gmk jdk22u-jdk-22.0.2-ga/make/modules/java.instrument/Lib.gmk
1294 --- jdk22u-jdk-22.0.2-ga.orig/make/modules/java.instrument/Lib.gmk 2024-06-04 18:47:50.000000000 +0200
1295 +++ jdk22u-jdk-22.0.2-ga/make/modules/java.instrument/Lib.gmk 2024-08-17 19:34:03.840487443 +0200
1296 @@ -44,11 +44,13 @@
1297 $(call SET_SHARED_LIBRARY_ORIGIN) \
1298 $(LIBINSTRUMENT_LDFLAGS), \
1299 LDFLAGS_linux := -L$(call FindLibDirForModule, java.base), \
1300 + LDFLAGS_solaris := -L$(call FindLibDirForModule, java.base), \
1301 LDFLAGS_macosx := -L$(call FindLibDirForModule, java.base), \
1302 LDFLAGS_aix := -L$(SUPPORT_OUTPUTDIR)/native/java.base, \
1303 LIBS := $(JDKLIB_LIBS), \
1304 LIBS_unix := -ljava -ljvm $(LIBZ_LIBS), \
1305 LIBS_linux := -ljli $(LIBDL), \
1306 + LIBS_solaris := -ljli $(LIBDL), \
1307 LIBS_aix := -liconv -ljli_static $(LIBDL), \
1308 LIBS_macosx := -ljli -liconv -framework Cocoa -framework Security \
1309 -framework ApplicationServices, \
1310 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/modules/java.management/Lib.gmk jdk22u-jdk-22.0.2-ga/make/modules/java.management/Lib.gmk
1311 --- jdk22u-jdk-22.0.2-ga.orig/make/modules/java.management/Lib.gmk 2024-06-04 18:47:50.000000000 +0200
1312 +++ jdk22u-jdk-22.0.2-ga/make/modules/java.management/Lib.gmk 2024-08-17 19:34:03.840913876 +0200
1313 @@ -28,7 +28,7 @@
1314 ################################################################################
1316 LIBMANAGEMENT_OPTIMIZATION := HIGH
1317 -ifeq ($(call isTargetOs, linux), true)
1318 +ifeq ($(call isTargetOs, solaris linux), true)
1319 ifeq ($(COMPILE_WITH_DEBUG_SYMBOLS), true)
1320 LIBMANAGEMENT_OPTIMIZATION := LOW
1321 endif
1322 @@ -41,6 +41,7 @@
1323 LDFLAGS := $(LDFLAGS_JDKLIB) \
1324 $(call SET_SHARED_LIBRARY_ORIGIN), \
1325 LIBS := $(JDKLIB_LIBS), \
1326 + LIBS_solaris := -lkstat, \
1327 LIBS_aix := -lperfstat,\
1328 LIBS_windows := jvm.lib psapi.lib $(WIN_JAVA_LIB) advapi32.lib, \
1330 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/modules/java.prefs/Lib.gmk jdk22u-jdk-22.0.2-ga/make/modules/java.prefs/Lib.gmk
1331 --- jdk22u-jdk-22.0.2-ga.orig/make/modules/java.prefs/Lib.gmk 2024-06-04 18:47:50.000000000 +0200
1332 +++ jdk22u-jdk-22.0.2-ga/make/modules/java.prefs/Lib.gmk 2024-08-17 19:34:03.841305188 +0200
1333 @@ -41,6 +41,7 @@
1334 $(call SET_SHARED_LIBRARY_ORIGIN), \
1335 LIBS_unix := -ljvm, \
1336 LIBS_linux := -ljava, \
1337 + LIBS_solaris := -ljava, \
1338 LIBS_aix := -ljava, \
1339 LIBS_macosx := -framework CoreFoundation -framework Foundation, \
1340 LIBS_windows := advapi32.lib jvm.lib $(WIN_JAVA_LIB), \
1341 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/modules/jdk.attach/Lib.gmk jdk22u-jdk-22.0.2-ga/make/modules/jdk.attach/Lib.gmk
1342 --- jdk22u-jdk-22.0.2-ga.orig/make/modules/jdk.attach/Lib.gmk 2024-06-04 18:47:50.000000000 +0200
1343 +++ jdk22u-jdk-22.0.2-ga/make/modules/jdk.attach/Lib.gmk 2024-08-17 19:34:03.841671978 +0200
1344 @@ -42,6 +42,7 @@
1345 LDFLAGS := $(LDFLAGS_JDKLIB) \
1346 $(call SET_SHARED_LIBRARY_ORIGIN), \
1347 LIBS := $(JDKLIB_LIBS), \
1348 + LIBS_solaris := -ldoor, \
1349 LIBS_windows := $(WIN_JAVA_LIB) advapi32.lib psapi.lib, \
1352 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/modules/jdk.crypto.cryptoki/Copy.gmk jdk22u-jdk-22.0.2-ga/make/modules/jdk.crypto.cryptoki/Copy.gmk
1353 --- jdk22u-jdk-22.0.2-ga.orig/make/modules/jdk.crypto.cryptoki/Copy.gmk 1970-01-01 01:00:00.000000000 +0100
1354 +++ jdk22u-jdk-22.0.2-ga/make/modules/jdk.crypto.cryptoki/Copy.gmk 2024-08-17 19:34:03.894655900 +0200
1355 @@ -0,0 +1,45 @@
1357 +# Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
1358 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1360 +# This code is free software; you can redistribute it and/or modify it
1361 +# under the terms of the GNU General Public License version 2 only, as
1362 +# published by the Free Software Foundation. Oracle designates this
1363 +# particular file as subject to the "Classpath" exception as provided
1364 +# by Oracle in the LICENSE file that accompanied this code.
1366 +# This code is distributed in the hope that it will be useful, but WITHOUT
1367 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1368 +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1369 +# version 2 for more details (a copy is included in the LICENSE file that
1370 +# accompanied this code).
1372 +# You should have received a copy of the GNU General Public License version
1373 +# 2 along with this work; if not, write to the Free Software Foundation,
1374 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1376 +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1377 +# or visit www.oracle.com if you need additional information or have any
1378 +# questions.
1381 +include CopyCommon.gmk
1383 +################################################################################
1385 +ifeq ($(call isTargetOs, solaris), true)
1387 + SUNPKCS11_CFG_SRC := \
1388 + $(TOPDIR)/src/jdk.crypto.cryptoki/solaris/conf/security/sunpkcs11-solaris.cfg
1389 + SUNPKCS11_CFG_DST := $(CONF_DST_DIR)/security/sunpkcs11-solaris.cfg
1391 + $(SUNPKCS11_CFG_DST): $(SUNPKCS11_CFG_SRC)
1392 + $(call install-file)
1394 + SECURITY_PKCS11_CONF_FILES += $(SUNPKCS11_CFG_DST)
1396 + TARGETS := $(SUNPKCS11_CFG_DST)
1398 +endif
1400 +################################################################################
1401 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/modules/jdk.hotspot.agent/Lib.gmk jdk22u-jdk-22.0.2-ga/make/modules/jdk.hotspot.agent/Lib.gmk
1402 --- jdk22u-jdk-22.0.2-ga.orig/make/modules/jdk.hotspot.agent/Lib.gmk 2024-06-04 18:47:50.000000000 +0200
1403 +++ jdk22u-jdk-22.0.2-ga/make/modules/jdk.hotspot.agent/Lib.gmk 2024-08-17 19:34:03.842025654 +0200
1404 @@ -68,10 +68,11 @@
1405 CFLAGS := $(CFLAGS_JDKLIB) $(SA_CFLAGS), \
1406 CXXFLAGS := $(CXXFLAGS_JDKLIB) $(SA_CFLAGS) $(SA_CXXFLAGS), \
1407 EXTRA_SRC := $(LIBSA_EXTRA_SRC), \
1408 - LDFLAGS := $(LDFLAGS_JDKLIB) $(call SET_SHARED_LIBRARY_ORIGIN), \
1409 + LDFLAGS := $(LDFLAGS_JDKLIB) $(SA_LDFLAGS) $(call SET_SHARED_LIBRARY_ORIGIN), \
1410 LIBS := $(LIBCXX), \
1411 LIBS_unix := -ljava, \
1412 LIBS_linux := $(LIBDL), \
1413 + LIBS_solaris := -ldl -lstdc++ -lthread -lproc, \
1414 LIBS_macosx := -framework Foundation \
1415 -framework JavaRuntimeSupport -framework Security -framework CoreFoundation, \
1416 LIBS_windows := dbgeng.lib $(WIN_JAVA_LIB), \
1417 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/modules/jdk.jdwp.agent/Lib.gmk jdk22u-jdk-22.0.2-ga/make/modules/jdk.jdwp.agent/Lib.gmk
1418 --- jdk22u-jdk-22.0.2-ga.orig/make/modules/jdk.jdwp.agent/Lib.gmk 2024-06-04 18:47:50.000000000 +0200
1419 +++ jdk22u-jdk-22.0.2-ga/make/modules/jdk.jdwp.agent/Lib.gmk 2024-08-17 19:34:03.842415595 +0200
1420 @@ -38,6 +38,7 @@
1421 LDFLAGS := $(LDFLAGS_JDKLIB) \
1422 $(call SET_SHARED_LIBRARY_ORIGIN), \
1423 LIBS_linux := -lpthread, \
1424 + LIBS_solaris := -lnsl -lsocket, \
1425 LIBS_windows := $(JDKLIB_LIBS) ws2_32.lib iphlpapi.lib, \
1428 @@ -65,6 +66,7 @@
1429 $(call SET_SHARED_LIBRARY_ORIGIN), \
1430 LIBS := $(JDKLIB_LIBS), \
1431 LIBS_linux := $(LIBDL), \
1432 + LIBS_solaris := $(LIBDL), \
1433 LIBS_macosx := -liconv, \
1434 LIBS_aix := -liconv, \
1436 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/modules/jdk.management/Lib.gmk jdk22u-jdk-22.0.2-ga/make/modules/jdk.management/Lib.gmk
1437 --- jdk22u-jdk-22.0.2-ga.orig/make/modules/jdk.management/Lib.gmk 2024-06-04 18:47:50.000000000 +0200
1438 +++ jdk22u-jdk-22.0.2-ga/make/modules/jdk.management/Lib.gmk 2024-08-17 19:34:03.842824217 +0200
1439 @@ -35,7 +35,7 @@
1440 endif
1442 LIBMANAGEMENT_EXT_OPTIMIZATION := HIGH
1443 -ifeq ($(call isTargetOs, linux), true)
1444 +ifeq ($(call isTargetOs, solaris linux), true)
1445 ifeq ($(COMPILE_WITH_DEBUG_SYMBOLS), true)
1446 LIBMANAGEMENT_EXT_OPTIMIZATION := LOW
1447 endif
1448 @@ -49,6 +49,7 @@
1449 LDFLAGS := $(LDFLAGS_JDKLIB) \
1450 $(call SET_SHARED_LIBRARY_ORIGIN), \
1451 LIBS := $(JDKLIB_LIBS), \
1452 + LIBS_solaris := -lkstat, \
1453 LIBS_aix := -lperfstat,\
1454 LIBS_windows := jvm.lib psapi.lib $(WIN_JAVA_LIB) advapi32.lib, \
1456 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/modules/jdk.net/Lib.gmk jdk22u-jdk-22.0.2-ga/make/modules/jdk.net/Lib.gmk
1457 --- jdk22u-jdk-22.0.2-ga.orig/make/modules/jdk.net/Lib.gmk 2024-06-04 18:47:50.000000000 +0200
1458 +++ jdk22u-jdk-22.0.2-ga/make/modules/jdk.net/Lib.gmk 2024-08-17 19:34:03.843202202 +0200
1459 @@ -36,6 +36,7 @@
1460 LDFLAGS := $(LDFLAGS_JDKLIB) \
1461 $(call SET_SHARED_LIBRARY_ORIGIN), \
1462 LIBS_unix := -ljava, \
1463 + LIBS_solaris := -lsocket, \
1464 LIBS_linux := -ljvm, \
1465 LIBS_windows := jvm.lib ws2_32.lib $(WIN_JAVA_LIB), \
1467 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/modules/jdk.sctp/Lib.gmk jdk22u-jdk-22.0.2-ga/make/modules/jdk.sctp/Lib.gmk
1468 --- jdk22u-jdk-22.0.2-ga.orig/make/modules/jdk.sctp/Lib.gmk 2024-06-04 18:47:50.000000000 +0200
1469 +++ jdk22u-jdk-22.0.2-ga/make/modules/jdk.sctp/Lib.gmk 2024-08-17 19:34:03.843560105 +0200
1470 @@ -42,6 +42,7 @@
1471 $(call SET_SHARED_LIBRARY_ORIGIN), \
1472 LIBS_unix := -lnio -lnet -ljava -ljvm, \
1473 LIBS_linux := -lpthread $(LIBDL), \
1474 + LIBS_solaris := -lsocket, \
1477 TARGETS += $(BUILD_LIBSCTP)
1478 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/RunTestsPrebuilt.gmk jdk22u-jdk-22.0.2-ga/make/RunTestsPrebuilt.gmk
1479 --- jdk22u-jdk-22.0.2-ga.orig/make/RunTestsPrebuilt.gmk 2024-06-04 18:47:50.000000000 +0200
1480 +++ jdk22u-jdk-22.0.2-ga/make/RunTestsPrebuilt.gmk 2024-08-17 19:34:03.827690284 +0200
1481 @@ -168,6 +168,8 @@
1482 OPENJDK_TARGET_OS := linux
1483 else ifeq ($(UNAME_OS), Darwin)
1484 OPENJDK_TARGET_OS := macosx
1485 + else ifeq ($(UNAME_OS), SunOS)
1486 + OPENJDK_TARGET_OS := solaris
1487 else
1488 OPENJDK_TARGET_OS := $(UNAME_OS)
1489 endif
1490 @@ -180,15 +182,28 @@
1491 # Assume little endian unless otherwise specified
1492 OPENJDK_TARGET_CPU_ENDIAN := little
1494 -UNAME_CPU := $(shell $(UNAME) -m)
1495 -ifeq ($(UNAME_CPU), i686)
1496 - OPENJDK_TARGET_CPU := x86
1497 - OPENJDK_TARGET_CPU_BITS := 32
1498 -else
1499 - # Assume all others are 64-bit. We use the same CPU name as uname for
1500 - # at least x86_64 and aarch64.
1501 - OPENJDK_TARGET_CPU := $(UNAME_CPU)
1502 +ifeq ($(OPENJDK_TARGET_OS), solaris)
1503 + # On solaris, use uname -p
1504 + UNAME_CPU := $(shell $(UNAME) -p)
1505 + # Assume 64-bit platform
1506 OPENJDK_TARGET_CPU_BITS := 64
1507 + ifeq ($(UNAME_CPU), i386)
1508 + OPENJDK_TARGET_CPU := x86_64
1509 + else
1510 + OPENJDK_TARGET_CPU := $(UNAME_CPU)
1511 + endif
1512 +else
1513 + # ... all others use uname -m
1514 + UNAME_CPU := $(shell $(UNAME) -m)
1515 + ifeq ($(UNAME_CPU), i686)
1516 + OPENJDK_TARGET_CPU := x86
1517 + OPENJDK_TARGET_CPU_BITS := 32
1518 + else
1519 + # Assume all others are 64-bit. We use the same CPU name as uname for
1520 + # at least x86_64 and aarch64.
1521 + OPENJDK_TARGET_CPU := $(UNAME_CPU)
1522 + OPENJDK_TARGET_CPU_BITS := 64
1523 + endif
1524 endif
1526 OPENJDK_TARGET_CPU_ARCH := $(OPENJDK_TARGET_CPU)
1527 @@ -213,6 +228,11 @@
1528 else ifeq ($(OPENJDK_TARGET_OS), macosx)
1529 NUM_CORES := $(shell /usr/sbin/sysctl -n hw.ncpu)
1530 MEMORY_SIZE := $(shell $(EXPR) `/usr/sbin/sysctl -n hw.memsize` / 1024 / 1024)
1531 +else ifeq ($(OPENJDK_TARGET_OS), solaris)
1532 + NUM_CORES := $(shell /usr/sbin/psrinfo -v | $(GREP) -c on-line)
1533 + MEMORY_SIZE := $(shell \
1534 + /usr/sbin/prtconf 2> /dev/null | $(GREP) "^Memory [Ss]ize" | $(AWK) '{print $$3}' \
1536 else ifeq ($(OPENJDK_TARGET_OS), windows)
1537 NUM_CORES := $(NUMBER_OF_PROCESSORS)
1538 MEMORY_SIZE := $(shell \
1539 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/RunTestsPrebuiltSpec.gmk jdk22u-jdk-22.0.2-ga/make/RunTestsPrebuiltSpec.gmk
1540 --- jdk22u-jdk-22.0.2-ga.orig/make/RunTestsPrebuiltSpec.gmk 2024-06-04 18:47:50.000000000 +0200
1541 +++ jdk22u-jdk-22.0.2-ga/make/RunTestsPrebuiltSpec.gmk 2024-08-17 19:34:03.828068385 +0200
1542 @@ -173,6 +173,16 @@
1543 FILE := file
1544 ULIMIT := ulimit
1546 +# On Solaris gnu versions of some tools are required.
1547 +ifeq ($(OPENJDK_BUILD_OS), solaris)
1548 + AWK := gawk
1549 + GREP := ggrep
1550 + EGREP := ggrep -E
1551 + FGREP := grep -F
1552 + SED := gsed
1553 + TAR := gtar
1554 +endif
1556 ifeq ($(OPENJDK_BUILD_OS), windows)
1557 PATHTOOL := cygpath
1558 endif
1559 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/scripts/compare_exceptions.sh.incl jdk22u-jdk-22.0.2-ga/make/scripts/compare_exceptions.sh.incl
1560 --- jdk22u-jdk-22.0.2-ga.orig/make/scripts/compare_exceptions.sh.incl 2024-06-04 18:47:50.000000000 +0200
1561 +++ jdk22u-jdk-22.0.2-ga/make/scripts/compare_exceptions.sh.incl 2024-08-17 19:34:03.844671353 +0200
1562 @@ -45,6 +45,20 @@
1563 ./hotspot/gtest/server/libjvm.so
1566 +elif [ "$OPENJDK_TARGET_OS" = "solaris" ]; then
1567 + SKIP_BIN_DIFF="true"
1568 + SKIP_FULLDUMP_DIFF="true"
1569 + MAX_KNOWN_DIS_DIFF_SIZE="3000"
1570 + SORT_SYMBOLS="
1571 + ./lib/libfontmanager.so
1572 + ./lib/libjimage.so
1573 + ./lib/server/libjvm.so
1574 + ./hotspot/gtest/server/libjvm.so
1576 + KNOWN_DIS_DIFF="
1577 + ./lib/libfontmanager.so
1579 + STRIP_TESTS_BEFORE_COMPARE="true"
1580 elif [ "$OPENJDK_TARGET_OS" = "windows" ]; then
1581 SKIP_BIN_DIFF="true"
1582 SKIP_FULLDUMP_DIFF="true"
1583 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/scripts/compare.sh jdk22u-jdk-22.0.2-ga/make/scripts/compare.sh
1584 --- jdk22u-jdk-22.0.2-ga.orig/make/scripts/compare.sh 2024-06-04 18:47:50.000000000 +0200
1585 +++ jdk22u-jdk-22.0.2-ga/make/scripts/compare.sh 2024-08-17 19:34:03.844327437 +0200
1586 @@ -73,7 +73,14 @@
1587 # Disassembly diff filters. These filters try to filter out ephemeral parts of the
1588 # disassembly, such as hard-coded addresses, to be able to catch "actual" differences.
1590 -if [ "$OPENJDK_TARGET_OS" = "windows" ]; then
1591 +if [ "$OPENJDK_TARGET_OS" = "solaris" ]; then
1592 + if [ "$OPENJDK_TARGET_CPU" = "x86_64" ]; then
1593 + # Random strings looking like this differ: <.XAKoKoPIac2W0OA.
1594 + DIS_DIFF_FILTER="$SED \
1595 + -e 's/<\.[A-Za-z0-9]\{\15}\./<.SYM./' \
1597 + fi
1598 +elif [ "$OPENJDK_TARGET_OS" = "windows" ]; then
1599 if [ "$OPENJDK_TARGET_CPU" = "x86" ]; then
1600 DIS_DIFF_FILTER="$SED -r \
1601 -e 's/^ [0-9A-F]{16}: //' \
1602 @@ -440,7 +447,14 @@
1605 CONTENTS_DIFF_FILE=$WORK_DIR/$ZIP_FILE.diff
1606 - $DIFF -rq $OTHER_UNZIPDIR $THIS_UNZIPDIR > $CONTENTS_DIFF_FILE
1607 + # On solaris, there is no -q option.
1608 + if [ "$OPENJDK_TARGET_OS" = "solaris" ]; then
1609 + $DIFF -r $OTHER_UNZIPDIR $THIS_UNZIPDIR \
1610 + | $GREP -v -e "^<" -e "^>" -e "^Common subdirectories:" \
1611 + > $CONTENTS_DIFF_FILE
1612 + else
1613 + $DIFF -rq $OTHER_UNZIPDIR $THIS_UNZIPDIR > $CONTENTS_DIFF_FILE
1614 + fi
1616 ONLY_OTHER=$($GREP "^Only in $OTHER_UNZIPDIR" $CONTENTS_DIFF_FILE)
1617 ONLY_THIS=$($GREP "^Only in $THIS_UNZIPDIR" $CONTENTS_DIFF_FILE)
1618 @@ -460,8 +474,14 @@
1621 if [ "$CMP_ZIPS_CONTENTS" = "true" ]; then
1622 - DIFFING_FILES=$($GREP -e "differ$" $CONTENTS_DIFF_FILE \
1623 - | $CUT -f 2 -d ' ' | $SED "s|$OTHER_UNZIPDIR/||g")
1624 + if [ "$OPENJDK_TARGET_OS" = "solaris" ]; then
1625 + DIFFING_FILES=$($GREP -e 'differ$' -e '^diff ' $CONTENTS_DIFF_FILE \
1626 + | $SED -e 's/^Files //g' -e 's/diff -r //g' | $CUT -f 1 -d ' ' \
1627 + | $SED "s|$OTHER_UNZIPDIR/||g")
1628 + else
1629 + DIFFING_FILES=$($GREP -e "differ$" $CONTENTS_DIFF_FILE \
1630 + | $CUT -f 2 -d ' ' | $SED "s|$OTHER_UNZIPDIR/||g")
1631 + fi
1633 # Separate executable/library files from other files in zip.
1634 DIFFING_TEXT_FILES=
1635 @@ -806,6 +826,10 @@
1636 # to filter out that extra information.
1637 $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
1638 $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
1639 + elif [ "$OPENJDK_TARGET_OS" = "solaris" ]; then
1640 + # Some symbols get seemingly random 15 character prefixes. Filter them out.
1641 + $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
1642 + $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
1643 elif [ "$OPENJDK_TARGET_OS" = "aix" ]; then
1644 $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
1645 $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
1646 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/scripts/hide_important_warnings_from_javac.sh jdk22u-jdk-22.0.2-ga/make/scripts/hide_important_warnings_from_javac.sh
1647 --- jdk22u-jdk-22.0.2-ga.orig/make/scripts/hide_important_warnings_from_javac.sh 2024-06-04 18:47:50.000000000 +0200
1648 +++ jdk22u-jdk-22.0.2-ga/make/scripts/hide_important_warnings_from_javac.sh 2024-08-17 19:34:03.845008602 +0200
1649 @@ -22,8 +22,13 @@
1650 # questions.
1653 -GREP=grep
1655 +if [ -x /usr/bin/ggrep ] ; then
1656 + # Gnu grep on Solaris
1657 + # (reference configure and build/solaris-i586-clientANDserver-release/spec.gmk
1658 + GREP=/usr/bin/ggrep
1659 +else
1660 + GREP=grep
1663 EXP="Note: Some input files use or override a deprecated API."
1664 EXP="${EXP}|Note: Recompile with -Xlint:deprecation for details."
1665 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/test/JtregNativeHotspot.gmk jdk22u-jdk-22.0.2-ga/make/test/JtregNativeHotspot.gmk
1666 --- jdk22u-jdk-22.0.2-ga.orig/make/test/JtregNativeHotspot.gmk 2024-06-04 18:47:50.000000000 +0200
1667 +++ jdk22u-jdk-22.0.2-ga/make/test/JtregNativeHotspot.gmk 2024-08-17 19:34:03.845808509 +0200
1668 @@ -859,6 +859,10 @@
1670 BUILD_HOTSPOT_JTREG_EXECUTABLES_LIBS_exesigtest := -ljvm
1672 +ifeq ($(call isTargetOs, solaris), true)
1673 + BUILD_HOTSPOT_JTREG_EXCLUDE += libterminatedThread.c
1674 +endif
1676 ifeq ($(call isTargetOs, windows), true)
1677 BUILD_HOTSPOT_JTREG_EXECUTABLES_CFLAGS_exeFPRegs := -MT
1678 BUILD_HOTSPOT_JTREG_EXCLUDE += exesigtest.c libterminatedThread.c libTestJNI.c libCompleteExit.c libMonitorWithDeadObjectTest.c libTestPsig.c exeGetCreatedJavaVMs.c
1679 diff -Nru jdk22u-jdk-22.0.2-ga.orig/make/test/JtregNativeJdk.gmk jdk22u-jdk-22.0.2-ga/make/test/JtregNativeJdk.gmk
1680 --- jdk22u-jdk-22.0.2-ga.orig/make/test/JtregNativeJdk.gmk 2024-06-04 18:47:50.000000000 +0200
1681 +++ jdk22u-jdk-22.0.2-ga/make/test/JtregNativeJdk.gmk 2024-08-17 19:34:03.846189811 +0200
1682 @@ -107,6 +107,9 @@
1683 ifeq ($(call isTargetOs, linux), true)
1684 BUILD_JDK_JTREG_LIBRARIES_LIBS_libInheritedChannel := -ljava
1685 BUILD_JDK_JTREG_EXECUTABLES_LIBS_exelauncher := -ldl
1686 + else ifeq ($(call isTargetOs, solaris), true)
1687 + BUILD_JDK_JTREG_LIBRARIES_LIBS_libInheritedChannel := -ljava -lsocket -lnsl
1688 + BUILD_JDK_JTREG_EXECUTABLES_LIBS_exelauncher := -lthread -ldl
1689 endif
1690 BUILD_JDK_JTREG_EXECUTABLES_LIBS_exeJliLaunchTest := -ljli
1691 BUILD_JDK_JTREG_EXECUTABLES_LIBS_exeCallerAccessTest := -ljvm
1692 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/cpu/x86/globalDefinitions_x86.hpp jdk22u-jdk-22.0.2-ga/src/hotspot/cpu/x86/globalDefinitions_x86.hpp
1693 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/cpu/x86/globalDefinitions_x86.hpp 2024-06-04 18:47:50.000000000 +0200
1694 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/cpu/x86/globalDefinitions_x86.hpp 2024-08-17 19:34:03.846674731 +0200
1695 @@ -68,7 +68,7 @@
1696 #define INCLUDE_RTM_OPT 1
1697 #endif
1699 -#if defined(LINUX) || defined(__APPLE__)
1700 +#if defined(LINUX) || defined(SOLARIS) || defined(__APPLE__)
1701 #define SUPPORT_RESERVED_STACK_AREA
1702 #endif
1704 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os/posix/include/jvm_md.h jdk22u-jdk-22.0.2-ga/src/hotspot/os/posix/include/jvm_md.h
1705 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os/posix/include/jvm_md.h 2024-06-04 18:47:50.000000000 +0200
1706 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/os/posix/include/jvm_md.h 2024-08-17 19:34:03.847132801 +0200
1707 @@ -54,7 +54,7 @@
1708 #endif
1709 #define JNI_LIB_NAME(NAME) JNI_LIB_PREFIX NAME JNI_LIB_SUFFIX
1711 -#if defined(AIX)
1712 +#if defined(AIX) || defined(SOLARIS)
1713 #define JVM_MAXPATHLEN MAXPATHLEN
1714 #else
1715 // Hack: MAXPATHLEN is 4095 on some Linux and 4096 on others. This may
1716 @@ -87,8 +87,14 @@
1717 #define JVM_SIGTERM SIGTERM
1719 #define BREAK_SIGNAL SIGQUIT /* Thread dumping support. */
1720 +#ifdef SOLARIS
1721 +#define ASYNC_SIGNAL SIGJVM2 /* Event-based suspend/resume support */
1722 +#endif // SOLARIS
1723 #define SHUTDOWN1_SIGNAL SIGHUP /* Shutdown Hooks support. */
1724 #define SHUTDOWN2_SIGNAL SIGINT
1725 #define SHUTDOWN3_SIGNAL SIGTERM
1727 +/* With 1.4.1 libjsig added versioning: used in os_solaris.cpp and jsig.c */
1728 +#define JSIG_VERSION_1_4_1 0x30140100
1730 #endif /* !_JAVASOFT_JVM_MD_H_ */
1731 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os/posix/os_posix.cpp jdk22u-jdk-22.0.2-ga/src/hotspot/os/posix/os_posix.cpp
1732 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os/posix/os_posix.cpp 2024-06-04 18:47:50.000000000 +0200
1733 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/os/posix/os_posix.cpp 2024-08-17 19:34:03.847883227 +0200
1734 @@ -511,7 +511,7 @@
1735 st->print("%d", sysconf(_SC_CHILD_MAX));
1737 print_rlimit(st, ", THREADS", RLIMIT_THREADS);
1738 -#else
1739 +#elif !defined(SOLARIS)
1740 print_rlimit(st, ", NPROC", RLIMIT_NPROC);
1741 #endif
1743 @@ -529,6 +529,12 @@
1744 print_rlimit(st, ", MEMLOCK", RLIMIT_MEMLOCK, true);
1745 #endif
1747 +#if defined(SOLARIS)
1748 + // maximum size of mapped address space of a process in bytes;
1749 + // if the limit is exceeded, mmap and brk fail
1750 + print_rlimit(st, ", VMEM", RLIMIT_VMEM, true);
1751 +#endif
1753 // MacOS; The maximum size (in bytes) to which a process's resident set size may grow.
1754 #if defined(__APPLE__)
1755 print_rlimit(st, ", RSS", RLIMIT_RSS, true);
1756 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os/posix/os_posix.inline.hpp jdk22u-jdk-22.0.2-ga/src/hotspot/os/posix/os_posix.inline.hpp
1757 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os/posix/os_posix.inline.hpp 2024-06-04 18:47:50.000000000 +0200
1758 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/os/posix/os_posix.inline.hpp 2024-08-17 19:34:03.848245577 +0200
1759 @@ -34,8 +34,10 @@
1760 #include <sys/socket.h>
1761 #include <netdb.h>
1763 +#ifndef SOLARIS
1764 // Aix does not have NUMA support but need these for compilation.
1765 inline bool os::numa_has_group_homing() { AIX_ONLY(ShouldNotReachHere();) return false; }
1766 +#endif // !SOLARIS
1768 // Platform Mutex/Monitor implementation
1770 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os/posix/vmError_posix.cpp jdk22u-jdk-22.0.2-ga/src/hotspot/os/posix/vmError_posix.cpp
1771 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os/posix/vmError_posix.cpp 2024-06-04 18:47:50.000000000 +0200
1772 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/os/posix/vmError_posix.cpp 2024-08-17 19:34:03.848600505 +0200
1773 @@ -40,6 +40,9 @@
1774 #include <sys/syscall.h>
1775 #include <unistd.h>
1776 #endif
1777 +#ifdef SOLARIS
1778 +#include <thread.h>
1779 +#endif
1780 #ifdef AIX
1781 #include <unistd.h>
1782 #endif
1783 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os/solaris/attachListener_solaris.cpp jdk22u-jdk-22.0.2-ga/src/hotspot/os/solaris/attachListener_solaris.cpp
1784 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os/solaris/attachListener_solaris.cpp 1970-01-01 01:00:00.000000000 +0100
1785 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/os/solaris/attachListener_solaris.cpp 2024-08-17 19:34:03.895296712 +0200
1786 @@ -0,0 +1,715 @@
1788 + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
1789 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1791 + * This code is free software; you can redistribute it and/or modify it
1792 + * under the terms of the GNU General Public License version 2 only, as
1793 + * published by the Free Software Foundation.
1795 + * This code is distributed in the hope that it will be useful, but WITHOUT
1796 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1797 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1798 + * version 2 for more details (a copy is included in the LICENSE file that
1799 + * accompanied this code).
1801 + * You should have received a copy of the GNU General Public License version
1802 + * 2 along with this work; if not, write to the Free Software Foundation,
1803 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1805 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1806 + * or visit www.oracle.com if you need additional information or have any
1807 + * questions.
1809 + */
1811 +#include "precompiled.hpp"
1812 +#include "logging/log.hpp"
1813 +#include "runtime/interfaceSupport.inline.hpp"
1814 +#include "runtime/os.inline.hpp"
1815 +#include "services/attachListener.hpp"
1816 +#include "services/dtraceAttacher.hpp"
1817 +#include "utilities/vmError.hpp"
1819 +#include <door.h>
1820 +#include <limits.h>
1821 +#include <string.h>
1822 +#include <signal.h>
1823 +#include <sys/types.h>
1824 +#include <sys/socket.h>
1825 +#include <sys/stat.h>
1827 +// stropts.h uses STR in stream ioctl defines
1828 +#undef STR
1829 +#include <stropts.h>
1830 +#undef STR
1831 +#define STR(a) #a
1833 +// The attach mechanism on Solaris is implemented using the Doors IPC
1834 +// mechanism. The first tool to attempt to attach causes the attach
1835 +// listener thread to startup. This thread creats a door that is
1836 +// associated with a function that enqueues an operation to the attach
1837 +// listener. The door is attached to a file in the file system so that
1838 +// client (tools) can locate it. To enqueue an operation to the VM the
1839 +// client calls through the door which invokes the enqueue function in
1840 +// this process. The credentials of the client are checked and if the
1841 +// effective uid matches this process then the operation is enqueued.
1842 +// When an operation completes the attach listener is required to send the
1843 +// operation result and any result data to the client. In this implementation
1844 +// the result is returned via a UNIX domain socket. A pair of connected
1845 +// sockets (socketpair) is created in the enqueue function and the file
1846 +// descriptor for one of the sockets is returned to the client as the
1847 +// return from the door call. The other end is retained in this process.
1848 +// When the operation completes the result is sent to the client and
1849 +// the socket is closed.
1851 +// forward reference
1852 +class SolarisAttachOperation;
1854 +class SolarisAttachListener: AllStatic {
1855 + private:
1857 + // the path to which we attach the door file descriptor
1858 + static char _door_path[PATH_MAX+1];
1859 + static volatile bool _has_door_path;
1861 + // door descriptor returned by door_create
1862 + static int _door_descriptor;
1864 + static bool _atexit_registered;
1866 + // mutex to protect operation list
1867 + static pthread_mutex_t _mutex;
1869 + // semaphore to wakeup listener thread
1870 + static sema_t _wakeup;
1872 + static pthread_mutex_t* mutex() { return &_mutex; }
1873 + static sema_t* wakeup() { return &_wakeup; }
1875 + // enqueued operation list
1876 + static SolarisAttachOperation* _head;
1877 + static SolarisAttachOperation* _tail;
1879 + static SolarisAttachOperation* head() { return _head; }
1880 + static void set_head(SolarisAttachOperation* head) { _head = head; }
1882 + static SolarisAttachOperation* tail() { return _tail; }
1883 + static void set_tail(SolarisAttachOperation* tail) { _tail = tail; }
1885 + // create the door
1886 + static int create_door();
1888 + public:
1889 + enum {
1890 + ATTACH_PROTOCOL_VER = 1 // protocol version
1891 + };
1892 + enum {
1893 + ATTACH_ERROR_BADREQUEST = 100, // error code returned by
1894 + ATTACH_ERROR_BADVERSION = 101, // the door call
1895 + ATTACH_ERROR_RESOURCE = 102,
1896 + ATTACH_ERROR_INTERNAL = 103,
1897 + ATTACH_ERROR_DENIED = 104
1898 + };
1900 + static void set_door_path(char* path) {
1901 + if (path == NULL) {
1902 + _door_path[0] = '\0';
1903 + _has_door_path = false;
1904 + } else {
1905 + strncpy(_door_path, path, PATH_MAX);
1906 + _door_path[PATH_MAX] = '\0'; // ensure it's nul terminated
1907 + _has_door_path = true;
1911 + static void set_door_descriptor(int dd) { _door_descriptor = dd; }
1913 + // initialize the listener
1914 + static int init();
1916 + static bool has_door_path() { return _has_door_path; }
1917 + static char* door_path() { return _door_path; }
1918 + static int door_descriptor() { return _door_descriptor; }
1920 + // enqueue an operation
1921 + static void enqueue(SolarisAttachOperation* op);
1923 + // dequeue an operation
1924 + static SolarisAttachOperation* dequeue();
1928 +// SolarisAttachOperation is an AttachOperation that additionally encapsulates
1929 +// a socket connection to the requesting client/tool. SolarisAttachOperation
1930 +// can additionally be held in a linked list.
1932 +class SolarisAttachOperation: public AttachOperation {
1933 + private:
1934 + friend class SolarisAttachListener;
1936 + // connection to client
1937 + int _socket;
1939 + // linked list support
1940 + SolarisAttachOperation* _next;
1942 + SolarisAttachOperation* next() { return _next; }
1943 + void set_next(SolarisAttachOperation* next) { _next = next; }
1945 + public:
1946 + void complete(jint res, bufferedStream* st);
1948 + int socket() const { return _socket; }
1949 + void set_socket(int s) { _socket = s; }
1951 + SolarisAttachOperation(char* name) : AttachOperation(name) {
1952 + set_socket(-1);
1953 + set_next(NULL);
1957 +// statics
1958 +char SolarisAttachListener::_door_path[PATH_MAX+1];
1959 +volatile bool SolarisAttachListener::_has_door_path;
1960 +int SolarisAttachListener::_door_descriptor = -1;
1961 +bool SolarisAttachListener::_atexit_registered = false;
1962 +pthread_mutex_t SolarisAttachListener::_mutex;
1963 +sema_t SolarisAttachListener::_wakeup;
1964 +SolarisAttachOperation* SolarisAttachListener::_head = NULL;
1965 +SolarisAttachOperation* SolarisAttachListener::_tail = NULL;
1967 +// Supporting class to help split a buffer into individual components
1968 +class ArgumentIterator : public StackObj {
1969 + private:
1970 + char* _pos;
1971 + char* _end;
1972 + public:
1973 + ArgumentIterator(char* arg_buffer, size_t arg_size) {
1974 + _pos = arg_buffer;
1975 + _end = _pos + arg_size - 1;
1977 + char* next() {
1978 + if (*_pos == '\0') {
1979 + // advance the iterator if possible (null arguments)
1980 + if (_pos < _end) {
1981 + _pos += 1;
1983 + return NULL;
1985 + char* res = _pos;
1986 + char* next_pos = strchr(_pos, '\0');
1987 + if (next_pos < _end) {
1988 + next_pos++;
1990 + _pos = next_pos;
1991 + return res;
1995 +// Calls from the door function to check that the client credentials
1996 +// match this process. Returns 0 if credentials okay, otherwise -1.
1997 +static int check_credentials() {
1998 + ucred_t *cred_info = NULL;
1999 + int ret = -1; // deny by default
2001 + // get client credentials
2002 + if (door_ucred(&cred_info) == -1) {
2003 + return -1; // unable to get them, deny
2006 + // get euid/egid from ucred_free
2007 + uid_t ucred_euid = ucred_geteuid(cred_info);
2008 + gid_t ucred_egid = ucred_getegid(cred_info);
2010 + // check that the effective uid/gid matches
2011 + if (os::Posix::matches_effective_uid_and_gid_or_root(ucred_euid, ucred_egid)) {
2012 + ret = 0; // allow
2015 + ucred_free(cred_info);
2016 + return ret;
2020 +// Parses the argument buffer to create an AttachOperation that we should
2021 +// enqueue to the attach listener.
2022 +// The buffer is expected to be formatted as follows:
2023 +// <ver>0<cmd>0<arg>0<arg>0<arg>0
2024 +// where <ver> is the version number (must be "1"), <cmd> is the command
2025 +// name ("load, "datadump", ...) and <arg> is an argument.
2027 +static SolarisAttachOperation* create_operation(char* argp, size_t arg_size, int* err) {
2028 + // assume bad request until parsed
2029 + *err = SolarisAttachListener::ATTACH_ERROR_BADREQUEST;
2031 + if (arg_size < 2 || argp[arg_size-1] != '\0') {
2032 + return NULL; // no ver or not null terminated
2035 + // Use supporting class to iterate over the buffer
2036 + ArgumentIterator args(argp, arg_size);
2038 + // First check the protocol version
2039 + char* ver = args.next();
2040 + if (ver == NULL) {
2041 + return NULL;
2043 + if (atoi(ver) != SolarisAttachListener::ATTACH_PROTOCOL_VER) {
2044 + *err = SolarisAttachListener::ATTACH_ERROR_BADVERSION;
2045 + return NULL;
2048 + // Get command name and create the operation
2049 + char* name = args.next();
2050 + if (name == NULL || strlen(name) > AttachOperation::name_length_max) {
2051 + return NULL;
2053 + SolarisAttachOperation* op = new SolarisAttachOperation(name);
2055 + // Iterate over the arguments
2056 + for (int i=0; i<AttachOperation::arg_count_max; i++) {
2057 + char* arg = args.next();
2058 + if (arg == NULL) {
2059 + op->set_arg(i, NULL);
2060 + } else {
2061 + if (strlen(arg) > AttachOperation::arg_length_max) {
2062 + delete op;
2063 + return NULL;
2065 + op->set_arg(i, arg);
2069 + // return operation
2070 + *err = 0;
2071 + return op;
2074 +// This is door function which the client executes via a door_call.
2075 +extern "C" {
2076 + static void enqueue_proc(void* cookie, char* argp, size_t arg_size,
2077 + door_desc_t* dt, uint_t n_desc)
2079 + int return_fd = -1;
2080 + SolarisAttachOperation* op = NULL;
2082 + // wait up to 10 seconds for listener to be up and running
2083 + jint res = 0;
2084 + int sleep_count = 0;
2085 + while (!AttachListener::is_initialized()) {
2086 + sleep(1); // 1 second
2087 + sleep_count++;
2088 + if (sleep_count > 10) { // try for 10 seconds
2089 + debug_only(warning("door_call when not enabled"));
2090 + res = (jint)SolarisAttachListener::ATTACH_ERROR_INTERNAL;
2091 + break;
2095 + // check client credentials
2096 + if (res == 0) {
2097 + if (check_credentials() != 0) {
2098 + res = (jint)SolarisAttachListener::ATTACH_ERROR_DENIED;
2102 + // if we are stopped at ShowMessageBoxOnError then maybe we can
2103 + // load a diagnostic library
2104 + if (res == 0 && VMError::is_error_reported()) {
2105 + if (ShowMessageBoxOnError) {
2106 + // TBD - support loading of diagnostic library here
2109 + // can't enqueue operation after fatal error
2110 + res = (jint)SolarisAttachListener::ATTACH_ERROR_RESOURCE;
2113 + // create the operation
2114 + if (res == 0) {
2115 + int err;
2116 + op = create_operation(argp, arg_size, &err);
2117 + res = (op == NULL) ? (jint)err : 0;
2120 + // create a pair of connected sockets. Store the file descriptor
2121 + // for one end in the operation and enqueue the operation. The
2122 + // file descriptor for the other end wil be returned to the client.
2123 + if (res == 0) {
2124 + int s[2];
2125 + if (socketpair(PF_UNIX, SOCK_STREAM, 0, s) < 0) {
2126 + delete op;
2127 + res = (jint)SolarisAttachListener::ATTACH_ERROR_RESOURCE;
2128 + } else {
2129 + op->set_socket(s[0]);
2130 + return_fd = s[1];
2131 + SolarisAttachListener::enqueue(op);
2135 + // Return 0 (success) + file descriptor, or non-0 (error)
2136 + if (res == 0) {
2137 + door_desc_t desc;
2138 + // DOOR_RELEASE flag makes sure fd is closed after passing it to
2139 + // the client. See door_return(3DOOR) man page.
2140 + desc.d_attributes = DOOR_DESCRIPTOR | DOOR_RELEASE;
2141 + desc.d_data.d_desc.d_descriptor = return_fd;
2142 + door_return((char*)&res, sizeof(res), &desc, 1);
2143 + } else {
2144 + door_return((char*)&res, sizeof(res), NULL, 0);
2149 +// atexit hook to detach the door and remove the file
2150 +extern "C" {
2151 + static void listener_cleanup() {
2152 + int dd = SolarisAttachListener::door_descriptor();
2153 + if (dd >= 0) {
2154 + SolarisAttachListener::set_door_descriptor(-1);
2155 + ::close(dd);
2157 + if (SolarisAttachListener::has_door_path()) {
2158 + char* path = SolarisAttachListener::door_path();
2159 + ::fdetach(path);
2160 + ::unlink(path);
2161 + SolarisAttachListener::set_door_path(NULL);
2166 +// Create the door
2167 +int SolarisAttachListener::create_door() {
2168 + char door_path[PATH_MAX+1];
2169 + char initial_path[PATH_MAX+1];
2170 + int fd, res;
2172 + // register exit function
2173 + if (!_atexit_registered) {
2174 + _atexit_registered = true;
2175 + ::atexit(listener_cleanup);
2178 + // create the door descriptor
2179 + int dd = ::door_create(enqueue_proc, NULL, 0);
2180 + if (dd < 0) {
2181 + return -1;
2184 + // create initial file to attach door descriptor
2185 + snprintf(door_path, sizeof(door_path), "%s/.java_pid%d",
2186 + os::get_temp_directory(), os::current_process_id());
2187 + snprintf(initial_path, sizeof(initial_path), "%s.tmp", door_path);
2188 + RESTARTABLE(::creat(initial_path, S_IRUSR | S_IWUSR), fd);
2189 + if (fd == -1) {
2190 + log_debug(attach)("attempt to create door file %s failed (%d)", initial_path, errno);
2191 + ::door_revoke(dd);
2192 + return -1;
2194 + assert(fd >= 0, "bad file descriptor");
2195 + ::close(fd);
2197 + // attach the door descriptor to the file
2198 + if ((res = ::fattach(dd, initial_path)) == -1) {
2199 + // if busy then detach and try again
2200 + if (errno == EBUSY) {
2201 + ::fdetach(initial_path);
2202 + res = ::fattach(dd, initial_path);
2204 + if (res == -1) {
2205 + log_debug(attach)("unable to create door - fattach failed (%d)", errno);
2206 + ::door_revoke(dd);
2207 + dd = -1;
2211 + // rename file so that clients can attach
2212 + if (dd >= 0) {
2213 + if (::rename(initial_path, door_path) == -1) {
2214 + ::close(dd);
2215 + ::fdetach(initial_path);
2216 + log_debug(attach)("unable to create door - rename %s to %s failed (%d)", initial_path, door_path, errno);
2217 + dd = -1;
2220 + if (dd >= 0) {
2221 + set_door_descriptor(dd);
2222 + set_door_path(door_path);
2223 + log_trace(attach)("door file %s created succesfully", door_path);
2224 + } else {
2225 + // unable to create door, attach it to file, or rename file into place
2226 + ::unlink(initial_path);
2227 + return -1;
2230 + return 0;
2233 +// Initialization - create the door, locks, and other initialization
2234 +int SolarisAttachListener::init() {
2235 + if (create_door()) {
2236 + return -1;
2239 + int status = pthread_mutex_init(&_mutex, NULL);
2240 + assert_status(status==0, status, "mutex_init");
2242 + status = ::sema_init(&_wakeup, 0, NULL, NULL);
2243 + assert_status(status==0, status, "sema_init");
2245 + set_head(NULL);
2246 + set_tail(NULL);
2248 + return 0;
2251 +// Dequeue an operation
2252 +SolarisAttachOperation* SolarisAttachListener::dequeue() {
2253 + for (;;) {
2254 + int res;
2256 + // wait for somebody to enqueue something
2257 + while ((res = ::sema_wait(wakeup())) == EINTR)
2259 + if (res) {
2260 + warning("sema_wait failed: %s", os::strerror(res));
2261 + return NULL;
2264 + // lock the list
2265 + res = pthread_mutex_lock(mutex());
2266 + assert(res == 0, "mutex_lock failed");
2268 + // remove the head of the list
2269 + SolarisAttachOperation* op = head();
2270 + if (op != NULL) {
2271 + set_head(op->next());
2272 + if (head() == NULL) {
2273 + set_tail(NULL);
2277 + // unlock
2278 + pthread_mutex_unlock(mutex());
2280 + // if we got an operation when return it.
2281 + if (op != NULL) {
2282 + return op;
2287 +// Enqueue an operation
2288 +void SolarisAttachListener::enqueue(SolarisAttachOperation* op) {
2289 + // lock list
2290 + int res = pthread_mutex_lock(mutex());
2291 + assert(res == 0, "mutex_lock failed");
2293 + // enqueue at tail
2294 + op->set_next(NULL);
2295 + if (head() == NULL) {
2296 + set_head(op);
2297 + } else {
2298 + tail()->set_next(op);
2300 + set_tail(op);
2302 + // wakeup the attach listener
2303 + RESTARTABLE(::sema_post(wakeup()), res);
2304 + assert(res == 0, "sema_post failed");
2306 + // unlock
2307 + pthread_mutex_unlock(mutex());
2311 +// support function - writes the (entire) buffer to a socket
2312 +static int write_fully(int s, char* buf, int len) {
2313 + do {
2314 + int n = ::write(s, buf, len);
2315 + if (n == -1) {
2316 + if (errno != EINTR) return -1;
2317 + } else {
2318 + buf += n;
2319 + len -= n;
2322 + while (len > 0);
2323 + return 0;
2326 +// Complete an operation by sending the operation result and any result
2327 +// output to the client. At this time the socket is in blocking mode so
2328 +// potentially we can block if there is a lot of data and the client is
2329 +// non-responsive. For most operations this is a non-issue because the
2330 +// default send buffer is sufficient to buffer everything. In the future
2331 +// if there are operations that involves a very big reply then it the
2332 +// socket could be made non-blocking and a timeout could be used.
2334 +void SolarisAttachOperation::complete(jint res, bufferedStream* st) {
2335 + if (this->socket() >= 0) {
2336 + JavaThread* thread = JavaThread::current();
2337 + ThreadBlockInVM tbivm(thread);
2339 + // write operation result
2340 + char msg[32];
2341 + sprintf(msg, "%d\n", res);
2342 + int rc = write_fully(this->socket(), msg, strlen(msg));
2344 + // write any result data
2345 + if (rc == 0) {
2346 + write_fully(this->socket(), (char*) st->base(), st->size());
2347 + ::shutdown(this->socket(), 2);
2350 + // close socket and we're done
2351 + ::close(this->socket());
2353 + delete this;
2357 +// AttachListener functions
2359 +AttachOperation* AttachListener::dequeue() {
2360 + JavaThread* thread = JavaThread::current();
2361 + ThreadBlockInVM tbivm(thread);
2363 + AttachOperation* op = SolarisAttachListener::dequeue();
2365 + return op;
2369 +// Performs initialization at vm startup
2370 +// For Solaris we remove any stale .java_pid file which could cause
2371 +// an attaching process to think we are ready to receive a door_call
2372 +// before we are properly initialized
2374 +void AttachListener::vm_start() {
2375 + char fn[PATH_MAX+1];
2376 + struct stat64 st;
2377 + int ret;
2379 + int n = snprintf(fn, sizeof(fn), "%s/.java_pid%d",
2380 + os::get_temp_directory(), os::current_process_id());
2381 + assert(n < sizeof(fn), "java_pid file name buffer overflow");
2383 + RESTARTABLE(::stat64(fn, &st), ret);
2384 + if (ret == 0) {
2385 + ret = ::unlink(fn);
2386 + if (ret == -1) {
2387 + log_debug(attach)("Failed to remove stale attach pid file at %s", fn);
2392 +int AttachListener::pd_init() {
2393 + JavaThread* thread = JavaThread::current();
2394 + ThreadBlockInVM tbivm(thread);
2396 + int ret_code = SolarisAttachListener::init();
2398 + return ret_code;
2401 +// Attach Listener is started lazily except in the case when
2402 +// +ReduseSignalUsage is used
2403 +bool AttachListener::init_at_startup() {
2404 + if (ReduceSignalUsage) {
2405 + return true;
2406 + } else {
2407 + return false;
2411 +bool AttachListener::check_socket_file() {
2412 + int ret;
2413 + struct stat64 st;
2414 + ret = stat64(SolarisAttachListener::door_path(), &st);
2415 + if (ret == -1) { // need to restart attach listener.
2416 + log_debug(attach)("Door file %s does not exist - Restart Attach Listener",
2417 + SolarisAttachListener::door_path());
2419 + listener_cleanup();
2421 + // wait to terminate current attach listener instance...
2422 + while (AttachListener::transit_state(AL_INITIALIZING,
2423 + AL_NOT_INITIALIZED) != AL_NOT_INITIALIZED) {
2424 + os::naked_yield();
2426 + return is_init_trigger();
2428 + return false;
2431 +// If the file .attach_pid<pid> exists in the working directory
2432 +// or /tmp then this is the trigger to start the attach mechanism
2433 +bool AttachListener::is_init_trigger() {
2434 + if (init_at_startup() || is_initialized()) {
2435 + return false; // initialized at startup or already initialized
2437 + char fn[PATH_MAX + 1];
2438 + int ret;
2439 + struct stat64 st;
2440 + sprintf(fn, ".attach_pid%d", os::current_process_id());
2441 + RESTARTABLE(::stat64(fn, &st), ret);
2442 + if (ret == -1) {
2443 + log_trace(attach)("Failed to find attach file: %s, trying alternate", fn);
2444 + snprintf(fn, sizeof(fn), "%s/.attach_pid%d",
2445 + os::get_temp_directory(), os::current_process_id());
2446 + RESTARTABLE(::stat64(fn, &st), ret);
2447 + if (ret == -1) {
2448 + log_debug(attach)("Failed to find attach file: %s", fn);
2451 + if (ret == 0) {
2452 + // simple check to avoid starting the attach mechanism when
2453 + // a bogus non-root user creates the file
2454 + if (os::Posix::matches_effective_uid_or_root(st.st_uid)) {
2455 + init();
2456 + log_trace(attach)("Attach triggered by %s", fn);
2457 + return true;
2458 + } else {
2459 + log_debug(attach)("File %s has wrong user id %d (vs %d). Attach is not triggered", fn, st.st_uid, geteuid());
2462 + return false;
2465 +// if VM aborts then detach/cleanup
2466 +void AttachListener::abort() {
2467 + listener_cleanup();
2470 +void AttachListener::pd_data_dump() {
2471 + os::signal_notify(SIGQUIT);
2474 +static jint enable_dprobes(AttachOperation* op, outputStream* out) {
2475 + const char* probe = op->arg(0);
2476 + if (probe == NULL || probe[0] == '\0') {
2477 + out->print_cr("No probe specified");
2478 + return JNI_ERR;
2479 + } else {
2480 + char *end;
2481 + long val = strtol(probe, &end, 10);
2482 + if (end == probe || val < 0 || val > INT_MAX) {
2483 + out->print_cr("invalid probe type");
2484 + return JNI_ERR;
2485 + } else {
2486 + int probe_typess = (int) val;
2487 + DTrace::enable_dprobes(probe_typess);
2488 + return JNI_OK;
2493 +// platform specific operations table
2494 +static AttachOperationFunctionInfo funcs[] = {
2495 + { "enabledprobes", enable_dprobes },
2496 + { NULL, NULL }
2499 +void AttachListener::pd_detachall() {
2500 + DTrace::detach_all_clients();
2502 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os/solaris/c1_globals_solaris.hpp jdk22u-jdk-22.0.2-ga/src/hotspot/os/solaris/c1_globals_solaris.hpp
2503 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os/solaris/c1_globals_solaris.hpp 1970-01-01 01:00:00.000000000 +0100
2504 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/os/solaris/c1_globals_solaris.hpp 2024-08-17 19:34:03.895563526 +0200
2505 @@ -0,0 +1,36 @@
2507 + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
2508 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
2510 + * This code is free software; you can redistribute it and/or modify it
2511 + * under the terms of the GNU General Public License version 2 only, as
2512 + * published by the Free Software Foundation.
2514 + * This code is distributed in the hope that it will be useful, but WITHOUT
2515 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
2516 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
2517 + * version 2 for more details (a copy is included in the LICENSE file that
2518 + * accompanied this code).
2520 + * You should have received a copy of the GNU General Public License version
2521 + * 2 along with this work; if not, write to the Free Software Foundation,
2522 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2524 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2525 + * or visit www.oracle.com if you need additional information or have any
2526 + * questions.
2528 + */
2530 +#ifndef OS_SOLARIS_C1_GLOBALS_SOLARIS_HPP
2531 +#define OS_SOLARIS_C1_GLOBALS_SOLARIS_HPP
2533 +#include "utilities/globalDefinitions.hpp"
2534 +#include "utilities/macros.hpp"
2537 +// Sets the default values for operating system dependent flags used by the
2538 +// client compiler. (see c1_globals.hpp)
2541 +#endif // OS_SOLARIS_C1_GLOBALS_SOLARIS_HPP
2542 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os/solaris/c2_globals_solaris.hpp jdk22u-jdk-22.0.2-ga/src/hotspot/os/solaris/c2_globals_solaris.hpp
2543 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os/solaris/c2_globals_solaris.hpp 1970-01-01 01:00:00.000000000 +0100
2544 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/os/solaris/c2_globals_solaris.hpp 2024-08-17 19:34:03.895818260 +0200
2545 @@ -0,0 +1,36 @@
2547 + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
2548 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
2550 + * This code is free software; you can redistribute it and/or modify it
2551 + * under the terms of the GNU General Public License version 2 only, as
2552 + * published by the Free Software Foundation.
2554 + * This code is distributed in the hope that it will be useful, but WITHOUT
2555 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
2556 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
2557 + * version 2 for more details (a copy is included in the LICENSE file that
2558 + * accompanied this code).
2560 + * You should have received a copy of the GNU General Public License version
2561 + * 2 along with this work; if not, write to the Free Software Foundation,
2562 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2564 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2565 + * or visit www.oracle.com if you need additional information or have any
2566 + * questions.
2568 + */
2570 +#ifndef OS_SOLARIS_C2_GLOBALS_SOLARIS_HPP
2571 +#define OS_SOLARIS_C2_GLOBALS_SOLARIS_HPP
2573 +#include "utilities/globalDefinitions.hpp"
2574 +#include "utilities/macros.hpp"
2577 +// Sets the default values for operating system dependent flags used by the
2578 +// server compiler. (see c2_globals.hpp)
2581 +#endif // OS_SOLARIS_C2_GLOBALS_SOLARIS_HPP
2582 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os/solaris/decoder_solaris.cpp jdk22u-jdk-22.0.2-ga/src/hotspot/os/solaris/decoder_solaris.cpp
2583 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os/solaris/decoder_solaris.cpp 1970-01-01 01:00:00.000000000 +0100
2584 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/os/solaris/decoder_solaris.cpp 2024-08-17 19:34:03.896066137 +0200
2585 @@ -0,0 +1,32 @@
2587 + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
2588 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
2590 + * This code is free software; you can redistribute it and/or modify it
2591 + * under the terms of the GNU General Public License version 2 only, as
2592 + * published by the Free Software Foundation.
2594 + * This code is distributed in the hope that it will be useful, but WITHOUT
2595 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
2596 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
2597 + * version 2 for more details (a copy is included in the LICENSE file that
2598 + * accompanied this code).
2600 + * You should have received a copy of the GNU General Public License version
2601 + * 2 along with this work; if not, write to the Free Software Foundation,
2602 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2604 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2605 + * or visit www.oracle.com if you need additional information or have any
2606 + * questions.
2608 + */
2610 +#include "utilities/decoder_elf.hpp"
2612 +#include <demangle.h>
2614 +bool ElfDecoder::demangle(const char* symbol, char *buf, int buflen) {
2615 + return !cplus_demangle(symbol, buf, (size_t)buflen);
2618 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os/solaris/dtrace/jhelper.d jdk22u-jdk-22.0.2-ga/src/hotspot/os/solaris/dtrace/jhelper.d
2619 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os/solaris/dtrace/jhelper.d 1970-01-01 01:00:00.000000000 +0100
2620 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/os/solaris/dtrace/jhelper.d 2024-08-17 19:34:03.896957029 +0200
2621 @@ -0,0 +1,540 @@
2623 + * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
2624 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
2626 + * This code is free software; you can redistribute it and/or modify it
2627 + * under the terms of the GNU General Public License version 2 only, as
2628 + * published by the Free Software Foundation.
2630 + * This code is distributed in the hope that it will be useful, but WITHOUT
2631 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
2632 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
2633 + * version 2 for more details (a copy is included in the LICENSE file that
2634 + * accompanied this code).
2636 + * You should have received a copy of the GNU General Public License version
2637 + * 2 along with this work; if not, write to the Free Software Foundation,
2638 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2640 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2641 + * or visit www.oracle.com if you need additional information or have any
2642 + * questions.
2644 + */
2646 +/* This file is auto-generated */
2647 +#include "JvmOffsetsIndex.h"
2649 +#define DEBUG
2651 +#ifdef DEBUG
2652 +#define MARK_LINE this->line = __LINE__
2653 +#else
2654 +#define MARK_LINE
2655 +#endif
2657 +#ifdef _LP64
2658 +#define STACK_BIAS 0x7ff
2659 +#define pointer uint64_t
2660 +#else
2661 +#define STACK_BIAS 0
2662 +#define pointer uint32_t
2663 +#endif
2665 +extern pointer __JvmOffsets;
2667 +/* GrowableArray<CodeHeaps*>* */
2668 +extern pointer __1cJCodeCacheG_heaps_;
2670 +extern pointer __1cIUniverseO_collectedHeap_;
2672 +extern pointer __1cHnmethodG__vtbl_;
2673 +extern pointer __1cGMethodG__vtbl_;
2674 +extern pointer __1cKBufferBlobG__vtbl_;
2676 +#define copyin_ptr(ADDR) *(pointer*) copyin((pointer) (ADDR), sizeof(pointer))
2677 +#define copyin_uchar(ADDR) *(uchar_t*) copyin((pointer) (ADDR), sizeof(uchar_t))
2678 +#define copyin_uint16(ADDR) *(uint16_t*) copyin((pointer) (ADDR), sizeof(uint16_t))
2679 +#define copyin_uint32(ADDR) *(uint32_t*) copyin((pointer) (ADDR), sizeof(uint32_t))
2680 +#define copyin_int32(ADDR) *(int32_t*) copyin((pointer) (ADDR), sizeof(int32_t))
2681 +#define copyin_uint8(ADDR) *(uint8_t*) copyin((pointer) (ADDR), sizeof(uint8_t))
2683 +#define copyin_offset(JVM_CONST) JVM_CONST = \
2684 + copyin_int32(JvmOffsetsPtr + IDX_##JVM_CONST * sizeof(int32_t))
2686 +int init_done;
2688 +dtrace:helper:ustack:
2690 + MARK_LINE;
2691 + this->done = 0;
2692 + /*
2693 + * TBD:
2694 + * Here we initialize init_done, otherwise jhelper does not work.
2695 + * Therefore, copyin_offset() statements work multiple times now.
2696 + * There is a hope we could avoid it in the future, and so,
2697 + * this initialization can be removed.
2698 + */
2699 + init_done = 0;
2700 + this->error = (char *) NULL;
2701 + this->result = (char *) NULL;
2702 + this->isMethod = 0;
2703 + this->codecache = 0;
2704 + this->klass = (pointer) NULL;
2705 + this->vtbl = (pointer) NULL;
2706 + this->suffix = '\0';
2709 +dtrace:helper:ustack:
2711 + MARK_LINE;
2712 + /* Initialization of JvmOffsets constants */
2713 + JvmOffsetsPtr = (pointer) &``__JvmOffsets;
2716 +dtrace:helper:ustack:
2717 +/!init_done && !this->done/
2719 + MARK_LINE;
2721 + copyin_offset(POINTER_SIZE);
2722 + copyin_offset(COMPILER);
2723 + copyin_offset(OFFSET_CollectedHeap_reserved);
2724 + copyin_offset(OFFSET_MemRegion_start);
2725 + copyin_offset(OFFSET_MemRegion_word_size);
2726 + copyin_offset(SIZE_HeapWord);
2728 + copyin_offset(OFFSET_interpreter_frame_method);
2729 + copyin_offset(OFFSET_Klass_name);
2730 + copyin_offset(OFFSET_ConstantPool_pool_holder);
2732 + copyin_offset(OFFSET_HeapBlockHeader_used);
2733 + copyin_offset(OFFSET_oopDesc_metadata);
2735 + copyin_offset(OFFSET_Symbol_length);
2736 + copyin_offset(OFFSET_Symbol_body);
2738 + copyin_offset(OFFSET_Method_constMethod);
2739 + copyin_offset(OFFSET_ConstMethod_constants);
2740 + copyin_offset(OFFSET_ConstMethod_name_index);
2741 + copyin_offset(OFFSET_ConstMethod_signature_index);
2743 + copyin_offset(OFFSET_CodeHeap_memory);
2744 + copyin_offset(OFFSET_CodeHeap_segmap);
2745 + copyin_offset(OFFSET_CodeHeap_log2_segment_size);
2747 + copyin_offset(OFFSET_GrowableArray_CodeHeap_data);
2748 + copyin_offset(OFFSET_GrowableArray_CodeHeap_len);
2750 + copyin_offset(OFFSET_VirtualSpace_low);
2751 + copyin_offset(OFFSET_VirtualSpace_high);
2753 + copyin_offset(OFFSET_CodeBlob_name);
2755 + copyin_offset(OFFSET_nmethod_method);
2756 + copyin_offset(SIZE_HeapBlockHeader);
2757 + copyin_offset(SIZE_oopDesc);
2758 + copyin_offset(SIZE_ConstantPool);
2760 + copyin_offset(OFFSET_NarrowPtrStruct_base);
2761 + copyin_offset(OFFSET_NarrowPtrStruct_shift);
2763 + /*
2764 + * The PC to translate is in arg0.
2765 + */
2766 + this->pc = arg0;
2768 +#if defined(__i386) || defined(__amd64)
2769 + this->methodPtr = copyin_ptr(arg1 + OFFSET_interpreter_frame_method);
2770 +#else
2771 +#error "Don't know architecture"
2772 +#endif
2774 + /* Read address of GrowableArray<CodeHeaps*> */
2775 + // this->code_heaps_address = copyin_ptr(&``__1cJCodeCacheG_heaps_);
2776 + this->code_heaps_address = * ( uint64_t * ) copyin ( ( uint64_t ) ( &``__1cJCodeCacheG_heaps_ ) , sizeof ( uint64_t ) );
2778 + /* Read address of _data array field in GrowableArray */
2779 + this->code_heaps_array_address = copyin_ptr(this->code_heaps_address + OFFSET_GrowableArray_CodeHeap_data);
2780 + this->number_of_heaps = copyin_uint32(this->code_heaps_address + OFFSET_GrowableArray_CodeHeap_len);
2782 + this->Method_vtbl = (pointer) &``__1cGMethodG__vtbl_;
2784 + /*
2785 + * Get Java heap bounds
2786 + */
2787 + // this->Universe_collectedHeap = copyin_ptr(&``__1cIUniverseO_collectedHeap_);
2788 + this->Universe_collectedHeap = * ( uint64_t * ) copyin ( ( uint64_t ) ( &``__1cIUniverseO_collectedHeap_ ) , sizeof ( uint64_t ) );
2790 + this->heap_start = copyin_ptr(this->Universe_collectedHeap +
2791 + OFFSET_CollectedHeap_reserved +
2792 + OFFSET_MemRegion_start);
2793 + this->heap_size = SIZE_HeapWord *
2794 + copyin_ptr(this->Universe_collectedHeap +
2795 + OFFSET_CollectedHeap_reserved +
2796 + OFFSET_MemRegion_word_size
2797 + );
2798 + this->heap_end = this->heap_start + this->heap_size;
2802 + * IMPORTANT: At the moment the ustack helper supports up to 5 code heaps in
2803 + * the code cache. If more code heaps are added the following probes have to
2804 + * be extended. This is done by simply adding a probe to get the heap bounds
2805 + * and another probe to set the code heap address of the newly created heap.
2806 + */
2809 + * ----- BEGIN: Get bounds of code heaps -----
2810 + */
2811 +dtrace:helper:ustack:
2812 +/init_done < 1 && this->number_of_heaps >= 1 && !this->done/
2814 + MARK_LINE;
2815 + /* CodeHeap 1 */
2816 + init_done = 1;
2817 + this->code_heap1_address = copyin_ptr(this->code_heaps_array_address);
2818 + this->code_heap1_low = copyin_ptr(this->code_heap1_address +
2819 + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low);
2820 + this->code_heap1_high = copyin_ptr(this->code_heap1_address +
2821 + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_high);
2824 +dtrace:helper:ustack:
2825 +/init_done < 2 && this->number_of_heaps >= 2 && !this->done/
2827 + MARK_LINE;
2828 + /* CodeHeap 2 */
2829 + init_done = 2;
2830 + this->code_heaps_array_address = this->code_heaps_array_address + POINTER_SIZE;
2831 + this->code_heap2_address = copyin_ptr(this->code_heaps_array_address);
2832 + this->code_heap2_low = copyin_ptr(this->code_heap2_address +
2833 + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low);
2834 + this->code_heap2_high = copyin_ptr(this->code_heap2_address +
2835 + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_high);
2838 +dtrace:helper:ustack:
2839 +/init_done < 3 && this->number_of_heaps >= 3 && !this->done/
2841 + /* CodeHeap 3 */
2842 + init_done = 3;
2843 + this->code_heaps_array_address = this->code_heaps_array_address + POINTER_SIZE;
2844 + this->code_heap3_address = copyin_ptr(this->code_heaps_array_address);
2845 + this->code_heap3_low = copyin_ptr(this->code_heap3_address +
2846 + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low);
2847 + this->code_heap3_high = copyin_ptr(this->code_heap3_address +
2848 + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_high);
2851 +dtrace:helper:ustack:
2852 +/init_done < 4 && this->number_of_heaps >= 4 && !this->done/
2854 + /* CodeHeap 4 */
2855 + init_done = 4;
2856 + this->code_heaps_array_address = this->code_heaps_array_address + POINTER_SIZE;
2857 + this->code_heap4_address = copyin_ptr(this->code_heaps_array_address);
2858 + this->code_heap4_low = copyin_ptr(this->code_heap4_address +
2859 + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low);
2860 + this->code_heap4_high = copyin_ptr(this->code_heap4_address +
2861 + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_high);
2864 +dtrace:helper:ustack:
2865 +/init_done < 5 && this->number_of_heaps >= 5 && !this->done/
2867 + /* CodeHeap 5 */
2868 + init_done = 5;
2869 + this->code_heaps_array_address = this->code_heaps_array_address + POINTER_SIZE;
2870 + this->code_heap5_address = copyin_ptr(this->code_heaps_array_address);
2871 + this->code_heap5_low = copyin_ptr(this->code_heap5_address +
2872 + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low);
2873 + this->code_heap5_high = copyin_ptr(this->code_heap5_address +
2874 + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_high);
2877 + * ----- END: Get bounds of code heaps -----
2878 + */
2881 + * ----- BEGIN: Get address of the code heap pc points to -----
2882 + */
2883 +dtrace:helper:ustack:
2884 +/!this->done && this->number_of_heaps >= 1 && this->code_heap1_low <= this->pc && this->pc < this->code_heap1_high/
2886 + MARK_LINE;
2887 + this->codecache = 1;
2888 + this->code_heap_address = this->code_heap1_address;
2891 +dtrace:helper:ustack:
2892 +/!this->done && this->number_of_heaps >= 2 && this->code_heap2_low <= this->pc && this->pc < this->code_heap2_high/
2894 + MARK_LINE;
2895 + this->codecache = 1;
2896 + this->code_heap_address = this->code_heap2_address;
2899 +dtrace:helper:ustack:
2900 +/!this->done && this->number_of_heaps >= 3 && this->code_heap3_low <= this->pc && this->pc < this->code_heap3_high/
2902 + MARK_LINE;
2903 + this->codecache = 1;
2904 + this->code_heap_address = this->code_heap3_address;
2907 +dtrace:helper:ustack:
2908 +/!this->done && this->number_of_heaps >= 4 && this->code_heap4_low <= this->pc && this->pc < this->code_heap4_high/
2910 + MARK_LINE;
2911 + this->codecache = 1;
2912 + this->code_heap_address = this->code_heap4_address;
2915 +dtrace:helper:ustack:
2916 +/!this->done && this->number_of_heaps >= 5 && this->code_heap5_low <= this->pc && this->pc < this->code_heap5_high/
2918 + MARK_LINE;
2919 + this->codecache = 1;
2920 + this->code_heap_address = this->code_heap5_address;
2923 + * ----- END: Get address of the code heap pc points to -----
2924 + */
2926 +dtrace:helper:ustack:
2927 +/!this->done && this->codecache/
2929 + MARK_LINE;
2930 + /*
2931 + * Get code heap configuration
2932 + */
2933 + this->code_heap_low = copyin_ptr(this->code_heap_address +
2934 + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low);
2935 + this->code_heap_segmap_low = copyin_ptr(this->code_heap_address +
2936 + OFFSET_CodeHeap_segmap + OFFSET_VirtualSpace_low);
2937 + this->code_heap_log2_segment_size = copyin_uint32(
2938 + this->code_heap_address + OFFSET_CodeHeap_log2_segment_size);
2940 + /*
2941 + * Find start
2942 + */
2943 + this->segment = (this->pc - this->code_heap_low) >>
2944 + this->code_heap_log2_segment_size;
2945 + this->block = this->code_heap_segmap_low;
2946 + this->tag = copyin_uchar(this->block + this->segment);
2949 +dtrace:helper:ustack:
2950 +/!this->done && this->codecache && this->tag > 0/
2952 + MARK_LINE;
2953 + this->tag = copyin_uchar(this->block + this->segment);
2954 + this->segment = this->segment - this->tag;
2957 +dtrace:helper:ustack:
2958 +/!this->done && this->codecache && this->tag > 0/
2960 + MARK_LINE;
2961 + this->tag = copyin_uchar(this->block + this->segment);
2962 + this->segment = this->segment - this->tag;
2965 +dtrace:helper:ustack:
2966 +/!this->done && this->codecache && this->tag > 0/
2968 + MARK_LINE;
2969 + this->tag = copyin_uchar(this->block + this->segment);
2970 + this->segment = this->segment - this->tag;
2973 +dtrace:helper:ustack:
2974 +/!this->done && this->codecache && this->tag > 0/
2976 + MARK_LINE;
2977 + this->tag = copyin_uchar(this->block + this->segment);
2978 + this->segment = this->segment - this->tag;
2981 +dtrace:helper:ustack:
2982 +/!this->done && this->codecache && this->tag > 0/
2984 + MARK_LINE;
2985 + this->tag = copyin_uchar(this->block + this->segment);
2986 + this->segment = this->segment - this->tag;
2989 +dtrace:helper:ustack:
2990 +/!this->done && this->codecache && this->tag > 0/
2992 + MARK_LINE;
2993 + this->error = "<couldn't find start>";
2994 + this->done = 1;
2997 +dtrace:helper:ustack:
2998 +/!this->done && this->codecache/
3000 + MARK_LINE;
3001 + this->block = this->code_heap_low +
3002 + (this->segment << this->code_heap_log2_segment_size);
3003 + this->used = copyin_uint32(this->block + OFFSET_HeapBlockHeader_used);
3006 +dtrace:helper:ustack:
3007 +/!this->done && this->codecache && !this->used/
3009 + MARK_LINE;
3010 + this->error = "<block not in use>";
3011 + this->done = 1;
3014 +dtrace:helper:ustack:
3015 +/!this->done && this->codecache/
3017 + MARK_LINE;
3018 + this->start = this->block + SIZE_HeapBlockHeader;
3019 + this->vtbl = copyin_ptr(this->start);
3021 + this->nmethod_vtbl = (pointer) &``__1cHnmethodG__vtbl_;
3022 + this->BufferBlob_vtbl = (pointer) &``__1cKBufferBlobG__vtbl_;
3025 +dtrace:helper:ustack:
3026 +/!this->done && this->vtbl == this->nmethod_vtbl/
3028 + MARK_LINE;
3029 + this->methodPtr = copyin_ptr(this->start + OFFSET_nmethod_method);
3030 + this->suffix = '*';
3031 + this->isMethod = 1;
3034 +dtrace:helper:ustack:
3035 +/!this->done && this->vtbl == this->BufferBlob_vtbl/
3037 + MARK_LINE;
3038 + this->name = copyin_ptr(this->start + OFFSET_CodeBlob_name);
3042 +dtrace:helper:ustack:
3043 +/!this->done && this->vtbl == this->BufferBlob_vtbl && this->methodPtr != 0/
3045 + MARK_LINE;
3046 + this->klass = copyin_ptr(this->methodPtr);
3047 + this->isMethod = this->klass == this->Method_vtbl;
3048 + this->done = !this->isMethod;
3051 +dtrace:helper:ustack:
3052 +/!this->done && !this->isMethod/
3054 + MARK_LINE;
3055 + this->name = copyin_ptr(this->start + OFFSET_CodeBlob_name);
3056 + this->result = this->name != 0 ? copyinstr(this->name) : "<CodeBlob>";
3057 + this->done = 1;
3060 +dtrace:helper:ustack:
3061 +/!this->done && this->isMethod/
3063 + MARK_LINE;
3064 + this->constMethod = copyin_ptr(this->methodPtr +
3065 + OFFSET_Method_constMethod);
3067 + this->nameIndex = copyin_uint16(this->constMethod +
3068 + OFFSET_ConstMethod_name_index);
3070 + this->signatureIndex = copyin_uint16(this->constMethod +
3071 + OFFSET_ConstMethod_signature_index);
3073 + this->constantPool = copyin_ptr(this->constMethod +
3074 + OFFSET_ConstMethod_constants);
3076 + this->nameSymbol = copyin_ptr(this->constantPool +
3077 + this->nameIndex * sizeof (pointer) + SIZE_ConstantPool);
3078 + /* The symbol is a CPSlot and has lower bit set to indicate metadata */
3079 + this->nameSymbol &= (~1); /* remove metadata lsb */
3081 + this->nameSymbolLength = copyin_uint16(this->nameSymbol +
3082 + OFFSET_Symbol_length);
3084 + this->signatureSymbol = copyin_ptr(this->constantPool +
3085 + this->signatureIndex * sizeof (pointer) + SIZE_ConstantPool);
3086 + this->signatureSymbol &= (~1); /* remove metadata lsb */
3088 + this->signatureSymbolLength = copyin_uint16(this->signatureSymbol +
3089 + OFFSET_Symbol_length);
3091 + this->klassPtr = copyin_ptr(this->constantPool +
3092 + OFFSET_ConstantPool_pool_holder);
3094 + this->klassSymbol = copyin_ptr(this->klassPtr +
3095 + OFFSET_Klass_name);
3097 + this->klassSymbolLength = copyin_uint16(this->klassSymbol +
3098 + OFFSET_Symbol_length);
3100 + /*
3101 + * Enough for three strings, plus the '.', plus the trailing '\0'.
3102 + */
3103 + this->result = (char *) alloca(this->klassSymbolLength +
3104 + this->nameSymbolLength +
3105 + this->signatureSymbolLength + 2 + 1);
3107 + copyinto(this->klassSymbol + OFFSET_Symbol_body,
3108 + this->klassSymbolLength, this->result);
3110 + /*
3111 + * Add the '.' between the class and the name.
3112 + */
3113 + this->result[this->klassSymbolLength] = '.';
3115 + copyinto(this->nameSymbol + OFFSET_Symbol_body,
3116 + this->nameSymbolLength,
3117 + this->result + this->klassSymbolLength + 1);
3119 + copyinto(this->signatureSymbol + OFFSET_Symbol_body,
3120 + this->signatureSymbolLength,
3121 + this->result + this->klassSymbolLength +
3122 + this->nameSymbolLength + 1);
3124 + /*
3125 + * Now we need to add a trailing '\0' and possibly a tag character.
3126 + */
3127 + this->result[this->klassSymbolLength + 1 +
3128 + this->nameSymbolLength +
3129 + this->signatureSymbolLength] = this->suffix;
3130 + this->result[this->klassSymbolLength + 2 +
3131 + this->nameSymbolLength +
3132 + this->signatureSymbolLength] = '\0';
3134 + this->done = 1;
3137 +dtrace:helper:ustack:
3138 +/this->done && this->error == (char *) NULL/
3140 + this->result;
3143 +dtrace:helper:ustack:
3144 +/this->done && this->error != (char *) NULL/
3146 + this->error;
3149 +dtrace:helper:ustack:
3150 +/!this->done && this->codecache/
3152 + this->done = 1;
3153 + "error";
3157 +dtrace:helper:ustack:
3158 +/!this->done/
3160 + NULL;
3162 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os/solaris/globals_solaris.hpp jdk22u-jdk-22.0.2-ga/src/hotspot/os/solaris/globals_solaris.hpp
3163 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os/solaris/globals_solaris.hpp 1970-01-01 01:00:00.000000000 +0100
3164 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/os/solaris/globals_solaris.hpp 2024-08-17 19:34:03.897226580 +0200
3165 @@ -0,0 +1,49 @@
3167 + * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved.
3168 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3170 + * This code is free software; you can redistribute it and/or modify it
3171 + * under the terms of the GNU General Public License version 2 only, as
3172 + * published by the Free Software Foundation.
3174 + * This code is distributed in the hope that it will be useful, but WITHOUT
3175 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
3176 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
3177 + * version 2 for more details (a copy is included in the LICENSE file that
3178 + * accompanied this code).
3180 + * You should have received a copy of the GNU General Public License version
3181 + * 2 along with this work; if not, write to the Free Software Foundation,
3182 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
3184 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
3185 + * or visit www.oracle.com if you need additional information or have any
3186 + * questions.
3188 + */
3190 +#ifndef OS_SOLARIS_GLOBALS_SOLARIS_HPP
3191 +#define OS_SOLARIS_GLOBALS_SOLARIS_HPP
3194 +// Defines Solaris specific flags. They are not available on other platforms.
3196 +#define RUNTIME_OS_FLAGS(develop, \
3197 + develop_pd, \
3198 + product, \
3199 + product_pd, \
3200 + notproduct, \
3201 + range, \
3202 + constraint)
3205 +// Defines Solaris-specific default values. The flags are available on all
3206 +// platforms, but they may have different default values on other platforms.
3208 +define_pd_global(size_t, PreTouchParallelChunkSize, 1 * G);
3209 +define_pd_global(bool, UseLargePages, true);
3210 +define_pd_global(bool, UseLargePagesIndividualAllocation, false);
3211 +define_pd_global(bool, UseOSErrorReporting, false);
3212 +define_pd_global(bool, UseThreadPriorities, false);
3214 +#endif // OS_SOLARIS_GLOBALS_SOLARIS_HPP
3215 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os/solaris/os_perf_solaris.cpp jdk22u-jdk-22.0.2-ga/src/hotspot/os/solaris/os_perf_solaris.cpp
3216 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os/solaris/os_perf_solaris.cpp 1970-01-01 01:00:00.000000000 +0100
3217 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/os/solaris/os_perf_solaris.cpp 2024-08-17 19:34:03.898337648 +0200
3218 @@ -0,0 +1,808 @@
3220 + * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
3221 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3223 + * This code is free software; you can redistribute it and/or modify it
3224 + * under the terms of the GNU General Public License version 2 only, as
3225 + * published by the Free Software Foundation.
3227 + * This code is distributed in the hope that it will be useful, but WITHOUT
3228 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
3229 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
3230 + * version 2 for more details (a copy is included in the LICENSE file that
3231 + * accompanied this code).
3233 + * You should have received a copy of the GNU General Public License version
3234 + * 2 along with this work; if not, write to the Free Software Foundation,
3235 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
3237 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
3238 + * or visit www.oracle.com if you need additional information or have any
3239 + * questions.
3241 + */
3243 +#include "precompiled.hpp"
3244 +#include "jvm.h"
3245 +#include "memory/allocation.inline.hpp"
3246 +#include "runtime/os.hpp"
3247 +#include "runtime/os_perf.hpp"
3248 +#include "runtime/vm_version.hpp"
3249 +#include "os_solaris.inline.hpp"
3250 +#include "utilities/globalDefinitions.hpp"
3251 +#include "utilities/macros.hpp"
3253 +#include <sys/types.h>
3254 +#include <procfs.h>
3255 +#include <dirent.h>
3256 +#include <errno.h>
3257 +#include <stdio.h>
3258 +#include <stdlib.h>
3259 +#include <strings.h>
3260 +#include <unistd.h>
3261 +#include <fcntl.h>
3262 +#include <kstat.h>
3263 +#include <unistd.h>
3264 +#include <string.h>
3265 +#include <sys/sysinfo.h>
3266 +#include <sys/lwp.h>
3267 +#include <pthread.h>
3268 +#include <time.h>
3269 +#include <utmpx.h>
3270 +#include <dlfcn.h>
3271 +#include <sys/loadavg.h>
3272 +#include <limits.h>
3274 +static const double NANOS_PER_SEC = 1000000000.0;
3276 +struct CPUPerfTicks {
3277 + kstat_t* kstat;
3278 + uint64_t last_idle;
3279 + uint64_t last_total;
3280 + double last_ratio;
3283 +struct CPUPerfCounters {
3284 + int nProcs;
3285 + CPUPerfTicks* jvmTicks;
3286 + kstat_ctl_t* kstat_ctrl;
3289 +static int get_info(const char* path, void* info, size_t s, off_t o) {
3290 + assert(path != NULL, "path is NULL!");
3291 + assert(info != NULL, "info is NULL!");
3293 + int fd = -1;
3295 + if ((fd = os::open(path, O_RDONLY, 0)) < 0) {
3296 + return OS_ERR;
3298 + if (pread(fd, info, s, o) != s) {
3299 + close(fd);
3300 + return OS_ERR;
3302 + close(fd);
3303 + return OS_OK;
3306 +static int get_psinfo2(void* info, size_t s, off_t o) {
3307 + return get_info("/proc/self/psinfo", info, s, o);
3310 +static int get_psinfo(psinfo_t* info) {
3311 + return get_psinfo2(info, sizeof(*info), 0);
3314 +static int read_cpustat(kstat_ctl_t* kstat_ctrl, CPUPerfTicks* load, cpu_stat_t* cpu_stat) {
3315 + assert(kstat_ctrl != NULL, "kstat_ctrl pointer is NULL!");
3316 + assert(load != NULL, "load pointer is NULL!");
3317 + assert(cpu_stat != NULL, "cpu_stat pointer is NULL!");
3319 + if (load->kstat == NULL) {
3320 + // no handle.
3321 + return OS_ERR;
3323 + if (kstat_read(kstat_ctrl, load->kstat, cpu_stat) == OS_ERR) {
3324 + // disable handle for this CPU
3325 + load->kstat = NULL;
3326 + return OS_ERR;
3328 + return OS_OK;
3331 +static double get_cpu_load(int which_logical_cpu, CPUPerfCounters* counters) {
3332 + assert(counters != NULL, "counters pointer is NULL!");
3334 + cpu_stat_t cpu_stat = {0};
3336 + if (which_logical_cpu >= counters->nProcs) {
3337 + return .0;
3340 + CPUPerfTicks load = counters->jvmTicks[which_logical_cpu];
3341 + if (read_cpustat(counters->kstat_ctrl, &load, &cpu_stat) != OS_OK) {
3342 + return .0;
3345 + uint_t* usage = cpu_stat.cpu_sysinfo.cpu;
3346 + if (usage == NULL) {
3347 + return .0;
3350 + uint64_t c_idle = usage[CPU_IDLE];
3351 + uint64_t c_total = 0;
3353 + for (int i = 0; i < CPU_STATES; i++) {
3354 + c_total += usage[i];
3357 + // Calculate diff against previous snapshot
3358 + uint64_t d_idle = c_idle - load.last_idle;
3359 + uint64_t d_total = c_total - load.last_total;
3361 + /** update if weve moved */
3362 + if (d_total > 0) {
3363 + // Save current values for next time around
3364 + load.last_idle = c_idle;
3365 + load.last_total = c_total;
3366 + load.last_ratio = (double) (d_total - d_idle) / d_total;
3369 + return load.last_ratio;
3372 +static int get_boot_time(uint64_t* time) {
3373 + assert(time != NULL, "time pointer is NULL!");
3374 + setutxent();
3375 + for(;;) {
3376 + struct utmpx* u;
3377 + if ((u = getutxent()) == NULL) {
3378 + break;
3380 + if (u->ut_type == BOOT_TIME) {
3381 + *time = u->ut_xtime;
3382 + endutxent();
3383 + return OS_OK;
3386 + endutxent();
3387 + return OS_ERR;
3390 +static int get_noof_context_switches(CPUPerfCounters* counters, uint64_t* switches) {
3391 + assert(switches != NULL, "switches pointer is NULL!");
3392 + assert(counters != NULL, "counter pointer is NULL!");
3393 + *switches = 0;
3394 + uint64_t s = 0;
3396 + // Collect data from all CPUs
3397 + for (int i = 0; i < counters->nProcs; i++) {
3398 + cpu_stat_t cpu_stat = {0};
3399 + CPUPerfTicks load = counters->jvmTicks[i];
3401 + if (read_cpustat(counters->kstat_ctrl, &load, &cpu_stat) == OS_OK) {
3402 + s += cpu_stat.cpu_sysinfo.pswitch;
3403 + } else {
3404 + //fail fast...
3405 + return OS_ERR;
3408 + *switches = s;
3409 + return OS_OK;
3412 +static int perf_context_switch_rate(CPUPerfCounters* counters, double* rate) {
3413 + assert(counters != NULL, "counters is NULL!");
3414 + assert(rate != NULL, "rate pointer is NULL!");
3415 + static pthread_mutex_t contextSwitchLock = PTHREAD_MUTEX_INITIALIZER;
3416 + static uint64_t lastTime = 0;
3417 + static uint64_t lastSwitches = 0;
3418 + static double lastRate = 0.0;
3420 + uint64_t lt = 0;
3421 + int res = 0;
3423 + if (lastTime == 0) {
3424 + uint64_t tmp;
3425 + if (get_boot_time(&tmp) < 0) {
3426 + return OS_ERR;
3428 + lt = tmp * 1000;
3431 + res = OS_OK;
3433 + pthread_mutex_lock(&contextSwitchLock);
3436 + uint64_t sw = 0;
3437 + clock_t t, d;
3439 + if (lastTime == 0) {
3440 + lastTime = lt;
3443 + t = clock();
3444 + d = t - lastTime;
3446 + if (d == 0) {
3447 + *rate = lastRate;
3448 + } else if (get_noof_context_switches(counters, &sw)== OS_OK) {
3449 + *rate = ((double)(sw - lastSwitches) / d) * 1000;
3450 + lastRate = *rate;
3451 + lastSwitches = sw;
3452 + lastTime = t;
3453 + } else {
3454 + *rate = 0.0;
3455 + res = OS_ERR;
3457 + if (*rate < 0.0) {
3458 + *rate = 0.0;
3459 + lastRate = 0.0;
3462 + pthread_mutex_unlock(&contextSwitchLock);
3463 + return res;
3468 +class CPUPerformanceInterface::CPUPerformance : public CHeapObj<mtInternal> {
3469 + friend class CPUPerformanceInterface;
3470 + private:
3471 + CPUPerfCounters _counters;
3472 + int cpu_load(int which_logical_cpu, double* cpu_load);
3473 + int context_switch_rate(double* rate);
3474 + int cpu_load_total_process(double* cpu_load);
3475 + int cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad);
3477 + CPUPerformance();
3478 + ~CPUPerformance();
3479 + bool initialize();
3482 +CPUPerformanceInterface::CPUPerformance::CPUPerformance() {
3483 + _counters.nProcs = 0;
3484 + _counters.jvmTicks = NULL;
3485 + _counters.kstat_ctrl = NULL;
3488 +bool CPUPerformanceInterface::CPUPerformance::initialize() {
3489 + // initialize kstat control structure,
3490 + _counters.kstat_ctrl = kstat_open();
3491 + assert(_counters.kstat_ctrl != NULL, "error initializing kstat control structure!");
3493 + if (NULL == _counters.kstat_ctrl) {
3494 + return false;
3497 + // Get number of CPU(s)
3498 + if ((_counters.nProcs = sysconf(_SC_NPROCESSORS_ONLN)) == OS_ERR) {
3499 + // ignore error?
3500 + _counters.nProcs = 1;
3503 + assert(_counters.nProcs > 0, "no CPUs detected in sysconf call!");
3504 + if (_counters.nProcs == 0) {
3505 + return false;
3508 + // Data structure(s) for saving CPU load (one per CPU)
3509 + size_t array_entry_count = _counters.nProcs;
3510 + _counters.jvmTicks = NEW_C_HEAP_ARRAY(CPUPerfTicks, array_entry_count, mtInternal);
3511 + memset(_counters.jvmTicks, 0, array_entry_count * sizeof(*_counters.jvmTicks));
3513 + // Get kstat cpu_stat counters for every CPU
3514 + // loop over kstat to find our cpu_stat(s)
3515 + int i = 0;
3516 + for (kstat_t* kstat = _counters.kstat_ctrl->kc_chain; kstat != NULL; kstat = kstat->ks_next) {
3517 + if (strncmp(kstat->ks_module, "cpu_stat", 8) == 0) {
3518 + if (kstat_read(_counters.kstat_ctrl, kstat, NULL) == OS_ERR) {
3519 + continue;
3521 + if (i == _counters.nProcs) {
3522 + // more cpu_stats than reported CPUs
3523 + break;
3525 + _counters.jvmTicks[i++].kstat = kstat;
3528 + return true;
3531 +CPUPerformanceInterface::CPUPerformance::~CPUPerformance() {
3532 + FREE_C_HEAP_ARRAY(char, _counters.jvmTicks);
3533 + if (_counters.kstat_ctrl != NULL) {
3534 + kstat_close(_counters.kstat_ctrl);
3538 +int CPUPerformanceInterface::CPUPerformance::cpu_load(int which_logical_cpu, double* cpu_load) {
3539 + assert(cpu_load != NULL, "cpu_load pointer is NULL!");
3540 + double t = .0;
3541 + if (-1 == which_logical_cpu) {
3542 + for (int i = 0; i < _counters.nProcs; i++) {
3543 + t += get_cpu_load(i, &_counters);
3545 + // Cap total systemload to 1.0
3546 + t = MIN2<double>((t / _counters.nProcs), 1.0);
3547 + } else {
3548 + t = MIN2<double>(get_cpu_load(which_logical_cpu, &_counters), 1.0);
3551 + *cpu_load = t;
3552 + return OS_OK;
3555 +int CPUPerformanceInterface::CPUPerformance::cpu_load_total_process(double* cpu_load) {
3556 + assert(cpu_load != NULL, "cpu_load pointer is NULL!");
3558 + psinfo_t info;
3560 + // Get the percentage of "recent cpu usage" from all the lwp:s in the JVM:s
3561 + // process. This is returned as a value between 0.0 and 1.0 multiplied by 0x8000.
3562 + if (get_psinfo2(&info.pr_pctcpu, sizeof(info.pr_pctcpu), offsetof(psinfo_t, pr_pctcpu)) != 0) {
3563 + *cpu_load = 0.0;
3564 + return OS_ERR;
3566 + *cpu_load = (double) info.pr_pctcpu / 0x8000;
3567 + return OS_OK;
3570 +int CPUPerformanceInterface::CPUPerformance::cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad) {
3571 + assert(pjvmUserLoad != NULL, "pjvmUserLoad not inited");
3572 + assert(pjvmKernelLoad != NULL, "pjvmKernelLoad not inited");
3573 + assert(psystemTotalLoad != NULL, "psystemTotalLoad not inited");
3575 + static uint64_t lastTime;
3576 + static uint64_t lastUser, lastKernel;
3577 + static double lastUserRes, lastKernelRes;
3579 + pstatus_t pss;
3580 + psinfo_t info;
3582 + *pjvmKernelLoad = *pjvmUserLoad = *psystemTotalLoad = 0;
3583 + if (get_info("/proc/self/status", &pss.pr_utime, sizeof(timestruc_t)*2, offsetof(pstatus_t, pr_utime)) != 0) {
3584 + return OS_ERR;
3587 + if (get_psinfo(&info) != 0) {
3588 + return OS_ERR;
3591 + // get the total time in user, kernel and total time
3592 + // check ratios for 'lately' and multiply the 'recent load'.
3593 + uint64_t time = (info.pr_time.tv_sec * NANOS_PER_SEC) + info.pr_time.tv_nsec;
3594 + uint64_t user = (pss.pr_utime.tv_sec * NANOS_PER_SEC) + pss.pr_utime.tv_nsec;
3595 + uint64_t kernel = (pss.pr_stime.tv_sec * NANOS_PER_SEC) + pss.pr_stime.tv_nsec;
3596 + uint64_t diff = time - lastTime;
3597 + double load = (double) info.pr_pctcpu / 0x8000;
3599 + if (diff > 0) {
3600 + lastUserRes = (load * (user - lastUser)) / diff;
3601 + lastKernelRes = (load * (kernel - lastKernel)) / diff;
3603 + // BUG9182835 - patch for clamping these values to sane ones.
3604 + lastUserRes = MIN2<double>(1, lastUserRes);
3605 + lastUserRes = MAX2<double>(0, lastUserRes);
3606 + lastKernelRes = MIN2<double>(1, lastKernelRes);
3607 + lastKernelRes = MAX2<double>(0, lastKernelRes);
3610 + double t = .0;
3611 + cpu_load(-1, &t);
3612 + // clamp at user+system and 1.0
3613 + if (lastUserRes + lastKernelRes > t) {
3614 + t = MIN2<double>(lastUserRes + lastKernelRes, 1.0);
3617 + *pjvmUserLoad = lastUserRes;
3618 + *pjvmKernelLoad = lastKernelRes;
3619 + *psystemTotalLoad = t;
3621 + lastTime = time;
3622 + lastUser = user;
3623 + lastKernel = kernel;
3625 + return OS_OK;
3628 +int CPUPerformanceInterface::CPUPerformance::context_switch_rate(double* rate) {
3629 + return perf_context_switch_rate(&_counters, rate);
3632 +CPUPerformanceInterface::CPUPerformanceInterface() {
3633 + _impl = NULL;
3636 +bool CPUPerformanceInterface::initialize() {
3637 + _impl = new CPUPerformanceInterface::CPUPerformance();
3638 + return _impl->initialize();
3641 +CPUPerformanceInterface::~CPUPerformanceInterface(void) {
3642 + if (_impl != NULL) {
3643 + delete _impl;
3647 +int CPUPerformanceInterface::cpu_load(int which_logical_cpu, double* cpu_load) const {
3648 + return _impl->cpu_load(which_logical_cpu, cpu_load);
3651 +int CPUPerformanceInterface::cpu_load_total_process(double* cpu_load) const {
3652 + return _impl->cpu_load_total_process(cpu_load);
3655 +int CPUPerformanceInterface::cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad) const {
3656 + return _impl->cpu_loads_process(pjvmUserLoad, pjvmKernelLoad, psystemTotalLoad);
3659 +int CPUPerformanceInterface::context_switch_rate(double* rate) const {
3660 + return _impl->context_switch_rate(rate);
3663 +class SystemProcessInterface::SystemProcesses : public CHeapObj<mtInternal> {
3664 + friend class SystemProcessInterface;
3665 + private:
3666 + class ProcessIterator : public CHeapObj<mtInternal> {
3667 + friend class SystemProcessInterface::SystemProcesses;
3668 + private:
3669 + DIR* _dir;
3670 + struct dirent* _entry;
3671 + bool _valid;
3673 + ProcessIterator();
3674 + ~ProcessIterator();
3675 + bool initialize();
3677 + bool is_valid() const { return _valid; }
3678 + bool is_valid_entry(struct dirent* const entry) const;
3679 + bool is_dir(const char* const name) const;
3680 + char* allocate_string(const char* const str) const;
3681 + int current(SystemProcess* const process_info);
3682 + int next_process();
3683 + };
3685 + ProcessIterator* _iterator;
3686 + SystemProcesses();
3687 + bool initialize();
3688 + ~SystemProcesses();
3690 + //information about system processes
3691 + int system_processes(SystemProcess** system_processes, int* no_of_sys_processes) const;
3694 +bool SystemProcessInterface::SystemProcesses::ProcessIterator::is_dir(const char* name) const {
3695 + struct stat64 mystat;
3696 + int ret_val = 0;
3698 + ret_val = ::stat64(name, &mystat);
3700 + if (ret_val < 0) {
3701 + return false;
3703 + ret_val = S_ISDIR(mystat.st_mode);
3704 + return ret_val > 0;
3707 +// if it has a numeric name, is a directory and has a 'psinfo' file in it
3708 +bool SystemProcessInterface::SystemProcesses::ProcessIterator::is_valid_entry(struct dirent* entry) const {
3709 + // ignore the "." and ".." directories
3710 + if ((strcmp(entry->d_name, ".") == 0) ||
3711 + (strcmp(entry->d_name, "..") == 0)) {
3712 + return false;
3715 + char buffer[PATH_MAX] = {0};
3716 + uint64_t size = 0;
3717 + bool result = false;
3718 + FILE *fp = NULL;
3720 + if (atoi(entry->d_name) != 0) {
3721 + jio_snprintf(buffer, PATH_MAX, "/proc/%s", entry->d_name);
3723 + if (is_dir(buffer)) {
3724 + memset(buffer, 0, PATH_MAX);
3725 + jio_snprintf(buffer, PATH_MAX, "/proc/%s/psinfo", entry->d_name);
3726 + if ((fp = fopen(buffer, "r")) != NULL) {
3727 + int nread = 0;
3728 + psinfo_t psinfo_data;
3729 + if ((nread = fread(&psinfo_data, 1, sizeof(psinfo_t), fp)) != -1) {
3730 + // only considering system process owned by root
3731 + if (psinfo_data.pr_uid == 0) {
3732 + result = true;
3739 + if (fp != NULL) {
3740 + fclose(fp);
3743 + return result;
3746 +char* SystemProcessInterface::SystemProcesses::ProcessIterator::allocate_string(const char* str) const {
3747 + if (str != NULL) {
3748 + return os::strdup_check_oom(str, mtInternal);
3750 + return NULL;
3753 +int SystemProcessInterface::SystemProcesses::ProcessIterator::current(SystemProcess* process_info) {
3754 + if (!is_valid()) {
3755 + return OS_ERR;
3758 + char psinfo_path[PATH_MAX] = {0};
3759 + jio_snprintf(psinfo_path, PATH_MAX, "/proc/%s/psinfo", _entry->d_name);
3761 + FILE *fp = NULL;
3762 + if ((fp = fopen(psinfo_path, "r")) == NULL) {
3763 + return OS_ERR;
3766 + int nread = 0;
3767 + psinfo_t psinfo_data;
3768 + if ((nread = fread(&psinfo_data, 1, sizeof(psinfo_t), fp)) == -1) {
3769 + fclose(fp);
3770 + return OS_ERR;
3773 + char *exe_path = NULL;
3774 + if ((psinfo_data.pr_fname != NULL) &&
3775 + (psinfo_data.pr_psargs != NULL)) {
3776 + char *path_substring = strstr(psinfo_data.pr_psargs, psinfo_data.pr_fname);
3777 + if (path_substring != NULL) {
3778 + int len = path_substring - psinfo_data.pr_psargs;
3779 + exe_path = NEW_C_HEAP_ARRAY(char, len+1, mtInternal);
3780 + jio_snprintf(exe_path, len, "%s", psinfo_data.pr_psargs);
3781 + exe_path[len] = '\0';
3785 + process_info->set_pid(atoi(_entry->d_name));
3786 + process_info->set_name(allocate_string(psinfo_data.pr_fname));
3787 + process_info->set_path(allocate_string(exe_path));
3788 + process_info->set_command_line(allocate_string(psinfo_data.pr_psargs));
3790 + if (exe_path != NULL) {
3791 + FREE_C_HEAP_ARRAY(char, exe_path);
3794 + if (fp != NULL) {
3795 + fclose(fp);
3798 + return OS_OK;
3801 +int SystemProcessInterface::SystemProcesses::ProcessIterator::next_process() {
3802 + if (!is_valid()) {
3803 + return OS_ERR;
3806 + do {
3807 + _entry = os::readdir(_dir);
3808 + if (_entry == NULL) {
3809 + // Error or reached end. Could use errno to distinguish those cases.
3810 + _valid = false;
3811 + return OS_ERR;
3813 + } while(!is_valid_entry(_entry));
3815 + _valid = true;
3816 + return OS_OK;
3819 +SystemProcessInterface::SystemProcesses::ProcessIterator::ProcessIterator() {
3820 + _dir = NULL;
3821 + _entry = NULL;
3822 + _valid = false;
3825 +bool SystemProcessInterface::SystemProcesses::ProcessIterator::initialize() {
3826 + _dir = os::opendir("/proc");
3827 + _entry = NULL;
3828 + _valid = true;
3829 + next_process();
3831 + return true;
3834 +SystemProcessInterface::SystemProcesses::ProcessIterator::~ProcessIterator() {
3835 + if (_dir != NULL) {
3836 + os::closedir(_dir);
3840 +SystemProcessInterface::SystemProcesses::SystemProcesses() {
3841 + _iterator = NULL;
3844 +bool SystemProcessInterface::SystemProcesses::initialize() {
3845 + _iterator = new SystemProcessInterface::SystemProcesses::ProcessIterator();
3846 + return _iterator->initialize();
3849 +SystemProcessInterface::SystemProcesses::~SystemProcesses() {
3850 + if (_iterator != NULL) {
3851 + delete _iterator;
3855 +int SystemProcessInterface::SystemProcesses::system_processes(SystemProcess** system_processes, int* no_of_sys_processes) const {
3856 + assert(system_processes != NULL, "system_processes pointer is NULL!");
3857 + assert(no_of_sys_processes != NULL, "system_processes counter pointer is NULL!");
3858 + assert(_iterator != NULL, "iterator is NULL!");
3860 + // initialize pointers
3861 + *no_of_sys_processes = 0;
3862 + *system_processes = NULL;
3864 + while (_iterator->is_valid()) {
3865 + SystemProcess* tmp = new SystemProcess();
3866 + _iterator->current(tmp);
3868 + //if already existing head
3869 + if (*system_processes != NULL) {
3870 + //move "first to second"
3871 + tmp->set_next(*system_processes);
3873 + // new head
3874 + *system_processes = tmp;
3875 + // increment
3876 + (*no_of_sys_processes)++;
3877 + // step forward
3878 + _iterator->next_process();
3880 + return OS_OK;
3883 +int SystemProcessInterface::system_processes(SystemProcess** system_procs, int* no_of_sys_processes) const {
3884 + return _impl->system_processes(system_procs, no_of_sys_processes);
3887 +SystemProcessInterface::SystemProcessInterface() {
3888 + _impl = NULL;
3891 +bool SystemProcessInterface::initialize() {
3892 + _impl = new SystemProcessInterface::SystemProcesses();
3893 + return _impl->initialize();
3897 +SystemProcessInterface::~SystemProcessInterface() {
3898 + if (_impl != NULL) {
3899 + delete _impl;
3903 +CPUInformationInterface::CPUInformationInterface() {
3904 + _cpu_info = NULL;
3907 +bool CPUInformationInterface::initialize() {
3908 + _cpu_info = new CPUInformation();
3909 + VM_Version::initialize_cpu_information();
3910 + _cpu_info->set_number_of_hardware_threads(VM_Version::number_of_threads());
3911 + _cpu_info->set_number_of_cores(VM_Version::number_of_cores());
3912 + _cpu_info->set_number_of_sockets(VM_Version::number_of_sockets());
3913 + _cpu_info->set_cpu_name(VM_Version::cpu_name());
3914 + _cpu_info->set_cpu_description(VM_Version::cpu_description());
3915 + return true;
3918 +CPUInformationInterface::~CPUInformationInterface() {
3919 + if (_cpu_info != NULL) {
3920 + if (_cpu_info->cpu_name() != NULL) {
3921 + const char* cpu_name = _cpu_info->cpu_name();
3922 + FREE_C_HEAP_ARRAY(char, cpu_name);
3923 + _cpu_info->set_cpu_name(NULL);
3925 + if (_cpu_info->cpu_description() != NULL) {
3926 + const char* cpu_desc = _cpu_info->cpu_description();
3927 + FREE_C_HEAP_ARRAY(char, cpu_desc);
3928 + _cpu_info->set_cpu_description(NULL);
3930 + delete _cpu_info;
3934 +int CPUInformationInterface::cpu_information(CPUInformation& cpu_info) {
3935 + if (_cpu_info == NULL) {
3936 + return OS_ERR;
3939 + cpu_info = *_cpu_info; // shallow copy assignment
3940 + return OS_OK;
3943 +class NetworkPerformanceInterface::NetworkPerformance : public CHeapObj<mtInternal> {
3944 + friend class NetworkPerformanceInterface;
3945 + private:
3946 + NetworkPerformance();
3947 + NONCOPYABLE(NetworkPerformance);
3948 + bool initialize();
3949 + ~NetworkPerformance();
3950 + int network_utilization(NetworkInterface** network_interfaces) const;
3953 +NetworkPerformanceInterface::NetworkPerformance::NetworkPerformance() {
3957 +bool NetworkPerformanceInterface::NetworkPerformance::initialize() {
3958 + return true;
3961 +NetworkPerformanceInterface::NetworkPerformance::~NetworkPerformance() {
3965 +int NetworkPerformanceInterface::NetworkPerformance::network_utilization(NetworkInterface** network_interfaces) const
3967 + kstat_ctl_t* ctl = kstat_open();
3968 + if (ctl == NULL) {
3969 + return OS_ERR;
3972 + NetworkInterface* ret = NULL;
3973 + for (kstat_t* k = ctl->kc_chain; k != NULL; k = k->ks_next) {
3974 + if (strcmp(k->ks_class, "net") != 0) {
3975 + continue;
3977 + if (strcmp(k->ks_module, "link") != 0) {
3978 + continue;
3981 + if (kstat_read(ctl, k, NULL) == -1) {
3982 + return OS_ERR;
3985 + uint64_t bytes_in = UINT64_MAX;
3986 + uint64_t bytes_out = UINT64_MAX;
3987 + for (unsigned int i = 0; i < k->ks_ndata; ++i) {
3988 + kstat_named_t* data = &reinterpret_cast<kstat_named_t*>(k->ks_data)[i];
3989 + if (strcmp(data->name, "rbytes64") == 0) {
3990 + bytes_in = data->value.ui64;
3992 + else if (strcmp(data->name, "obytes64") == 0) {
3993 + bytes_out = data->value.ui64;
3997 + if ((bytes_in != UINT64_MAX) && (bytes_out != UINT64_MAX)) {
3998 + NetworkInterface* cur = new NetworkInterface(k->ks_name, bytes_in, bytes_out, ret);
3999 + ret = cur;
4003 + kstat_close(ctl);
4004 + *network_interfaces = ret;
4006 + return OS_OK;
4009 +NetworkPerformanceInterface::NetworkPerformanceInterface() {
4010 + _impl = NULL;
4013 +NetworkPerformanceInterface::~NetworkPerformanceInterface() {
4014 + if (_impl != NULL) {
4015 + delete _impl;
4019 +bool NetworkPerformanceInterface::initialize() {
4020 + _impl = new NetworkPerformanceInterface::NetworkPerformance();
4021 + return _impl->initialize();
4024 +int NetworkPerformanceInterface::network_utilization(NetworkInterface** network_interfaces) const {
4025 + return _impl->network_utilization(network_interfaces);
4027 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os/solaris/os_solaris.cpp jdk22u-jdk-22.0.2-ga/src/hotspot/os/solaris/os_solaris.cpp
4028 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os/solaris/os_solaris.cpp 1970-01-01 01:00:00.000000000 +0100
4029 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/os/solaris/os_solaris.cpp 2024-08-17 19:34:03.900234189 +0200
4030 @@ -0,0 +1,2974 @@
4032 + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
4033 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4035 + * This code is free software; you can redistribute it and/or modify it
4036 + * under the terms of the GNU General Public License version 2 only, as
4037 + * published by the Free Software Foundation.
4039 + * This code is distributed in the hope that it will be useful, but WITHOUT
4040 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
4041 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
4042 + * version 2 for more details (a copy is included in the LICENSE file that
4043 + * accompanied this code).
4045 + * You should have received a copy of the GNU General Public License version
4046 + * 2 along with this work; if not, write to the Free Software Foundation,
4047 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
4049 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
4050 + * or visit www.oracle.com if you need additional information or have any
4051 + * questions.
4053 + */
4055 +// no precompiled headers
4056 +#include "jvm.h"
4057 +#include "classfile/classLoader.hpp"
4058 +#include "classfile/systemDictionary.hpp"
4059 +#include "classfile/vmSymbols.hpp"
4060 +#include "code/icBuffer.hpp"
4061 +#include "code/vtableStubs.hpp"
4062 +#include "compiler/compileBroker.hpp"
4063 +#include "compiler/disassembler.hpp"
4064 +#include "interpreter/interpreter.hpp"
4065 +#include "jvmtifiles/jvmti.h"
4066 +#include "logging/log.hpp"
4067 +#include "logging/logStream.hpp"
4068 +#include "memory/allocation.inline.hpp"
4069 +#include "memory/universe.hpp"
4070 +#include "oops/oop.inline.hpp"
4071 +#include "os_solaris.inline.hpp"
4072 +#include "prims/jniFastGetField.hpp"
4073 +#include "prims/jvm_misc.hpp"
4074 +#include "runtime/arguments.hpp"
4075 +#include "runtime/atomic.hpp"
4076 +#include "runtime/globals.hpp"
4077 +#include "runtime/globals_extension.hpp"
4078 +#include "runtime/interfaceSupport.inline.hpp"
4079 +#include "runtime/java.hpp"
4080 +#include "runtime/javaCalls.hpp"
4081 +#include "runtime/javaThread.hpp"
4082 +#include "runtime/mutexLocker.hpp"
4083 +#include "runtime/objectMonitor.hpp"
4084 +#include "runtime/osInfo.hpp"
4085 +#include "runtime/orderAccess.hpp"
4086 +#include "runtime/osThread.hpp"
4087 +#include "runtime/park.hpp"
4088 +#include "runtime/perfMemory.hpp"
4089 +#include "runtime/sharedRuntime.hpp"
4090 +#include "runtime/statSampler.hpp"
4091 +#include "runtime/stubRoutines.hpp"
4092 +#include "runtime/threadCritical.hpp"
4093 +#include "runtime/threads.hpp"
4094 +#include "runtime/timer.hpp"
4095 +#include "runtime/vm_version.hpp"
4096 +#include "semaphore_posix.hpp"
4097 +#include "services/attachListener.hpp"
4098 +#include "nmt/memTracker.hpp"
4099 +#include "services/runtimeService.hpp"
4100 +#include "signals_posix.hpp"
4101 +#include "utilities/align.hpp"
4102 +#include "utilities/checkedCast.hpp"
4103 +#include "utilities/decoder.hpp"
4104 +#include "utilities/defaultStream.hpp"
4105 +#include "utilities/events.hpp"
4106 +#include "utilities/growableArray.hpp"
4107 +#include "utilities/macros.hpp"
4108 +#include "utilities/vmError.hpp"
4110 +// put OS-includes here
4111 +# include <dlfcn.h>
4112 +# include <errno.h>
4113 +# include <exception>
4114 +# include <link.h>
4115 +# include <poll.h>
4116 +# include <pthread.h>
4117 +# include <setjmp.h>
4118 +# include <signal.h>
4119 +# include <stdio.h>
4120 +# include <alloca.h>
4121 +# include <sys/filio.h>
4122 +# include <sys/ipc.h>
4123 +# include <sys/lwp.h>
4124 +# include <sys/machelf.h> // for elf Sym structure used by dladdr1
4125 +# include <sys/mman.h>
4126 +# include <sys/processor.h>
4127 +# include <sys/procset.h>
4128 +# include <sys/pset.h>
4129 +# include <sys/resource.h>
4130 +# include <sys/shm.h>
4131 +# include <sys/socket.h>
4132 +# include <sys/stat.h>
4133 +# include <sys/systeminfo.h>
4134 +# include <sys/time.h>
4135 +# include <sys/times.h>
4136 +# include <sys/types.h>
4137 +# include <sys/wait.h>
4138 +# include <sys/utsname.h>
4139 +# include <thread.h>
4140 +# include <unistd.h>
4141 +# include <sys/priocntl.h>
4142 +# include <sys/rtpriocntl.h>
4143 +# include <sys/tspriocntl.h>
4144 +# include <sys/iapriocntl.h>
4145 +# include <sys/fxpriocntl.h>
4146 +# include <sys/loadavg.h>
4147 +# include <string.h>
4148 +# include <stdio.h>
4150 +# include <procfs.h>
4152 +#define MAX_PATH (2 * K)
4154 +// for timer info max values which include all bits
4155 +#define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF)
4157 +// Here are some liblgrp types from sys/lgrp_user.h to be able to
4158 +// compile on older systems without this header file.
4160 +#ifndef MADV_ACCESS_LWP
4161 + #define MADV_ACCESS_LWP 7 /* next LWP to access heavily */
4162 +#endif
4163 +#ifndef MADV_ACCESS_MANY
4164 + #define MADV_ACCESS_MANY 8 /* many processes to access heavily */
4165 +#endif
4167 +#ifndef LGRP_RSRC_CPU
4168 + #define LGRP_RSRC_CPU 0 /* CPU resources */
4169 +#endif
4170 +#ifndef LGRP_RSRC_MEM
4171 + #define LGRP_RSRC_MEM 1 /* memory resources */
4172 +#endif
4174 +// guarded in sys/mman.h
4175 +extern "C" {
4176 +extern int getpagesizes(size_t[], int);
4179 +// Values for ThreadPriorityPolicy == 1
4180 +int prio_policy1[CriticalPriority+1] = {
4181 + -99999, 0, 16, 32, 48, 64,
4182 + 80, 96, 112, 124, 127, 127 };
4184 +// System parameters used internally
4185 +static clock_t clock_tics_per_sec = 100;
4187 +// For diagnostics to print a message once. see run_periodic_checks
4188 +static bool check_addr0_done = false;
4190 +address os::Solaris::handler_start; // start pc of thr_sighndlrinfo
4191 +address os::Solaris::handler_end; // end pc of thr_sighndlrinfo
4193 +address os::Solaris::_main_stack_base = NULL; // 4352906 workaround
4195 +os::Solaris::pthread_setname_np_func_t os::Solaris::_pthread_setname_np = NULL;
4197 +// "default" initializers for missing libc APIs
4198 +extern "C" {
4199 + int memcntl(void *, size_t, int, void *, int, int);
4200 + int meminfo(const uint64_t *, int, const uint_t *, int, uint64_t *, uint_t *);
4203 +static inline size_t adjust_stack_size(address base, size_t size) {
4204 + if ((ssize_t)size < 0) {
4205 + // 4759953: Compensate for ridiculous stack size.
4206 + size = max_intx;
4208 + if (size > (size_t)base) {
4209 + // 4812466: Make sure size doesn't allow the stack to wrap the address space.
4210 + size = (size_t)base;
4212 + return size;
4215 +static inline stack_t get_stack_info() {
4216 + stack_t st;
4217 + int retval = thr_stksegment(&st);
4218 + st.ss_size = adjust_stack_size((address)st.ss_sp, st.ss_size);
4219 + assert(retval == 0, "incorrect return value from thr_stksegment");
4220 + assert((address)&st < (address)st.ss_sp, "Invalid stack base returned");
4221 + assert((address)&st > (address)st.ss_sp-st.ss_size, "Invalid stack size returned");
4222 + return st;
4225 +bool os::is_primordial_thread(void) {
4226 + int r = thr_main();
4227 + guarantee(r == 0 || r == 1, "CR6501650 or CR6493689");
4228 + return r == 1;
4231 +address os::Solaris::current_stack_base() {
4232 + bool _is_primordial_thread = os::is_primordial_thread();
4234 + // Workaround 4352906, avoid calls to thr_stksegment by
4235 + // thr_main after the first one (it looks like we trash
4236 + // some data, causing the value for ss_sp to be incorrect).
4237 + if (!_is_primordial_thread || os::Solaris::_main_stack_base == NULL) {
4238 + stack_t st = get_stack_info();
4239 + if (_is_primordial_thread) {
4240 + // cache initial value of stack base
4241 + os::Solaris::_main_stack_base = (address)st.ss_sp;
4243 + return (address)st.ss_sp;
4244 + } else {
4245 + guarantee(os::Solaris::_main_stack_base != NULL, "Attempt to use null cached stack base");
4246 + return os::Solaris::_main_stack_base;
4250 +size_t os::Solaris::current_stack_size() {
4251 + size_t size;
4253 + if (!os::is_primordial_thread()) {
4254 + size = get_stack_info().ss_size;
4255 + } else {
4256 + struct rlimit limits;
4257 + getrlimit(RLIMIT_STACK, &limits);
4258 + size = adjust_stack_size(os::Solaris::_main_stack_base, (size_t)limits.rlim_cur);
4260 + // base may not be page aligned
4261 + address base = current_stack_base();
4262 + address bottom = align_up(base - size, os::vm_page_size());;
4263 + return (size_t)(base - bottom);
4266 +void os::current_stack_base_and_size(address* stack_base, size_t* stack_size) {
4267 + *stack_base = os::Solaris::current_stack_base();
4268 + *stack_size = os::Solaris::current_stack_size();
4271 +jint os::Solaris::_os_thread_limit = 0;
4272 +volatile jint os::Solaris::_os_thread_count = 0;
4274 +julong os::available_memory() {
4275 + return Solaris::available_memory();
4278 +julong os::free_memory() {
4279 + return Solaris::available_memory();
4282 +julong os::Solaris::available_memory() {
4283 + return (julong)sysconf(_SC_AVPHYS_PAGES) * os::vm_page_size();
4286 +julong os::Solaris::_physical_memory = 0;
4288 +julong os::physical_memory() {
4289 + return Solaris::physical_memory();
4292 +static hrtime_t first_hrtime = 0;
4293 +static const hrtime_t hrtime_hz = 1000*1000*1000;
4294 +static volatile hrtime_t max_hrtime = 0;
4297 +void os::Solaris::initialize_system_info() {
4298 + set_processor_count(sysconf(_SC_NPROCESSORS_CONF));
4299 + _physical_memory = (julong)sysconf(_SC_PHYS_PAGES) *
4300 + (julong)sysconf(_SC_PAGESIZE);
4303 +uint os::processor_id() {
4304 + const processorid_t id = ::getcpuid();
4305 + assert(id >= 0 && id < _processor_count, "Invalid processor id");
4306 + return (uint)id;
4309 +int os::active_processor_count() {
4310 + // User has overridden the number of active processors
4311 + if (ActiveProcessorCount > 0) {
4312 + log_trace(os)("active_processor_count: "
4313 + "active processor count set by user : %d",
4314 + ActiveProcessorCount);
4315 + return ActiveProcessorCount;
4318 + int online_cpus = sysconf(_SC_NPROCESSORS_ONLN);
4319 + pid_t pid = getpid();
4320 + psetid_t pset = PS_NONE;
4321 + // Are we running in a processor set or is there any processor set around?
4322 + if (pset_bind(PS_QUERY, P_PID, pid, &pset) == 0) {
4323 + uint_t pset_cpus;
4324 + // Query the number of cpus available to us.
4325 + if (pset_info(pset, NULL, &pset_cpus, NULL) == 0) {
4326 + assert(pset_cpus > 0 && pset_cpus <= online_cpus, "sanity check");
4327 + return pset_cpus;
4330 + // Otherwise return number of online cpus
4331 + return online_cpus;
4334 +void os::set_native_thread_name(const char *name) {
4335 + if (Solaris::_pthread_setname_np != NULL) {
4336 + // Only the first 31 bytes of 'name' are processed by pthread_setname_np
4337 + // but we explicitly copy into a size-limited buffer to avoid any
4338 + // possible overflow.
4339 + char buf[32];
4340 + snprintf(buf, sizeof(buf), "%s", name);
4341 + buf[sizeof(buf) - 1] = '\0';
4342 + Solaris::_pthread_setname_np(pthread_self(), buf);
4346 +void os::init_system_properties_values() {
4347 + // The next steps are taken in the product version:
4348 + //
4349 + // Obtain the JAVA_HOME value from the location of libjvm.so.
4350 + // This library should be located at:
4351 + // <JAVA_HOME>/jre/lib/<arch>/{client|server}/libjvm.so.
4352 + //
4353 + // If "/jre/lib/" appears at the right place in the path, then we
4354 + // assume libjvm.so is installed in a JDK and we use this path.
4355 + //
4356 + // Otherwise exit with message: "Could not create the Java virtual machine."
4357 + //
4358 + // The following extra steps are taken in the debugging version:
4359 + //
4360 + // If "/jre/lib/" does NOT appear at the right place in the path
4361 + // instead of exit check for $JAVA_HOME environment variable.
4362 + //
4363 + // If it is defined and we are able to locate $JAVA_HOME/jre/lib/<arch>,
4364 + // then we append a fake suffix "hotspot/libjvm.so" to this path so
4365 + // it looks like libjvm.so is installed there
4366 + // <JAVA_HOME>/jre/lib/<arch>/hotspot/libjvm.so.
4367 + //
4368 + // Otherwise exit.
4369 + //
4370 + // Important note: if the location of libjvm.so changes this
4371 + // code needs to be changed accordingly.
4373 +// Base path of extensions installed on the system.
4374 +#define SYS_EXT_DIR "/usr/jdk/packages"
4375 +#define EXTENSIONS_DIR "/lib/ext"
4377 + // Buffer that fits several sprintfs.
4378 + // Note that the space for the colon and the trailing null are provided
4379 + // by the nulls included by the sizeof operator.
4380 + const size_t bufsize =
4381 + MAX3((size_t)MAXPATHLEN, // For dll_dir & friends.
4382 + sizeof(SYS_EXT_DIR) + sizeof("/lib/"), // invariant ld_library_path
4383 + (size_t)MAXPATHLEN + sizeof(EXTENSIONS_DIR) + sizeof(SYS_EXT_DIR) + sizeof(EXTENSIONS_DIR)); // extensions dir
4384 + char *buf = NEW_C_HEAP_ARRAY(char, bufsize, mtInternal);
4386 + // sysclasspath, java_home, dll_dir
4388 + char *pslash;
4389 + os::jvm_path(buf, bufsize);
4391 + // Found the full path to libjvm.so.
4392 + // Now cut the path to <java_home>/jre if we can.
4393 + *(strrchr(buf, '/')) = '\0'; // Get rid of /libjvm.so.
4394 + pslash = strrchr(buf, '/');
4395 + if (pslash != NULL) {
4396 + *pslash = '\0'; // Get rid of /{client|server|hotspot}.
4398 + Arguments::set_dll_dir(buf);
4400 + if (pslash != NULL) {
4401 + pslash = strrchr(buf, '/');
4402 + if (pslash != NULL) {
4403 + *pslash = '\0'; // Get rid of /lib.
4406 + Arguments::set_java_home(buf);
4407 + if (!set_boot_path('/', ':')) {
4408 + vm_exit_during_initialization("Failed setting boot class path.", NULL);
4412 + // Where to look for native libraries.
4414 + // Use dlinfo() to determine the correct java.library.path.
4415 + //
4416 + // If we're launched by the Java launcher, and the user
4417 + // does not set java.library.path explicitly on the commandline,
4418 + // the Java launcher sets LD_LIBRARY_PATH for us and unsets
4419 + // LD_LIBRARY_PATH_32 and LD_LIBRARY_PATH_64. In this case
4420 + // dlinfo returns LD_LIBRARY_PATH + crle settings (including
4421 + // /usr/lib), which is exactly what we want.
4422 + //
4423 + // If the user does set java.library.path, it completely
4424 + // overwrites this setting, and always has.
4425 + //
4426 + // If we're not launched by the Java launcher, we may
4427 + // get here with any/all of the LD_LIBRARY_PATH[_32|64]
4428 + // settings. Again, dlinfo does exactly what we want.
4430 + Dl_serinfo info_sz, *info = &info_sz;
4431 + Dl_serpath *path;
4432 + char *library_path;
4433 + char *common_path = buf;
4435 + // Determine search path count and required buffer size.
4436 + if (dlinfo(RTLD_SELF, RTLD_DI_SERINFOSIZE, (void *)info) == -1) {
4437 + FREE_C_HEAP_ARRAY(char, buf);
4438 + vm_exit_during_initialization("dlinfo SERINFOSIZE request", dlerror());
4441 + // Allocate new buffer and initialize.
4442 + info = (Dl_serinfo*)NEW_C_HEAP_ARRAY(char, info_sz.dls_size, mtInternal);
4443 + info->dls_size = info_sz.dls_size;
4444 + info->dls_cnt = info_sz.dls_cnt;
4446 + // Obtain search path information.
4447 + if (dlinfo(RTLD_SELF, RTLD_DI_SERINFO, (void *)info) == -1) {
4448 + FREE_C_HEAP_ARRAY(char, buf);
4449 + FREE_C_HEAP_ARRAY(char, info);
4450 + vm_exit_during_initialization("dlinfo SERINFO request", dlerror());
4453 + path = &info->dls_serpath[0];
4455 + // Note: Due to a legacy implementation, most of the library path
4456 + // is set in the launcher. This was to accommodate linking restrictions
4457 + // on legacy Solaris implementations (which are no longer supported).
4458 + // Eventually, all the library path setting will be done here.
4459 + //
4460 + // However, to prevent the proliferation of improperly built native
4461 + // libraries, the new path component /usr/jdk/packages is added here.
4463 + // Construct the invariant part of ld_library_path.
4464 + sprintf(common_path, SYS_EXT_DIR "/lib");
4466 + // Struct size is more than sufficient for the path components obtained
4467 + // through the dlinfo() call, so only add additional space for the path
4468 + // components explicitly added here.
4469 + size_t library_path_size = info->dls_size + strlen(common_path);
4470 + library_path = NEW_C_HEAP_ARRAY(char, library_path_size, mtInternal);
4471 + library_path[0] = '\0';
4473 + // Construct the desired Java library path from the linker's library
4474 + // search path.
4475 + //
4476 + // For compatibility, it is optimal that we insert the additional path
4477 + // components specific to the Java VM after those components specified
4478 + // in LD_LIBRARY_PATH (if any) but before those added by the ld.so
4479 + // infrastructure.
4480 + if (info->dls_cnt == 0) { // Not sure this can happen, but allow for it.
4481 + strcpy(library_path, common_path);
4482 + } else {
4483 + int inserted = 0;
4484 + uint_t i;
4485 + for (i = 0; i < info->dls_cnt; i++, path++) {
4486 + uint_t flags = path->dls_flags & LA_SER_MASK;
4487 + if (((flags & LA_SER_LIBPATH) == 0) && !inserted) {
4488 + strcat(library_path, common_path);
4489 + strcat(library_path, os::path_separator());
4490 + inserted = 1;
4492 + strcat(library_path, path->dls_name);
4493 + strcat(library_path, os::path_separator());
4495 + // Eliminate trailing path separator.
4496 + library_path[strlen(library_path)-1] = '\0';
4499 + // happens before argument parsing - can't use a trace flag
4500 + // tty->print_raw("init_system_properties_values: native lib path: ");
4501 + // tty->print_raw_cr(library_path);
4503 + // Callee copies into its own buffer.
4504 + Arguments::set_library_path(library_path);
4506 + FREE_C_HEAP_ARRAY(char, library_path);
4507 + FREE_C_HEAP_ARRAY(char, info);
4510 + // Extensions directories.
4511 + sprintf(buf, "%s" EXTENSIONS_DIR ":" SYS_EXT_DIR EXTENSIONS_DIR, Arguments::get_java_home());
4512 + Arguments::set_ext_dirs(buf);
4514 + FREE_C_HEAP_ARRAY(char, buf);
4516 +#undef SYS_EXT_DIR
4517 +#undef EXTENSIONS_DIR
4520 +static thread_t main_thread;
4522 +// Thread start routine for all newly created threads
4523 +extern "C" void* thread_native_entry(void* thread_addr) {
4525 + Thread* thread = (Thread*)thread_addr;
4527 + thread->record_stack_base_and_size();
4529 + // Try to randomize the cache line index of hot stack frames.
4530 + // This helps when threads of the same stack traces evict each other's
4531 + // cache lines. The threads can be either from the same JVM instance, or
4532 + // from different JVM instances. The benefit is especially true for
4533 + // processors with hyperthreading technology.
4534 + static int counter = 0;
4535 + int pid = os::current_process_id();
4536 + alloca(((pid ^ counter++) & 7) * 128);
4538 + int prio;
4540 + thread->initialize_thread_current();
4542 + OSThread* osthr = thread->osthread();
4544 + osthr->set_lwp_id(_lwp_self()); // Store lwp in case we are bound
4546 + log_info(os, thread)("Thread is alive (tid: " UINTX_FORMAT ").",
4547 + os::current_thread_id());
4549 + if (UseNUMA) {
4550 + int lgrp_id = os::numa_get_group_id();
4551 + if (lgrp_id != -1) {
4552 + thread->set_lgrp_id(lgrp_id);
4556 + // Our priority was set when we were created, and stored in the
4557 + // osthread, but couldn't be passed through to our LWP until now.
4558 + // So read back the priority and set it again.
4560 + if (osthr->thread_id() != -1) {
4561 + if (UseThreadPriorities) {
4562 + int prio = osthr->native_priority();
4563 + os::set_native_priority(thread, prio);
4567 + assert(osthr->get_state() == RUNNABLE, "invalid os thread state");
4569 + // initialize signal mask for this thread
4570 + PosixSignals::hotspot_sigmask(thread);
4572 + os::Solaris::init_thread_fpu_state();
4574 + thread->call_run();
4576 + // Note: at this point the thread object may already have deleted itself.
4577 + // Do not dereference it from here on out.
4579 + // One less thread is executing
4580 + // When the VMThread gets here, the main thread may have already exited
4581 + // which frees the CodeHeap containing the Atomic::dec code
4582 + if (thread != VMThread::vm_thread() && VMThread::vm_thread() != NULL) {
4583 + Atomic::dec(&os::Solaris::_os_thread_count);
4586 + log_info(os, thread)("Thread finished (tid: " UINTX_FORMAT ").", os::current_thread_id());
4588 + thr_exit(NULL);
4589 + ShouldNotReachHere();
4591 + return NULL;
4594 +static OSThread* create_os_thread(Thread* thread, thread_t thread_id) {
4595 + // Allocate the OSThread object
4596 + OSThread* osthread = new OSThread();
4597 + if (osthread == NULL) return NULL;
4599 + // Store info on the Solaris thread into the OSThread
4600 + osthread->set_thread_id(thread_id);
4601 + osthread->set_lwp_id(_lwp_self());
4603 + if (UseNUMA) {
4604 + int lgrp_id = os::numa_get_group_id();
4605 + if (lgrp_id != -1) {
4606 + thread->set_lgrp_id(lgrp_id);
4610 + // Initial thread state is INITIALIZED, not SUSPENDED
4611 + osthread->set_state(INITIALIZED);
4613 + return osthread;
4616 +bool os::create_attached_thread(JavaThread* thread) {
4617 +#ifdef ASSERT
4618 + thread->verify_not_published();
4619 +#endif
4620 + OSThread* osthread = create_os_thread(thread, thr_self());
4621 + if (osthread == NULL) {
4622 + return false;
4625 + // Initial thread state is RUNNABLE
4626 + osthread->set_state(RUNNABLE);
4627 + thread->set_osthread(osthread);
4629 + if (os::is_primordial_thread()) {
4630 + os::Solaris::correct_stack_boundaries_for_primordial_thread(thread);
4633 + // initialize signal mask for this thread
4634 + // and save the caller's signal mask
4635 + PosixSignals::hotspot_sigmask(thread);
4637 + log_info(os, thread)("Thread attached (tid: " UINTX_FORMAT ").",
4638 + os::current_thread_id());
4640 + return true;
4643 +bool os::create_main_thread(JavaThread* thread) {
4644 +#ifdef ASSERT
4645 + thread->verify_not_published();
4646 +#endif
4647 + if (_starting_thread == NULL) {
4648 + _starting_thread = create_os_thread(thread, main_thread);
4649 + if (_starting_thread == NULL) {
4650 + return false;
4654 + // The primodial thread is runnable from the start
4655 + _starting_thread->set_state(RUNNABLE);
4657 + thread->set_osthread(_starting_thread);
4659 + // initialize signal mask for this thread
4660 + // and save the caller's signal mask
4661 + PosixSignals::hotspot_sigmask(thread);
4663 + return true;
4666 +// Helper function to trace thread attributes, similar to os::Posix::describe_pthread_attr()
4667 +static char* describe_thr_create_attributes(char* buf, size_t buflen,
4668 + size_t stacksize, long flags) {
4669 + stringStream ss(buf, buflen);
4670 + ss.print("stacksize: " SIZE_FORMAT "k, ", stacksize / 1024);
4671 + ss.print("flags: ");
4672 + #define PRINT_FLAG(f) if (flags & f) ss.print( #f " ");
4673 + #define ALL(X) \
4674 + X(THR_SUSPENDED) \
4675 + X(THR_DETACHED) \
4676 + X(THR_BOUND) \
4677 + X(THR_NEW_LWP) \
4678 + X(THR_DAEMON)
4679 + ALL(PRINT_FLAG)
4680 + #undef ALL
4681 + #undef PRINT_FLAG
4682 + return buf;
4685 +// return default stack size for thr_type
4686 +size_t os::Posix::default_stack_size(os::ThreadType thr_type) {
4687 + // default stack size when not specified by caller is 1M (2M for LP64)
4688 + size_t s = (BytesPerWord >> 2) * K * K;
4689 + return s;
4692 +bool os::create_thread(Thread* thread, ThreadType thr_type,
4693 + size_t req_stack_size) {
4694 + // Allocate the OSThread object
4695 + OSThread* osthread = new OSThread();
4696 + if (osthread == NULL) {
4697 + return false;
4700 + // calculate stack size if it's not specified by caller
4701 + size_t stack_size = os::Posix::get_initial_stack_size(thr_type, req_stack_size);
4703 + // Initial state is ALLOCATED but not INITIALIZED
4704 + osthread->set_state(ALLOCATED);
4706 + if (os::Solaris::_os_thread_count > os::Solaris::_os_thread_limit) {
4707 + // We got lots of threads. Check if we still have some address space left.
4708 + // Need to be at least 5Mb of unreserved address space. We do check by
4709 + // trying to reserve some.
4710 + const size_t VirtualMemoryBangSize = 20*K*K;
4711 + char* mem = os::reserve_memory(VirtualMemoryBangSize);
4712 + if (mem == NULL) {
4713 + delete osthread;
4714 + return false;
4715 + } else {
4716 + // Release the memory again
4717 + os::release_memory(mem, VirtualMemoryBangSize);
4721 + // Setup osthread because the child thread may need it.
4722 + thread->set_osthread(osthread);
4724 + // Create the Solaris thread
4725 + thread_t tid = 0;
4726 + long flags = THR_DETACHED | THR_SUSPENDED;
4727 + int status;
4729 + // Mark that we don't have an lwp or thread id yet.
4730 + // In case we attempt to set the priority before the thread starts.
4731 + osthread->set_lwp_id(-1);
4732 + osthread->set_thread_id(-1);
4734 + status = thr_create(NULL, stack_size, thread_native_entry, thread, flags, &tid);
4736 + char buf[64];
4737 + if (status == 0) {
4738 + log_info(os, thread)("Thread \"%s\" started (tid: " UINTX_FORMAT ", attributes: %s). ",
4739 + thread->name(), (uintx) tid, describe_thr_create_attributes(buf, sizeof(buf), stack_size, flags));
4740 + } else {
4741 + log_warning(os, thread)("Failed to start thread \"%s\" - thr_create failed (%s) for attributes: %s.",
4742 + thread->name(), os::errno_name(status), describe_thr_create_attributes(buf, sizeof(buf), stack_size, flags));
4743 + // Log some OS information which might explain why creating the thread failed.
4744 + log_info(os, thread)("Number of threads approx. running in the VM: %d", Threads::number_of_threads());
4745 + LogStream st(Log(os, thread)::info());
4746 + os::Posix::print_rlimit_info(&st);
4747 + os::print_memory_info(&st);
4750 + if (status != 0) {
4751 + thread->set_osthread(NULL);
4752 + // Need to clean up stuff we've allocated so far
4753 + delete osthread;
4754 + return false;
4757 + Atomic::inc(&os::Solaris::_os_thread_count);
4759 + // Store info on the Solaris thread into the OSThread
4760 + osthread->set_thread_id(tid);
4762 + // Remember that we created this thread so we can set priority on it
4763 + osthread->set_vm_created();
4765 + // Most thread types will set an explicit priority before starting the thread,
4766 + // but for those that don't we need a valid value to read back in thread_native_entry.
4767 + osthread->set_native_priority(NormPriority);
4769 + // Initial thread state is INITIALIZED, not SUSPENDED
4770 + osthread->set_state(INITIALIZED);
4772 + // The thread is returned suspended (in state INITIALIZED), and is started higher up in the call chain
4773 + return true;
4776 +// CR 7190089: on Solaris, primordial thread's stack needs adjusting.
4777 +// Without the adjustment, stack size is incorrect if stack is set to unlimited (ulimit -s unlimited).
4778 +void os::Solaris::correct_stack_boundaries_for_primordial_thread(Thread* thr) {
4779 + assert(is_primordial_thread(), "Call only for primordial thread");
4781 + JavaThread* jt = (JavaThread *)thr;
4782 + assert(jt != NULL, "Sanity check");
4783 + size_t stack_size;
4784 + address base = jt->stack_base();
4785 + if (Arguments::created_by_java_launcher()) {
4786 + // Use 2MB to allow for Solaris 7 64 bit mode.
4787 + stack_size = JavaThread::stack_size_at_create() == 0
4788 + ? 2048*K : JavaThread::stack_size_at_create();
4790 + // There are rare cases when we may have already used more than
4791 + // the basic stack size allotment before this method is invoked.
4792 + // Attempt to allow for a normally sized java_stack.
4793 + size_t current_stack_offset = (size_t)(base - (address)&stack_size);
4794 + stack_size += ReservedSpace::page_align_size_down(current_stack_offset);
4795 + } else {
4796 + // 6269555: If we were not created by a Java launcher, i.e. if we are
4797 + // running embedded in a native application, treat the primordial thread
4798 + // as much like a native attached thread as possible. This means using
4799 + // the current stack size from thr_stksegment(), unless it is too large
4800 + // to reliably setup guard pages. A reasonable max size is 8MB.
4801 + size_t current_size = current_stack_size();
4802 + // This should never happen, but just in case....
4803 + if (current_size == 0) current_size = 2 * K * K;
4804 + stack_size = current_size > (8 * K * K) ? (8 * K * K) : current_size;
4806 + address bottom = align_up(base - stack_size, os::vm_page_size());;
4807 + stack_size = (size_t)(base - bottom);
4809 + assert(stack_size > 0, "Stack size calculation problem");
4811 + if (stack_size > jt->stack_size()) {
4812 +#ifndef PRODUCT
4813 + struct rlimit limits;
4814 + getrlimit(RLIMIT_STACK, &limits);
4815 + size_t size = adjust_stack_size(base, (size_t)limits.rlim_cur);
4816 + assert(size >= jt->stack_size(), "Stack size problem in main thread");
4817 +#endif
4818 + tty->print_cr("Stack size of " SIZE_FORMAT " Kb exceeds current limit of " SIZE_FORMAT " Kb.\n"
4819 + "(Stack sizes are rounded up to a multiple of the system page size.)\n"
4820 + "See limit(1) to increase the stack size limit.",
4821 + stack_size / K, jt->stack_size() / K);
4822 + vm_exit(1);
4824 + assert(jt->stack_size() >= stack_size,
4825 + "Attempt to map more stack than was allocated");
4826 + jt->set_stack_size(stack_size);
4832 +// Free Solaris resources related to the OSThread
4833 +void os::free_thread(OSThread* osthread) {
4834 + assert(osthread != NULL, "os::free_thread but osthread not set");
4836 + // We are told to free resources of the argument thread,
4837 + // but we can only really operate on the current thread.
4838 + assert(Thread::current()->osthread() == osthread,
4839 + "os::free_thread but not current thread");
4841 + // Restore caller's signal mask
4842 + sigset_t sigmask = osthread->caller_sigmask();
4843 + pthread_sigmask(SIG_SETMASK, &sigmask, NULL);
4845 + delete osthread;
4848 +void os::pd_start_thread(Thread* thread) {
4849 + int status = thr_continue(thread->osthread()->thread_id());
4850 + assert_status(status == 0, status, "thr_continue failed");
4854 +intx os::current_thread_id() {
4855 + return (intx)thr_self();
4858 +static pid_t _initial_pid = 0;
4860 +int os::current_process_id() {
4861 + return (int)(_initial_pid ? _initial_pid : getpid());
4864 +// gethrtime() should be monotonic according to the documentation,
4865 +// but some virtualized platforms are known to break this guarantee.
4866 +// getTimeNanos() must be guaranteed not to move backwards, so we
4867 +// are forced to add a check here.
4868 +inline hrtime_t getTimeNanos() {
4869 + const hrtime_t now = gethrtime();
4870 + const hrtime_t prev = max_hrtime;
4871 + if (now <= prev) {
4872 + return prev; // same or retrograde time;
4874 + const hrtime_t obsv = Atomic::cmpxchg(&max_hrtime, prev, now);
4875 + assert(obsv >= prev, "invariant"); // Monotonicity
4876 + // If the CAS succeeded then we're done and return "now".
4877 + // If the CAS failed and the observed value "obsv" is >= now then
4878 + // we should return "obsv". If the CAS failed and now > obsv > prv then
4879 + // some other thread raced this thread and installed a new value, in which case
4880 + // we could either (a) retry the entire operation, (b) retry trying to install now
4881 + // or (c) just return obsv. We use (c). No loop is required although in some cases
4882 + // we might discard a higher "now" value in deference to a slightly lower but freshly
4883 + // installed obsv value. That's entirely benign -- it admits no new orderings compared
4884 + // to (a) or (b) -- and greatly reduces coherence traffic.
4885 + // We might also condition (c) on the magnitude of the delta between obsv and now.
4886 + // Avoiding excessive CAS operations to hot RW locations is critical.
4887 + // See https://blogs.oracle.com/dave/entry/cas_and_cache_trivia_invalidate
4888 + return (prev == obsv) ? now : obsv;
4891 +double os::elapsedVTime() {
4892 + return (double)gethrvtime() / (double)hrtime_hz;
4895 +// DLL functions
4897 +// This must be hard coded because it's the system's temporary
4898 +// directory not the java application's temp directory, ala java.io.tmpdir.
4899 +const char* os::get_temp_directory() { return "/tmp"; }
4901 +// check if addr is inside libjvm.so
4902 +bool os::address_is_in_vm(address addr) {
4903 + static address libjvm_base_addr;
4904 + Dl_info dlinfo;
4906 + if (libjvm_base_addr == NULL) {
4907 + if (dladdr(CAST_FROM_FN_PTR(void *, os::address_is_in_vm), &dlinfo) != 0) {
4908 + libjvm_base_addr = (address)dlinfo.dli_fbase;
4910 + assert(libjvm_base_addr !=NULL, "Cannot obtain base address for libjvm");
4913 + if (dladdr((void *)addr, &dlinfo) != 0) {
4914 + if (libjvm_base_addr == (address)dlinfo.dli_fbase) return true;
4917 + return false;
4920 +void os::prepare_native_symbols() {
4923 +bool os::dll_address_to_function_name(address addr, char *buf,
4924 + int buflen, int * offset,
4925 + bool demangle) {
4926 + // buf is not optional, but offset is optional
4927 + assert(buf != NULL, "sanity check");
4929 + Dl_info dlinfo;
4931 +#ifdef _LP64
4932 + Elf64_Sym * info;
4933 +#else
4934 + Elf32_Sym * info;
4935 +#endif
4936 + if (dladdr1((void *)addr, &dlinfo, (void **)&info,
4937 + RTLD_DL_SYMENT) != 0) {
4938 + // see if we have a matching symbol that covers our address
4939 + if (dlinfo.dli_saddr != NULL &&
4940 + (char *)dlinfo.dli_saddr + info->st_size > (char *)addr) {
4941 + if (dlinfo.dli_sname != NULL) {
4942 + if (!(demangle && Decoder::demangle(dlinfo.dli_sname, buf, buflen))) {
4943 + jio_snprintf(buf, buflen, "%s", dlinfo.dli_sname);
4945 + if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr;
4946 + return true;
4949 + // no matching symbol so try for just file info
4950 + if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != NULL) {
4951 + if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
4952 + buf, buflen, offset, dlinfo.dli_fname, demangle)) {
4953 + return true;
4957 + buf[0] = '\0';
4958 + if (offset != NULL) *offset = -1;
4959 + return false;
4962 +bool os::dll_address_to_library_name(address addr, char* buf,
4963 + int buflen, int* offset) {
4964 + // buf is not optional, but offset is optional
4965 + assert(buf != NULL, "sanity check");
4967 + Dl_info dlinfo;
4969 + if (dladdr((void*)addr, &dlinfo) != 0) {
4970 + if (dlinfo.dli_fname != NULL) {
4971 + jio_snprintf(buf, buflen, "%s", dlinfo.dli_fname);
4973 + if (dlinfo.dli_fbase != NULL && offset != NULL) {
4974 + *offset = addr - (address)dlinfo.dli_fbase;
4976 + return true;
4979 + buf[0] = '\0';
4980 + if (offset) *offset = -1;
4981 + return false;
4984 +int os::get_loaded_modules_info(os::LoadedModulesCallbackFunc callback, void *param) {
4985 + Dl_info dli;
4986 + // Sanity check?
4987 + if (dladdr(CAST_FROM_FN_PTR(void *, os::get_loaded_modules_info), &dli) == 0 ||
4988 + dli.dli_fname == NULL) {
4989 + return 1;
4992 + void * handle = dlopen(dli.dli_fname, RTLD_LAZY);
4993 + if (handle == NULL) {
4994 + return 1;
4997 + Link_map *map;
4998 + dlinfo(handle, RTLD_DI_LINKMAP, &map);
4999 + if (map == NULL) {
5000 + dlclose(handle);
5001 + return 1;
5004 + while (map->l_prev != NULL) {
5005 + map = map->l_prev;
5008 + while (map != NULL) {
5009 + // Iterate through all map entries and call callback with fields of interest
5010 + if(callback(map->l_name, (address)map->l_addr, (address)0, param)) {
5011 + dlclose(handle);
5012 + return 1;
5014 + map = map->l_next;
5017 + dlclose(handle);
5018 + return 0;
5021 +int _print_dll_info_cb(const char * name, address base_address, address top_address, void * param) {
5022 + outputStream * out = (outputStream *) param;
5023 + out->print_cr(INTPTR_FORMAT " \t%s", (intptr_t)base_address, name);
5024 + return 0;
5027 +void os::print_dll_info(outputStream * st) {
5028 + st->print_cr("Dynamic libraries:"); st->flush();
5029 + if (get_loaded_modules_info(_print_dll_info_cb, (void *)st)) {
5030 + st->print_cr("Error: Cannot print dynamic libraries.");
5034 +static void change_endianness(Elf32_Half& val) {
5035 + unsigned char *ptr = (unsigned char *)&val;
5036 + unsigned char swp = ptr[0];
5037 + ptr[0] = ptr[1];
5038 + ptr[1] = swp;
5041 +// Loads .dll/.so and
5042 +// in case of error it checks if .dll/.so was built for the
5043 +// same architecture as Hotspot is running on
5045 +void * os::dll_load(const char *filename, char *ebuf, int ebuflen) {
5046 + log_info(os)("attempting shared library load of %s", filename);
5048 + void * result= ::dlopen(filename, RTLD_LAZY);
5049 + if (result != NULL) {
5050 + // Successful loading
5051 + Events::log(NULL, "Loaded shared library %s", filename);
5052 + log_info(os)("shared library load of %s was successful", filename);
5053 + return result;
5056 + Elf32_Ehdr elf_head;
5057 + const char* error_report = ::dlerror();
5058 + if (error_report == NULL) {
5059 + error_report = "dlerror returned no error description";
5061 + if (ebuf != NULL && ebuflen > 0) {
5062 + ::strncpy(ebuf, error_report, ebuflen-1);
5063 + ebuf[ebuflen-1]='\0';
5066 + Events::log(NULL, "Loading shared library %s failed, %s", filename, error_report);
5067 + log_info(os)("shared library load of %s failed, %s", filename, error_report);
5069 + int diag_msg_max_length=ebuflen-strlen(ebuf);
5070 + char* diag_msg_buf=ebuf+strlen(ebuf);
5072 + if (diag_msg_max_length==0) {
5073 + // No more space in ebuf for additional diagnostics message
5074 + return NULL;
5078 + int file_descriptor= ::open(filename, O_RDONLY | O_NONBLOCK);
5080 + if (file_descriptor < 0) {
5081 + // Can't open library, report dlerror() message
5082 + return NULL;
5085 + bool failed_to_read_elf_head=
5086 + (sizeof(elf_head)!=
5087 + (::read(file_descriptor, &elf_head,sizeof(elf_head))));
5089 + ::close(file_descriptor);
5090 + if (failed_to_read_elf_head) {
5091 + // file i/o error - report dlerror() msg
5092 + return NULL;
5095 + if (elf_head.e_ident[EI_DATA] != LITTLE_ENDIAN_ONLY(ELFDATA2LSB) BIG_ENDIAN_ONLY(ELFDATA2MSB)) {
5096 + // handle invalid/out of range endianness values
5097 + if (elf_head.e_ident[EI_DATA] == 0 || elf_head.e_ident[EI_DATA] > 2) {
5098 + return NULL;
5100 + change_endianness(elf_head.e_machine);
5103 + typedef struct {
5104 + Elf32_Half code; // Actual value as defined in elf.h
5105 + Elf32_Half compat_class; // Compatibility of archs at VM's sense
5106 + unsigned char elf_class; // 32 or 64 bit
5107 + unsigned char endianess; // MSB or LSB
5108 + char* name; // String representation
5109 + } arch_t;
5111 + static const arch_t arch_array[]={
5112 + {EM_386, EM_386, ELFCLASS32, ELFDATA2LSB, (char*)"IA 32"},
5113 + {EM_486, EM_386, ELFCLASS32, ELFDATA2LSB, (char*)"IA 32"},
5114 + {EM_IA_64, EM_IA_64, ELFCLASS64, ELFDATA2LSB, (char*)"IA 64"},
5115 + {EM_X86_64, EM_X86_64, ELFCLASS64, ELFDATA2LSB, (char*)"AMD 64"},
5116 + {EM_SPARC, EM_SPARC, ELFCLASS32, ELFDATA2MSB, (char*)"Sparc 32"},
5117 + {EM_SPARC32PLUS, EM_SPARC, ELFCLASS32, ELFDATA2MSB, (char*)"Sparc 32"},
5118 + {EM_SPARCV9, EM_SPARCV9, ELFCLASS64, ELFDATA2MSB, (char*)"Sparc v9 64"},
5119 + {EM_PPC, EM_PPC, ELFCLASS32, ELFDATA2MSB, (char*)"Power PC 32"},
5120 + {EM_PPC64, EM_PPC64, ELFCLASS64, ELFDATA2MSB, (char*)"Power PC 64"},
5121 + {EM_ARM, EM_ARM, ELFCLASS32, ELFDATA2LSB, (char*)"ARM"},
5122 + // we only support 64 bit z architecture
5123 + {EM_S390, EM_S390, ELFCLASS64, ELFDATA2MSB, (char*)"IBM System/390"},
5124 + {EM_AARCH64, EM_AARCH64, ELFCLASS64, ELFDATA2LSB, (char*)"AARCH64"}
5125 + };
5127 +#if (defined IA32)
5128 + static Elf32_Half running_arch_code=EM_386;
5129 +#elif (defined AMD64)
5130 + static Elf32_Half running_arch_code=EM_X86_64;
5131 +#elif (defined IA64)
5132 + static Elf32_Half running_arch_code=EM_IA_64;
5133 +#elif (defined __sparc) && (defined _LP64)
5134 + static Elf32_Half running_arch_code=EM_SPARCV9;
5135 +#elif (defined __sparc) && (!defined _LP64)
5136 + static Elf32_Half running_arch_code=EM_SPARC;
5137 +#elif (defined __powerpc64__)
5138 + static Elf32_Half running_arch_code=EM_PPC64;
5139 +#elif (defined __powerpc__)
5140 + static Elf32_Half running_arch_code=EM_PPC;
5141 +#elif (defined ARM)
5142 + static Elf32_Half running_arch_code=EM_ARM;
5143 +#else
5144 + #error Method os::dll_load requires that one of following is defined:\
5145 + IA32, AMD64, IA64, __sparc, __powerpc__, ARM, ARM
5146 +#endif
5148 + // Identify compatibility class for VM's architecture and library's architecture
5149 + // Obtain string descriptions for architectures
5151 + arch_t lib_arch={elf_head.e_machine,0,elf_head.e_ident[EI_CLASS], elf_head.e_ident[EI_DATA], NULL};
5152 + int running_arch_index=-1;
5154 + for (unsigned int i=0; i < ARRAY_SIZE(arch_array); i++) {
5155 + if (running_arch_code == arch_array[i].code) {
5156 + running_arch_index = i;
5158 + if (lib_arch.code == arch_array[i].code) {
5159 + lib_arch.compat_class = arch_array[i].compat_class;
5160 + lib_arch.name = arch_array[i].name;
5164 + assert(running_arch_index != -1,
5165 + "Didn't find running architecture code (running_arch_code) in arch_array");
5166 + if (running_arch_index == -1) {
5167 + // Even though running architecture detection failed
5168 + // we may still continue with reporting dlerror() message
5169 + return NULL;
5172 + if (lib_arch.compat_class != arch_array[running_arch_index].compat_class) {
5173 + if (lib_arch.name != NULL) {
5174 + ::snprintf(diag_msg_buf, diag_msg_max_length-1,
5175 + " (Possible cause: can't load %s .so on a %s platform)",
5176 + lib_arch.name, arch_array[running_arch_index].name);
5177 + } else {
5178 + ::snprintf(diag_msg_buf, diag_msg_max_length-1,
5179 + " (Possible cause: can't load this .so (machine code=0x%x) on a %s platform)",
5180 + lib_arch.code, arch_array[running_arch_index].name);
5182 + return NULL;
5185 + if (lib_arch.endianess != arch_array[running_arch_index].endianess) {
5186 + ::snprintf(diag_msg_buf, diag_msg_max_length-1," (Possible cause: endianness mismatch)");
5187 + return NULL;
5190 + // ELF file class/capacity : 0 - invalid, 1 - 32bit, 2 - 64bit
5191 + if (lib_arch.elf_class > 2 || lib_arch.elf_class < 1) {
5192 + ::snprintf(diag_msg_buf, diag_msg_max_length-1, " (Possible cause: invalid ELF file class)");
5193 + return NULL;
5196 + if (lib_arch.elf_class != arch_array[running_arch_index].elf_class) {
5197 + ::snprintf(diag_msg_buf, diag_msg_max_length-1,
5198 + " (Possible cause: architecture word width mismatch, can't load %d-bit .so on a %d-bit platform)",
5199 + (int) lib_arch.elf_class * 32, arch_array[running_arch_index].elf_class * 32);
5200 + return NULL;
5203 + return NULL;
5206 +static inline time_t get_mtime(const char* filename) {
5207 + struct stat st;
5208 + int ret = os::stat(filename, &st);
5209 + assert(ret == 0, "failed to stat() file '%s': %s", filename, os::strerror(errno));
5210 + return st.st_mtime;
5213 +int os::compare_file_modified_times(const char* file1, const char* file2) {
5214 + time_t t1 = get_mtime(file1);
5215 + time_t t2 = get_mtime(file2);
5216 + return t1 - t2;
5219 +static bool _print_ascii_file(const char* filename, outputStream* st) {
5220 + int fd = ::open(filename, O_RDONLY);
5221 + if (fd == -1) {
5222 + return false;
5225 + char buf[32];
5226 + int bytes;
5227 + while ((bytes = ::read(fd, buf, sizeof(buf))) > 0) {
5228 + st->print_raw(buf, bytes);
5231 + ::close(fd);
5233 + return true;
5236 +void os::print_os_info_brief(outputStream* st) {
5237 + os::Solaris::print_distro_info(st);
5239 + os::Posix::print_uname_info(st);
5241 + os::Solaris::print_libversion_info(st);
5244 +void os::print_os_info(outputStream* st) {
5245 + st->print("OS:");
5247 + os::Solaris::print_distro_info(st);
5249 + os::Posix::print_uname_info(st);
5251 + os::Posix::print_uptime_info(st);
5253 + os::Solaris::print_libversion_info(st);
5255 + os::Posix::print_rlimit_info(st);
5257 + os::Posix::print_load_average(st);
5260 +void os::Solaris::print_distro_info(outputStream* st) {
5261 + if (!_print_ascii_file("/etc/release", st)) {
5262 + st->print("Solaris");
5264 + st->cr();
5267 +void os::get_summary_os_info(char* buf, size_t buflen) {
5268 + strncpy(buf, "Solaris", buflen); // default to plain solaris
5269 + FILE* fp = fopen("/etc/release", "r");
5270 + if (fp != NULL) {
5271 + char tmp[256];
5272 + // Only get the first line and chop out everything but the os name.
5273 + if (fgets(tmp, sizeof(tmp), fp)) {
5274 + char* ptr = tmp;
5275 + // skip past whitespace characters
5276 + while (*ptr != '\0' && (*ptr == ' ' || *ptr == '\t' || *ptr == '\n')) ptr++;
5277 + if (*ptr != '\0') {
5278 + char* nl = strchr(ptr, '\n');
5279 + if (nl != NULL) *nl = '\0';
5280 + strncpy(buf, ptr, buflen);
5283 + fclose(fp);
5287 +void os::Solaris::print_libversion_info(outputStream* st) {
5288 + st->print(" (T2 libthread)");
5289 + st->cr();
5292 +static bool check_addr0(outputStream* st) {
5293 + jboolean status = false;
5294 + const int read_chunk = 200;
5295 + int ret = 0;
5296 + int nmap = 0;
5297 + int fd = ::open("/proc/self/map",O_RDONLY);
5298 + if (fd >= 0) {
5299 + prmap_t *p = NULL;
5300 + char *mbuff = (char *) calloc(read_chunk, sizeof(prmap_t));
5301 + if (NULL == mbuff) {
5302 + ::close(fd);
5303 + return status;
5305 + while ((ret = ::read(fd, mbuff, read_chunk*sizeof(prmap_t))) > 0) {
5306 + //check if read() has not read partial data
5307 + if( 0 != ret % sizeof(prmap_t)){
5308 + break;
5310 + nmap = ret / sizeof(prmap_t);
5311 + p = (prmap_t *)mbuff;
5312 + for(int i = 0; i < nmap; i++){
5313 + if (p->pr_vaddr == 0x0) {
5314 + st->print("Warning: Address: " PTR_FORMAT ", Size: " SIZE_FORMAT "K, ",p->pr_vaddr, p->pr_size/1024);
5315 + st->print("Mapped file: %s, ", p->pr_mapname[0] == '\0' ? "None" : p->pr_mapname);
5316 + st->print("Access: ");
5317 + st->print("%s",(p->pr_mflags & MA_READ) ? "r" : "-");
5318 + st->print("%s",(p->pr_mflags & MA_WRITE) ? "w" : "-");
5319 + st->print("%s",(p->pr_mflags & MA_EXEC) ? "x" : "-");
5320 + st->cr();
5321 + status = true;
5323 + p++;
5326 + free(mbuff);
5327 + ::close(fd);
5329 + return status;
5332 +void os::get_summary_cpu_info(char* buf, size_t buflen) {
5333 + // Get MHz with system call. We don't seem to already have this.
5334 + processor_info_t stats;
5335 + processorid_t id = getcpuid();
5336 + int clock = 0;
5337 + if (processor_info(id, &stats) != -1) {
5338 + clock = stats.pi_clock; // pi_processor_type isn't more informative than below
5340 + snprintf(buf, buflen, "64 bit %d MHz", clock);
5343 +void os::pd_print_cpu_info(outputStream* st, char* buf, size_t buflen) {
5344 + // Nothing to do for now.
5347 +void os::print_memory_info(outputStream* st) {
5348 + st->print("Memory:");
5349 + st->print(" " SIZE_FORMAT "k page", os::vm_page_size()>>10);
5350 + st->print(", physical " UINT64_FORMAT "k", os::physical_memory()>>10);
5351 + st->print("(" UINT64_FORMAT "k free)", os::available_memory() >> 10);
5352 + st->cr();
5353 + (void) check_addr0(st);
5356 +static int Maxsignum = 0;
5358 +static char saved_jvm_path[MAXPATHLEN] = { 0 };
5360 +// Find the full path to the current module, libjvm.so
5361 +void os::jvm_path(char *buf, jint buflen) {
5362 + // Error checking.
5363 + if (buflen < MAXPATHLEN) {
5364 + assert(false, "must use a large-enough buffer");
5365 + buf[0] = '\0';
5366 + return;
5368 + // Lazy resolve the path to current module.
5369 + if (saved_jvm_path[0] != 0) {
5370 + strcpy(buf, saved_jvm_path);
5371 + return;
5374 + Dl_info dlinfo;
5375 + int ret = dladdr(CAST_FROM_FN_PTR(void *, os::jvm_path), &dlinfo);
5376 + assert(ret != 0, "cannot locate libjvm");
5377 + if (ret != 0 && dlinfo.dli_fname != NULL) {
5378 + if (os::Posix::realpath((char *)dlinfo.dli_fname, buf, buflen) == NULL) {
5379 + return;
5381 + } else {
5382 + buf[0] = '\0';
5383 + return;
5386 + if (Arguments::sun_java_launcher_is_altjvm()) {
5387 + // Support for the java launcher's '-XXaltjvm=<path>' option. Typical
5388 + // value for buf is "<JAVA_HOME>/jre/lib/<arch>/<vmtype>/libjvm.so".
5389 + // If "/jre/lib/" appears at the right place in the string, then
5390 + // assume we are installed in a JDK and we're done. Otherwise, check
5391 + // for a JAVA_HOME environment variable and fix up the path so it
5392 + // looks like libjvm.so is installed there (append a fake suffix
5393 + // hotspot/libjvm.so).
5394 + const char *p = buf + strlen(buf) - 1;
5395 + for (int count = 0; p > buf && count < 5; ++count) {
5396 + for (--p; p > buf && *p != '/'; --p)
5397 + /* empty */ ;
5400 + if (strncmp(p, "/jre/lib/", 9) != 0) {
5401 + // Look for JAVA_HOME in the environment.
5402 + char* java_home_var = ::getenv("JAVA_HOME");
5403 + if (java_home_var != NULL && java_home_var[0] != 0) {
5404 + char* jrelib_p;
5405 + int len;
5407 + // Check the current module name "libjvm.so".
5408 + p = strrchr(buf, '/');
5409 + assert(strstr(p, "/libjvm") == p, "invalid library name");
5411 + if (os::Posix::realpath(java_home_var, buf, buflen) == NULL) {
5412 + return;
5414 + // determine if this is a legacy image or modules image
5415 + // modules image doesn't have "jre" subdirectory
5416 + len = strlen(buf);
5417 + assert(len < buflen, "Ran out of buffer space");
5418 + jrelib_p = buf + len;
5419 + snprintf(jrelib_p, buflen-len, "/jre/lib");
5420 + if (0 != access(buf, F_OK)) {
5421 + snprintf(jrelib_p, buflen-len, "/lib");
5424 + if (0 == access(buf, F_OK)) {
5425 + // Use current module name "libjvm.so"
5426 + len = strlen(buf);
5427 + snprintf(buf + len, buflen-len, "/hotspot/libjvm.so");
5428 + } else {
5429 + // Go back to path of .so
5430 + if (os::Posix::realpath((char *)dlinfo.dli_fname, buf, buflen) == NULL) {
5431 + return;
5438 + strncpy(saved_jvm_path, buf, MAXPATHLEN);
5439 + saved_jvm_path[MAXPATHLEN - 1] = '\0';
5442 +////////////////////////////////////////////////////////////////////////////////
5443 +// Virtual Memory
5445 +static bool recoverable_mmap_error(int err) {
5446 + // See if the error is one we can let the caller handle. This
5447 + // list of errno values comes from the Solaris mmap(2) man page.
5448 + switch (err) {
5449 + case EBADF:
5450 + case EINVAL:
5451 + case ENOTSUP:
5452 + // let the caller deal with these errors
5453 + return true;
5455 + default:
5456 + // Any remaining errors on this OS can cause our reserved mapping
5457 + // to be lost. That can cause confusion where different data
5458 + // structures think they have the same memory mapped. The worst
5459 + // scenario is if both the VM and a library think they have the
5460 + // same memory mapped.
5461 + return false;
5465 +static void warn_fail_commit_memory(char* addr, size_t bytes, bool exec,
5466 + int err) {
5467 + warning("INFO: os::commit_memory(" PTR_FORMAT ", " SIZE_FORMAT
5468 + ", %d) failed; error='%s' (errno=%d)", p2i(addr), bytes, exec,
5469 + os::strerror(err), err);
5472 +static void warn_fail_commit_memory(char* addr, size_t bytes,
5473 + size_t alignment_hint, bool exec,
5474 + int err) {
5475 + warning("INFO: os::commit_memory(" PTR_FORMAT ", " SIZE_FORMAT
5476 + ", " SIZE_FORMAT ", %d) failed; error='%s' (errno=%d)", p2i(addr),
5477 + bytes, alignment_hint, exec, os::strerror(err), err);
5480 +int os::Solaris::commit_memory_impl(char* addr, size_t bytes, bool exec) {
5481 + int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE;
5482 + size_t size = bytes;
5483 + char *res = Solaris::mmap_chunk(addr, size, MAP_PRIVATE|MAP_FIXED, prot);
5484 + if (res != NULL) {
5485 + if (UseNUMAInterleaving) {
5486 + numa_make_global(addr, bytes);
5488 + return 0;
5491 + int err = errno; // save errno from mmap() call in mmap_chunk()
5493 + if (!recoverable_mmap_error(err)) {
5494 + warn_fail_commit_memory(addr, bytes, exec, err);
5495 + vm_exit_out_of_memory(bytes, OOM_MMAP_ERROR, "committing reserved memory.");
5498 + return err;
5501 +bool os::pd_commit_memory(char* addr, size_t bytes, bool exec) {
5502 + return Solaris::commit_memory_impl(addr, bytes, exec) == 0;
5505 +void os::pd_commit_memory_or_exit(char* addr, size_t bytes, bool exec,
5506 + const char* mesg) {
5507 + assert(mesg != NULL, "mesg must be specified");
5508 + int err = os::Solaris::commit_memory_impl(addr, bytes, exec);
5509 + if (err != 0) {
5510 + // the caller wants all commit errors to exit with the specified mesg:
5511 + warn_fail_commit_memory(addr, bytes, exec, err);
5512 + vm_exit_out_of_memory(bytes, OOM_MMAP_ERROR, "%s", mesg);
5516 +size_t os::Solaris::page_size_for_alignment(size_t alignment) {
5517 + assert(is_aligned(alignment, (size_t) os::vm_page_size()),
5518 + SIZE_FORMAT " is not aligned to " SIZE_FORMAT,
5519 + alignment, (size_t) os::vm_page_size());
5521 + int page_sizes_max = 9;
5522 + size_t _illumos_page_sizes[page_sizes_max];
5523 + int n = getpagesizes(_illumos_page_sizes, page_sizes_max);
5524 + for (int i = 0; _illumos_page_sizes[i] != 0; i++) {
5525 + if (is_aligned(alignment, _illumos_page_sizes[i])) {
5526 + return _illumos_page_sizes[i];
5530 + return (size_t) os::vm_page_size();
5533 +int os::Solaris::commit_memory_impl(char* addr, size_t bytes,
5534 + size_t alignment_hint, bool exec) {
5535 + int err = Solaris::commit_memory_impl(addr, bytes, exec);
5536 + if (err == 0 && UseLargePages && alignment_hint > 0) {
5537 + assert(is_aligned(bytes, alignment_hint),
5538 + SIZE_FORMAT " is not aligned to " SIZE_FORMAT, bytes, alignment_hint);
5540 + // The syscall memcntl requires an exact page size (see man memcntl for details).
5541 + size_t page_size = page_size_for_alignment(alignment_hint);
5542 + if (page_size > (size_t) os::vm_page_size()) {
5543 + (void)Solaris::setup_large_pages(addr, bytes, page_size);
5546 + return err;
5549 +bool os::pd_commit_memory(char* addr, size_t bytes, size_t alignment_hint,
5550 + bool exec) {
5551 + return Solaris::commit_memory_impl(addr, bytes, alignment_hint, exec) == 0;
5554 +void os::pd_commit_memory_or_exit(char* addr, size_t bytes,
5555 + size_t alignment_hint, bool exec,
5556 + const char* mesg) {
5557 + assert(mesg != NULL, "mesg must be specified");
5558 + int err = os::Solaris::commit_memory_impl(addr, bytes, alignment_hint, exec);
5559 + if (err != 0) {
5560 + // the caller wants all commit errors to exit with the specified mesg:
5561 + warn_fail_commit_memory(addr, bytes, alignment_hint, exec, err);
5562 + vm_exit_out_of_memory(bytes, OOM_MMAP_ERROR, "%s", mesg);
5566 +// Uncommit the pages in a specified region.
5567 +void os::pd_free_memory(char* addr, size_t bytes, size_t alignment_hint) {
5568 + if (posix_madvise(addr, bytes, MADV_FREE) < 0) {
5569 + debug_only(warning("MADV_FREE failed."));
5570 + return;
5574 +bool os::pd_create_stack_guard_pages(char* addr, size_t size) {
5575 + return os::commit_memory(addr, size, !ExecMem);
5578 +bool os::remove_stack_guard_pages(char* addr, size_t size) {
5579 + return os::uncommit_memory(addr, size);
5582 +// Change the page size in a given range.
5583 +void os::pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint) {
5584 + assert((intptr_t)addr % alignment_hint == 0, "Address should be aligned.");
5585 + assert((intptr_t)(addr + bytes) % alignment_hint == 0, "End should be aligned.");
5586 + if (UseLargePages) {
5587 + size_t page_size = Solaris::page_size_for_alignment(alignment_hint);
5588 + if (page_size > (size_t) os::vm_page_size()) {
5589 + Solaris::setup_large_pages(addr, bytes, page_size);
5594 +// Tell the OS to make the range local to the first-touching LWP
5595 +void os::numa_make_local(char *addr, size_t bytes, int lgrp_hint) {
5596 + assert((intptr_t)addr % os::vm_page_size() == 0, "Address should be page-aligned.");
5597 + if (posix_madvise(addr, bytes, MADV_ACCESS_LWP) < 0) {
5598 + debug_only(warning("MADV_ACCESS_LWP failed."));
5602 +// Tell the OS that this range would be accessed from different LWPs.
5603 +void os::numa_make_global(char *addr, size_t bytes) {
5604 + assert((intptr_t)addr % os::vm_page_size() == 0, "Address should be page-aligned.");
5605 + if (posix_madvise(addr, bytes, MADV_ACCESS_MANY) < 0) {
5606 + debug_only(warning("MADV_ACCESS_MANY failed."));
5610 +// Get the number of the locality groups.
5611 +size_t os::numa_get_groups_num() {
5612 + size_t n = Solaris::lgrp_nlgrps(Solaris::lgrp_cookie());
5613 + return n != -1 ? n : 1;
5616 +// Get a list of leaf locality groups. A leaf lgroup is group that
5617 +// doesn't have any children. Typical leaf group is a CPU or a CPU/memory
5618 +// board. An LWP is assigned to one of these groups upon creation.
5619 +size_t os::numa_get_leaf_groups(uint *ids, size_t size) {
5620 + if ((ids[0] = Solaris::lgrp_root(Solaris::lgrp_cookie())) == -1) {
5621 + ids[0] = 0;
5622 + return 1;
5624 + int result_size = 0, top = 1, bottom = 0, cur = 0;
5625 + for (unsigned int k = 0; k < size; k++) {
5626 + int r = Solaris::lgrp_children(Solaris::lgrp_cookie(), ids[cur],
5627 + (Solaris::lgrp_id_t*)&ids[top], size - top);
5628 + if (r == -1) {
5629 + ids[0] = 0;
5630 + return 1;
5632 + if (!r) {
5633 + // That's a leaf node.
5634 + assert(bottom <= cur, "Sanity check");
5635 + // Check if the node has memory
5636 + if (Solaris::lgrp_resources(Solaris::lgrp_cookie(), ids[cur],
5637 + NULL, 0, LGRP_RSRC_MEM) > 0) {
5638 + ids[bottom++] = ids[cur];
5641 + top += r;
5642 + cur++;
5644 + if (bottom == 0) {
5645 + // Handle a situation, when the OS reports no memory available.
5646 + // Assume UMA architecture.
5647 + ids[0] = 0;
5648 + return 1;
5650 + return bottom;
5653 +// Detect the topology change. Typically happens during CPU plugging-unplugging.
5654 +bool os::numa_topology_changed() {
5655 + int is_stale = Solaris::lgrp_cookie_stale(Solaris::lgrp_cookie());
5656 + if (is_stale != -1 && is_stale) {
5657 + Solaris::lgrp_fini(Solaris::lgrp_cookie());
5658 + Solaris::lgrp_cookie_t c = Solaris::lgrp_init(Solaris::LGRP_VIEW_CALLER);
5659 + assert(c != 0, "Failure to initialize LGRP API");
5660 + Solaris::set_lgrp_cookie(c);
5661 + return true;
5663 + return false;
5666 +// Get the group id of the current LWP.
5667 +int os::numa_get_group_id() {
5668 + int lgrp_id = Solaris::lgrp_home(P_LWPID, P_MYID);
5669 + if (lgrp_id == -1) {
5670 + return 0;
5672 + const int size = os::numa_get_groups_num();
5673 + int *ids = (int*)alloca(size * sizeof(int));
5675 + // Get the ids of all lgroups with memory; r is the count.
5676 + int r = Solaris::lgrp_resources(Solaris::lgrp_cookie(), lgrp_id,
5677 + (Solaris::lgrp_id_t*)ids, size, LGRP_RSRC_MEM);
5678 + if (r <= 0) {
5679 + return 0;
5681 + return ids[os::random() % r];
5684 +int os::numa_get_group_id_for_address(const void* address) {
5685 + return 0;
5688 +bool os::numa_get_group_ids_for_range(const void** addresses, int* lgrp_ids, size_t count) {
5689 + return false;
5692 +bool os::pd_uncommit_memory(char* addr, size_t bytes, bool exec) {
5693 + size_t size = bytes;
5694 + // Map uncommitted pages PROT_NONE so we fail early if we touch an
5695 + // uncommitted page. Otherwise, the read/write might succeed if we
5696 + // have enough swap space to back the physical page.
5697 + return
5698 + NULL != Solaris::mmap_chunk(addr, size,
5699 + MAP_PRIVATE|MAP_FIXED|MAP_NORESERVE,
5700 + PROT_NONE);
5703 +char* os::Solaris::mmap_chunk(char *addr, size_t size, int flags, int prot) {
5704 + char *b = (char *)mmap(addr, size, prot, flags, os::Solaris::_dev_zero_fd, 0);
5706 + if (b == MAP_FAILED) {
5707 + return NULL;
5709 + return b;
5712 +char* os::Solaris::anon_mmap(char* requested_addr, size_t bytes) {
5713 + char* addr = requested_addr;
5714 + int flags = MAP_PRIVATE | MAP_NORESERVE;
5716 + // Map uncommitted pages PROT_NONE so we fail early if we touch an
5717 + // uncommitted page. Otherwise, the read/write might succeed if we
5718 + // have enough swap space to back the physical page.
5719 + return mmap_chunk(addr, bytes, flags, PROT_NONE);
5722 +char* os::pd_reserve_memory(size_t bytes, bool exec) {
5723 + char* addr = Solaris::anon_mmap(NULL, bytes);
5725 + return addr;
5728 +char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, int file_desc) {
5729 + assert(file_desc >= 0, "file_desc is not valid");
5730 + char* result = pd_attempt_reserve_memory_at(requested_addr, bytes, !ExecMem);
5731 + if (result != NULL) {
5732 + if (replace_existing_mapping_with_file_mapping(result, bytes, file_desc) == NULL) {
5733 + vm_exit_during_initialization(err_msg("Error in mapping Java heap at the given filesystem directory"));
5736 + return result;
5739 +// Reserve memory at an arbitrary address, only if that area is
5740 +// available (and not reserved for something else).
5742 +char* os::pd_attempt_reserve_memory_at(char* requested_addr, size_t bytes, bool exec) {
5743 + // Assert only that the size is a multiple of the page size, since
5744 + // that's all that mmap requires, and since that's all we really know
5745 + // about at this low abstraction level. If we need higher alignment,
5746 + // we can either pass an alignment to this method or verify alignment
5747 + // in one of the methods further up the call chain. See bug 5044738.
5748 + assert(bytes % os::vm_page_size() == 0, "reserving unexpected size block");
5750 + // Since snv_84, Solaris attempts to honor the address hint - see 5003415.
5751 + char* addr = Solaris::anon_mmap(requested_addr, bytes);
5753 + volatile int err = errno;
5754 + if (addr == requested_addr) {
5755 + return addr;
5758 + if (addr != NULL) {
5759 + pd_unmap_memory(addr, bytes);
5762 + return NULL;
5765 +bool os::pd_release_memory(char* addr, size_t bytes) {
5766 + size_t size = bytes;
5767 + return munmap(addr, size) == 0;
5770 +static bool solaris_mprotect(char* addr, size_t bytes, int prot) {
5771 + assert(addr == (char*)align_down((uintptr_t)addr, os::vm_page_size()),
5772 + "addr must be page aligned");
5773 + Events::log(NULL, "Protecting memory [" INTPTR_FORMAT "," INTPTR_FORMAT "] with protection modes %x", p2i(addr), p2i(addr+bytes), prot);
5774 + int retVal = mprotect(addr, bytes, prot);
5775 + return retVal == 0;
5778 +// Protect memory (Used to pass readonly pages through
5779 +// JNI GetArray<type>Elements with empty arrays.)
5780 +// Also, used for serialization page and for compressed oops null pointer
5781 +// checking.
5782 +bool os::protect_memory(char* addr, size_t bytes, ProtType prot,
5783 + bool is_committed) {
5784 + unsigned int p = 0;
5785 + switch (prot) {
5786 + case MEM_PROT_NONE: p = PROT_NONE; break;
5787 + case MEM_PROT_READ: p = PROT_READ; break;
5788 + case MEM_PROT_RW: p = PROT_READ|PROT_WRITE; break;
5789 + case MEM_PROT_RWX: p = PROT_READ|PROT_WRITE|PROT_EXEC; break;
5790 + default:
5791 + ShouldNotReachHere();
5793 + // is_committed is unused.
5794 + return solaris_mprotect(addr, bytes, p);
5797 +// guard_memory and unguard_memory only happens within stack guard pages.
5798 +// Since ISM pertains only to the heap, guard and unguard memory should not
5799 +/// happen with an ISM region.
5800 +bool os::guard_memory(char* addr, size_t bytes) {
5801 + return solaris_mprotect(addr, bytes, PROT_NONE);
5804 +bool os::unguard_memory(char* addr, size_t bytes) {
5805 + return solaris_mprotect(addr, bytes, PROT_READ|PROT_WRITE);
5808 +// Large page support
5809 +static size_t _large_page_size = 0;
5811 +bool os::Solaris::mpss_sanity_check(bool warn, size_t* page_size) {
5812 + // Find the page sizes supported by the system
5813 + int page_sizes_max = 9;
5814 + size_t _illumos_page_sizes[page_sizes_max];
5815 + int n = getpagesizes(_illumos_page_sizes, page_sizes_max);
5816 + assert(n > 0, "illumos bug?");
5818 + if (n == 1) return false; // Only one page size available.
5820 + // Skip sizes larger than 4M (or LargePageSizeInBytes if it was set)
5821 + const size_t size_limit =
5822 + FLAG_IS_DEFAULT(LargePageSizeInBytes) ? 4 * M : LargePageSizeInBytes;
5823 + int beg;
5824 + for (beg = 0; beg < n; ++beg) {
5825 + if (_illumos_page_sizes[beg] <= size_limit) {
5826 + _page_sizes.add(_illumos_page_sizes[beg]);
5827 + if (_illumos_page_sizes[beg] > *page_size) {
5828 + *page_size = _illumos_page_sizes[beg];
5832 + // make sure we add the default
5833 + _page_sizes.add(os::vm_page_size());
5834 + return true;
5837 +void os::large_page_init() {
5838 + if (UseLargePages) {
5839 + // print a warning if any large page related flag is specified on command line
5840 + bool warn_on_failure = !FLAG_IS_DEFAULT(UseLargePages) ||
5841 + !FLAG_IS_DEFAULT(LargePageSizeInBytes);
5843 + UseLargePages = Solaris::mpss_sanity_check(warn_on_failure, &_large_page_size);
5847 +bool os::Solaris::is_valid_page_size(size_t bytes) {
5848 + return _page_sizes.contains(bytes);
5851 +bool os::Solaris::setup_large_pages(caddr_t start, size_t bytes, size_t align) {
5852 + assert(is_valid_page_size(align), SIZE_FORMAT " is not a valid page size", align);
5853 + assert(is_aligned((void*) start, align),
5854 + PTR_FORMAT " is not aligned to " SIZE_FORMAT, p2i((void*) start), align);
5855 + assert(is_aligned(bytes, align),
5856 + SIZE_FORMAT " is not aligned to " SIZE_FORMAT, bytes, align);
5858 + // Signal to OS that we want large pages for addresses
5859 + // from addr, addr + bytes
5860 + struct memcntl_mha mpss_struct;
5861 + mpss_struct.mha_cmd = MHA_MAPSIZE_VA;
5862 + mpss_struct.mha_pagesize = align;
5863 + mpss_struct.mha_flags = 0;
5864 + // Upon successful completion, memcntl() returns 0
5865 + if (memcntl(start, bytes, MC_HAT_ADVISE, (caddr_t) &mpss_struct, 0, 0)) {
5866 + debug_only(warning("Attempt to use MPSS failed."));
5867 + return false;
5869 + return true;
5872 +char* os::pd_reserve_memory_special(size_t size, size_t alignment, size_t page_size, char* addr, bool exec) {
5873 + fatal("os::reserve_memory_special should not be called on Solaris.");
5874 + return NULL;
5877 +bool os::pd_release_memory_special(char* base, size_t bytes) {
5878 + fatal("os::release_memory_special should not be called on Solaris.");
5879 + return false;
5882 +size_t os::large_page_size() {
5883 + return _large_page_size;
5886 +// MPSS allows application to commit large page memory on demand; with ISM
5887 +// the entire memory region must be allocated as shared memory.
5888 +bool os::can_commit_large_page_memory() {
5889 + return true;
5892 +bool os::can_execute_large_page_memory() {
5893 + return true;
5896 +size_t os::vm_min_address() {
5897 + return _vm_min_address_default;
5900 +// Interface for setting lwp priorities. We are using T2 libthread,
5901 +// which forces the use of bound threads, so all of our threads will
5902 +// be assigned to real lwp's. Using the thr_setprio function is
5903 +// meaningless in this mode so we must adjust the real lwp's priority.
5904 +// The routines below implement the getting and setting of lwp priorities.
5906 +// Note: There are three priority scales used on Solaris. Java priorities
5907 +// which range from 1 to 10, libthread "thr_setprio" scale which range
5908 +// from 0 to 127, and the current scheduling class of the process we
5909 +// are running in. This is typically from -60 to +60.
5910 +// The setting of the lwp priorities is done after a call to thr_setprio
5911 +// so Java priorities are mapped to libthread priorities and we map from
5912 +// the latter to lwp priorities. We don't keep priorities stored in
5913 +// Java priorities since some of our worker threads want to set priorities
5914 +// higher than all Java threads.
5916 +// For related information:
5917 +// (1) man -s 2 priocntl
5918 +// (2) man -s 4 priocntl
5919 +// (3) man dispadmin
5920 +// = librt.so
5921 +// = libthread/common/rtsched.c - thrp_setlwpprio().
5922 +// = ps -cL <pid> ... to validate priority.
5923 +// = sched_get_priority_min and _max
5924 +// pthread_create
5925 +// sched_setparam
5926 +// pthread_setschedparam
5928 +// Assumptions:
5929 +// + We assume that all threads in the process belong to the same
5930 +// scheduling class. IE. an homogenous process.
5931 +// + Must be root or in IA group to change change "interactive" attribute.
5932 +// Priocntl() will fail silently. The only indication of failure is when
5933 +// we read-back the value and notice that it hasn't changed.
5934 +// + Interactive threads enter the runq at the head, non-interactive at the tail.
5935 +// + For RT, change timeslice as well. Invariant:
5936 +// constant "priority integral"
5937 +// Konst == TimeSlice * (60-Priority)
5938 +// Given a priority, compute appropriate timeslice.
5939 +// + Higher numerical values have higher priority.
5941 +// sched class attributes
5942 +typedef struct {
5943 + int schedPolicy; // classID
5944 + int maxPrio;
5945 + int minPrio;
5946 +} SchedInfo;
5949 +static SchedInfo tsLimits, iaLimits, rtLimits, fxLimits;
5951 +#ifdef ASSERT
5952 +static int ReadBackValidate = 1;
5953 +#endif
5954 +static int myClass = 0;
5955 +static int myMin = 0;
5956 +static int myMax = 0;
5957 +static int myCur = 0;
5958 +static bool priocntl_enable = false;
5960 +static const int criticalPrio = FXCriticalPriority;
5961 +static int java_MaxPriority_to_os_priority = 0; // Saved mapping
5964 +// lwp_priocntl_init
5966 +// Try to determine the priority scale for our process.
5968 +// Return errno or 0 if OK.
5970 +static int lwp_priocntl_init() {
5971 + int rslt;
5972 + pcinfo_t ClassInfo;
5973 + pcparms_t ParmInfo;
5974 + int i;
5976 + if (!UseThreadPriorities) return 0;
5978 + // If ThreadPriorityPolicy is 1, switch tables
5979 + if (ThreadPriorityPolicy == 1) {
5980 + for (i = 0; i < CriticalPriority+1; i++)
5981 + os::java_to_os_priority[i] = prio_policy1[i];
5983 + if (UseCriticalJavaThreadPriority) {
5984 + // MaxPriority always maps to the FX scheduling class and criticalPrio.
5985 + // See set_native_priority() and set_lwp_class_and_priority().
5986 + // Save original MaxPriority mapping in case attempt to
5987 + // use critical priority fails.
5988 + java_MaxPriority_to_os_priority = os::java_to_os_priority[MaxPriority];
5989 + // Set negative to distinguish from other priorities
5990 + os::java_to_os_priority[MaxPriority] = -criticalPrio;
5993 + // Get IDs for a set of well-known scheduling classes.
5994 + // TODO-FIXME: GETCLINFO returns the current # of classes in the
5995 + // the system. We should have a loop that iterates over the
5996 + // classID values, which are known to be "small" integers.
5998 + strcpy(ClassInfo.pc_clname, "TS");
5999 + ClassInfo.pc_cid = -1;
6000 + rslt = priocntl(P_ALL, 0, PC_GETCID, (caddr_t)&ClassInfo);
6001 + if (rslt < 0) return errno;
6002 + assert(ClassInfo.pc_cid != -1, "cid for TS class is -1");
6003 + tsLimits.schedPolicy = ClassInfo.pc_cid;
6004 + tsLimits.maxPrio = ((tsinfo_t*)ClassInfo.pc_clinfo)->ts_maxupri;
6005 + tsLimits.minPrio = -tsLimits.maxPrio;
6007 + strcpy(ClassInfo.pc_clname, "IA");
6008 + ClassInfo.pc_cid = -1;
6009 + rslt = priocntl(P_ALL, 0, PC_GETCID, (caddr_t)&ClassInfo);
6010 + if (rslt < 0) return errno;
6011 + assert(ClassInfo.pc_cid != -1, "cid for IA class is -1");
6012 + iaLimits.schedPolicy = ClassInfo.pc_cid;
6013 + iaLimits.maxPrio = ((iainfo_t*)ClassInfo.pc_clinfo)->ia_maxupri;
6014 + iaLimits.minPrio = -iaLimits.maxPrio;
6016 + strcpy(ClassInfo.pc_clname, "RT");
6017 + ClassInfo.pc_cid = -1;
6018 + rslt = priocntl(P_ALL, 0, PC_GETCID, (caddr_t)&ClassInfo);
6019 + if (rslt < 0) return errno;
6020 + assert(ClassInfo.pc_cid != -1, "cid for RT class is -1");
6021 + rtLimits.schedPolicy = ClassInfo.pc_cid;
6022 + rtLimits.maxPrio = ((rtinfo_t*)ClassInfo.pc_clinfo)->rt_maxpri;
6023 + rtLimits.minPrio = 0;
6025 + strcpy(ClassInfo.pc_clname, "FX");
6026 + ClassInfo.pc_cid = -1;
6027 + rslt = priocntl(P_ALL, 0, PC_GETCID, (caddr_t)&ClassInfo);
6028 + if (rslt < 0) return errno;
6029 + assert(ClassInfo.pc_cid != -1, "cid for FX class is -1");
6030 + fxLimits.schedPolicy = ClassInfo.pc_cid;
6031 + fxLimits.maxPrio = ((fxinfo_t*)ClassInfo.pc_clinfo)->fx_maxupri;
6032 + fxLimits.minPrio = 0;
6034 + // Query our "current" scheduling class.
6035 + // This will normally be IA, TS or, rarely, FX or RT.
6036 + memset(&ParmInfo, 0, sizeof(ParmInfo));
6037 + ParmInfo.pc_cid = PC_CLNULL;
6038 + rslt = priocntl(P_PID, P_MYID, PC_GETPARMS, (caddr_t)&ParmInfo);
6039 + if (rslt < 0) return errno;
6040 + myClass = ParmInfo.pc_cid;
6042 + // We now know our scheduling classId, get specific information
6043 + // about the class.
6044 + ClassInfo.pc_cid = myClass;
6045 + ClassInfo.pc_clname[0] = 0;
6046 + rslt = priocntl((idtype)0, 0, PC_GETCLINFO, (caddr_t)&ClassInfo);
6047 + if (rslt < 0) return errno;
6049 + memset(&ParmInfo, 0, sizeof(pcparms_t));
6050 + ParmInfo.pc_cid = PC_CLNULL;
6051 + rslt = priocntl(P_PID, P_MYID, PC_GETPARMS, (caddr_t)&ParmInfo);
6052 + if (rslt < 0) return errno;
6054 + if (ParmInfo.pc_cid == rtLimits.schedPolicy) {
6055 + myMin = rtLimits.minPrio;
6056 + myMax = rtLimits.maxPrio;
6057 + } else if (ParmInfo.pc_cid == iaLimits.schedPolicy) {
6058 + iaparms_t *iaInfo = (iaparms_t*)ParmInfo.pc_clparms;
6059 + myMin = iaLimits.minPrio;
6060 + myMax = iaLimits.maxPrio;
6061 + myMax = MIN2(myMax, (int)iaInfo->ia_uprilim); // clamp - restrict
6062 + } else if (ParmInfo.pc_cid == tsLimits.schedPolicy) {
6063 + tsparms_t *tsInfo = (tsparms_t*)ParmInfo.pc_clparms;
6064 + myMin = tsLimits.minPrio;
6065 + myMax = tsLimits.maxPrio;
6066 + myMax = MIN2(myMax, (int)tsInfo->ts_uprilim); // clamp - restrict
6067 + } else if (ParmInfo.pc_cid == fxLimits.schedPolicy) {
6068 + fxparms_t *fxInfo = (fxparms_t*)ParmInfo.pc_clparms;
6069 + myMin = fxLimits.minPrio;
6070 + myMax = fxLimits.maxPrio;
6071 + myMax = MIN2(myMax, (int)fxInfo->fx_uprilim); // clamp - restrict
6072 + } else {
6073 + return EINVAL; // no clue, punt
6076 + priocntl_enable = true; // Enable changing priorities
6077 + return 0;
6080 +#define IAPRI(x) ((iaparms_t *)((x).pc_clparms))
6081 +#define RTPRI(x) ((rtparms_t *)((x).pc_clparms))
6082 +#define TSPRI(x) ((tsparms_t *)((x).pc_clparms))
6083 +#define FXPRI(x) ((fxparms_t *)((x).pc_clparms))
6086 +// scale_to_lwp_priority
6088 +// Convert from the libthread "thr_setprio" scale to our current
6089 +// lwp scheduling class scale.
6091 +static int scale_to_lwp_priority(int rMin, int rMax, int x) {
6092 + int v;
6094 + if (x == 127) return rMax; // avoid round-down
6095 + v = (((x*(rMax-rMin)))/128)+rMin;
6096 + return v;
6100 +// set_lwp_class_and_priority
6101 +int set_lwp_class_and_priority(int ThreadID, int lwpid,
6102 + int newPrio, int new_class, bool scale) {
6103 + int rslt;
6104 + int Actual, Expected, prv;
6105 + pcparms_t ParmInfo; // for GET-SET
6106 +#ifdef ASSERT
6107 + pcparms_t ReadBack; // for readback
6108 +#endif
6110 + // Set priority via PC_GETPARMS, update, PC_SETPARMS
6111 + // Query current values.
6112 + // TODO: accelerate this by eliminating the PC_GETPARMS call.
6113 + // Cache "pcparms_t" in global ParmCache.
6114 + // TODO: elide set-to-same-value
6116 + // If something went wrong on init, don't change priorities.
6117 + if (!priocntl_enable) {
6118 + return EINVAL;
6121 + // If lwp hasn't started yet, just return
6122 + // the _start routine will call us again.
6123 + if (lwpid <= 0) {
6124 + return 0;
6127 + memset(&ParmInfo, 0, sizeof(pcparms_t));
6128 + ParmInfo.pc_cid = PC_CLNULL;
6129 + rslt = priocntl(P_LWPID, lwpid, PC_GETPARMS, (caddr_t)&ParmInfo);
6130 + if (rslt < 0) return errno;
6132 + int cur_class = ParmInfo.pc_cid;
6133 + ParmInfo.pc_cid = (id_t)new_class;
6135 + if (new_class == rtLimits.schedPolicy) {
6136 + rtparms_t *rtInfo = (rtparms_t*)ParmInfo.pc_clparms;
6137 + rtInfo->rt_pri = scale ? scale_to_lwp_priority(rtLimits.minPrio,
6138 + rtLimits.maxPrio, newPrio)
6139 + : newPrio;
6140 + rtInfo->rt_tqsecs = RT_NOCHANGE;
6141 + rtInfo->rt_tqnsecs = RT_NOCHANGE;
6142 + } else if (new_class == iaLimits.schedPolicy) {
6143 + iaparms_t* iaInfo = (iaparms_t*)ParmInfo.pc_clparms;
6144 + int maxClamped = MIN2(iaLimits.maxPrio,
6145 + cur_class == new_class
6146 + ? (int)iaInfo->ia_uprilim : iaLimits.maxPrio);
6147 + iaInfo->ia_upri = scale ? scale_to_lwp_priority(iaLimits.minPrio,
6148 + maxClamped, newPrio)
6149 + : newPrio;
6150 + iaInfo->ia_uprilim = cur_class == new_class
6151 + ? IA_NOCHANGE : (pri_t)iaLimits.maxPrio;
6152 + iaInfo->ia_mode = IA_NOCHANGE;
6153 + } else if (new_class == tsLimits.schedPolicy) {
6154 + tsparms_t* tsInfo = (tsparms_t*)ParmInfo.pc_clparms;
6155 + int maxClamped = MIN2(tsLimits.maxPrio,
6156 + cur_class == new_class
6157 + ? (int)tsInfo->ts_uprilim : tsLimits.maxPrio);
6158 + tsInfo->ts_upri = scale ? scale_to_lwp_priority(tsLimits.minPrio,
6159 + maxClamped, newPrio)
6160 + : newPrio;
6161 + tsInfo->ts_uprilim = cur_class == new_class
6162 + ? TS_NOCHANGE : (pri_t)tsLimits.maxPrio;
6163 + } else if (new_class == fxLimits.schedPolicy) {
6164 + fxparms_t* fxInfo = (fxparms_t*)ParmInfo.pc_clparms;
6165 + int maxClamped = MIN2(fxLimits.maxPrio,
6166 + cur_class == new_class
6167 + ? (int)fxInfo->fx_uprilim : fxLimits.maxPrio);
6168 + fxInfo->fx_upri = scale ? scale_to_lwp_priority(fxLimits.minPrio,
6169 + maxClamped, newPrio)
6170 + : newPrio;
6171 + fxInfo->fx_uprilim = cur_class == new_class
6172 + ? FX_NOCHANGE : (pri_t)fxLimits.maxPrio;
6173 + fxInfo->fx_tqsecs = FX_NOCHANGE;
6174 + fxInfo->fx_tqnsecs = FX_NOCHANGE;
6175 + } else {
6176 + return EINVAL; // no clue, punt
6179 + rslt = priocntl(P_LWPID, lwpid, PC_SETPARMS, (caddr_t)&ParmInfo);
6180 + if (rslt < 0) return errno;
6182 +#ifdef ASSERT
6183 + // Sanity check: read back what we just attempted to set.
6184 + // In theory it could have changed in the interim ...
6185 + //
6186 + // The priocntl system call is tricky.
6187 + // Sometimes it'll validate the priority value argument and
6188 + // return EINVAL if unhappy. At other times it fails silently.
6189 + // Readbacks are prudent.
6191 + if (!ReadBackValidate) return 0;
6193 + memset(&ReadBack, 0, sizeof(pcparms_t));
6194 + ReadBack.pc_cid = PC_CLNULL;
6195 + rslt = priocntl(P_LWPID, lwpid, PC_GETPARMS, (caddr_t)&ReadBack);
6196 + assert(rslt >= 0, "priocntl failed");
6197 + Actual = Expected = 0xBAD;
6198 + assert(ParmInfo.pc_cid == ReadBack.pc_cid, "cid's don't match");
6199 + if (ParmInfo.pc_cid == rtLimits.schedPolicy) {
6200 + Actual = RTPRI(ReadBack)->rt_pri;
6201 + Expected = RTPRI(ParmInfo)->rt_pri;
6202 + } else if (ParmInfo.pc_cid == iaLimits.schedPolicy) {
6203 + Actual = IAPRI(ReadBack)->ia_upri;
6204 + Expected = IAPRI(ParmInfo)->ia_upri;
6205 + } else if (ParmInfo.pc_cid == tsLimits.schedPolicy) {
6206 + Actual = TSPRI(ReadBack)->ts_upri;
6207 + Expected = TSPRI(ParmInfo)->ts_upri;
6208 + } else if (ParmInfo.pc_cid == fxLimits.schedPolicy) {
6209 + Actual = FXPRI(ReadBack)->fx_upri;
6210 + Expected = FXPRI(ParmInfo)->fx_upri;
6212 +#endif
6214 + return 0;
6217 +// Solaris only gives access to 128 real priorities at a time,
6218 +// so we expand Java's ten to fill this range. This would be better
6219 +// if we dynamically adjusted relative priorities.
6221 +// The ThreadPriorityPolicy option allows us to select 2 different
6222 +// priority scales.
6224 +// ThreadPriorityPolicy=0
6225 +// Since the Solaris' default priority is MaximumPriority, we do not
6226 +// set a priority lower than Max unless a priority lower than
6227 +// NormPriority is requested.
6229 +// ThreadPriorityPolicy=1
6230 +// This mode causes the priority table to get filled with
6231 +// linear values. NormPriority get's mapped to 50% of the
6232 +// Maximum priority an so on. This will cause VM threads
6233 +// to get unfair treatment against other Solaris processes
6234 +// which do not explicitly alter their thread priorities.
6236 +int os::java_to_os_priority[CriticalPriority + 1] = {
6237 + -99999, // 0 Entry should never be used
6239 + 0, // 1 MinPriority
6240 + 32, // 2
6241 + 64, // 3
6243 + 96, // 4
6244 + 127, // 5 NormPriority
6245 + 127, // 6
6247 + 127, // 7
6248 + 127, // 8
6249 + 127, // 9 NearMaxPriority
6251 + 127, // 10 MaxPriority
6253 + -criticalPrio // 11 CriticalPriority
6256 +OSReturn os::set_native_priority(Thread* thread, int newpri) {
6257 + OSThread* osthread = thread->osthread();
6259 + // Save requested priority in case the thread hasn't been started
6260 + osthread->set_native_priority(newpri);
6262 + // Check for critical priority request
6263 + bool fxcritical = false;
6264 + if (newpri == -criticalPrio) {
6265 + fxcritical = true;
6266 + newpri = criticalPrio;
6269 + assert(newpri >= MinimumPriority && newpri <= MaximumPriority, "bad priority mapping");
6270 + if (!UseThreadPriorities) return OS_OK;
6272 + int status = 0;
6274 + if (!fxcritical) {
6275 + // Use thr_setprio only if we have a priority that thr_setprio understands
6276 + status = thr_setprio(thread->osthread()->thread_id(), newpri);
6279 + int lwp_status =
6280 + set_lwp_class_and_priority(osthread->thread_id(),
6281 + osthread->lwp_id(),
6282 + newpri,
6283 + fxcritical ? fxLimits.schedPolicy : myClass,
6284 + !fxcritical);
6285 + if (lwp_status != 0 && fxcritical) {
6286 + // Try again, this time without changing the scheduling class
6287 + newpri = java_MaxPriority_to_os_priority;
6288 + lwp_status = set_lwp_class_and_priority(osthread->thread_id(),
6289 + osthread->lwp_id(),
6290 + newpri, myClass, false);
6292 + status |= lwp_status;
6293 + return (status == 0) ? OS_OK : OS_ERR;
6297 +OSReturn os::get_native_priority(const Thread* const thread,
6298 + int *priority_ptr) {
6299 + int p;
6300 + if (!UseThreadPriorities) {
6301 + *priority_ptr = NormalPriority;
6302 + return OS_OK;
6304 + int status = thr_getprio(thread->osthread()->thread_id(), &p);
6305 + if (status != 0) {
6306 + return OS_ERR;
6308 + *priority_ptr = p;
6309 + return OS_OK;
6312 +////////////////////////////////////////////////////////////////////////////////
6314 +// This does not do anything on Solaris. This is basically a hook for being
6315 +// able to use structured exception handling (thread-local exception filters) on, e.g., Win32.
6316 +void os::os_exception_wrapper(java_call_t f, JavaValue* value,
6317 + const methodHandle& method, JavaCallArguments* args,
6318 + JavaThread* thread) {
6319 + f(value, method, args, thread);
6322 +void report_error(const char* file_name, int line_no, const char* title,
6323 + const char* format, ...);
6325 +// (Static) wrappers for the liblgrp API
6326 +os::Solaris::lgrp_home_func_t os::Solaris::_lgrp_home;
6327 +os::Solaris::lgrp_init_func_t os::Solaris::_lgrp_init;
6328 +os::Solaris::lgrp_fini_func_t os::Solaris::_lgrp_fini;
6329 +os::Solaris::lgrp_root_func_t os::Solaris::_lgrp_root;
6330 +os::Solaris::lgrp_children_func_t os::Solaris::_lgrp_children;
6331 +os::Solaris::lgrp_resources_func_t os::Solaris::_lgrp_resources;
6332 +os::Solaris::lgrp_nlgrps_func_t os::Solaris::_lgrp_nlgrps;
6333 +os::Solaris::lgrp_cookie_stale_func_t os::Solaris::_lgrp_cookie_stale;
6334 +os::Solaris::lgrp_cookie_t os::Solaris::_lgrp_cookie = 0;
6336 +static address resolve_symbol_lazy(const char* name) {
6337 + address addr = (address) dlsym(RTLD_DEFAULT, name);
6338 + if (addr == NULL) {
6339 + // RTLD_DEFAULT was not defined on some early versions of 2.5.1
6340 + addr = (address) dlsym(RTLD_NEXT, name);
6342 + return addr;
6345 +static address resolve_symbol(const char* name) {
6346 + address addr = resolve_symbol_lazy(name);
6347 + if (addr == NULL) {
6348 + fatal("resolve_symbol failed (%s)", dlerror());
6350 + return addr;
6353 +void os::Solaris::libthread_init() {
6354 + address func = (address)dlsym(RTLD_DEFAULT, "_thr_suspend_allmutators");
6356 + lwp_priocntl_init();
6358 + // RTLD_DEFAULT was not defined on some early versions of 5.5.1
6359 + if (func == NULL) {
6360 + func = (address) dlsym(RTLD_NEXT, "_thr_suspend_allmutators");
6361 + // Guarantee that this VM is running on an new enough OS (5.6 or
6362 + // later) that it will have a new enough libthread.so.
6363 + guarantee(func != NULL, "libthread.so is too old.");
6366 + int size;
6367 + void (*handler_info_func)(address *, int *);
6368 + handler_info_func = CAST_TO_FN_PTR(void (*)(address *, int *), resolve_symbol("thr_sighndlrinfo"));
6369 + handler_info_func(&handler_start, &size);
6370 + handler_end = handler_start + size;
6374 +bool os::Solaris::_synchronization_initialized;
6376 +void os::Solaris::synchronization_init() {
6377 + _synchronization_initialized = true;
6380 +bool os::Solaris::liblgrp_init() {
6381 + void *handle = dlopen("liblgrp.so.1", RTLD_LAZY);
6382 + if (handle != NULL) {
6383 + os::Solaris::set_lgrp_home(CAST_TO_FN_PTR(lgrp_home_func_t, dlsym(handle, "lgrp_home")));
6384 + os::Solaris::set_lgrp_init(CAST_TO_FN_PTR(lgrp_init_func_t, dlsym(handle, "lgrp_init")));
6385 + os::Solaris::set_lgrp_fini(CAST_TO_FN_PTR(lgrp_fini_func_t, dlsym(handle, "lgrp_fini")));
6386 + os::Solaris::set_lgrp_root(CAST_TO_FN_PTR(lgrp_root_func_t, dlsym(handle, "lgrp_root")));
6387 + os::Solaris::set_lgrp_children(CAST_TO_FN_PTR(lgrp_children_func_t, dlsym(handle, "lgrp_children")));
6388 + os::Solaris::set_lgrp_resources(CAST_TO_FN_PTR(lgrp_resources_func_t, dlsym(handle, "lgrp_resources")));
6389 + os::Solaris::set_lgrp_nlgrps(CAST_TO_FN_PTR(lgrp_nlgrps_func_t, dlsym(handle, "lgrp_nlgrps")));
6390 + os::Solaris::set_lgrp_cookie_stale(CAST_TO_FN_PTR(lgrp_cookie_stale_func_t,
6391 + dlsym(handle, "lgrp_cookie_stale")));
6393 + lgrp_cookie_t c = lgrp_init(LGRP_VIEW_CALLER);
6394 + set_lgrp_cookie(c);
6395 + return true;
6397 + return false;
6400 +// int pset_getloadavg(psetid_t pset, double loadavg[], int nelem);
6401 +typedef long (*pset_getloadavg_type)(psetid_t pset, double loadavg[], int nelem);
6402 +static pset_getloadavg_type pset_getloadavg_ptr = NULL;
6404 +void init_pset_getloadavg_ptr(void) {
6405 + pset_getloadavg_ptr =
6406 + (pset_getloadavg_type)dlsym(RTLD_DEFAULT, "pset_getloadavg");
6407 + if (pset_getloadavg_ptr == NULL) {
6408 + log_warning(os)("pset_getloadavg function not found");
6412 +int os::Solaris::_dev_zero_fd = -1;
6414 +// this is called _before_ the global arguments have been parsed
6415 +void os::init(void) {
6416 + _initial_pid = getpid();
6418 + max_hrtime = first_hrtime = gethrtime();
6420 + init_random(1234567);
6422 + int page_size = sysconf(_SC_PAGESIZE);
6423 + OSInfo::set_vm_page_size(page_size);
6424 + OSInfo::set_vm_allocation_granularity(page_size);
6425 + if (os::vm_page_size() <= 0) {
6426 + fatal("os_solaris.cpp: os::init: sysconf failed (%s)", os::strerror(errno));
6428 + _page_sizes.add(os::vm_page_size());
6430 + Solaris::initialize_system_info();
6432 + int fd = ::open("/dev/zero", O_RDWR);
6433 + if (fd < 0) {
6434 + fatal("os::init: cannot open /dev/zero (%s)", os::strerror(errno));
6435 + } else {
6436 + Solaris::set_dev_zero_fd(fd);
6438 + // Close on exec, child won't inherit.
6439 + fcntl(fd, F_SETFD, FD_CLOEXEC);
6442 + clock_tics_per_sec = CLK_TCK;
6444 + // main_thread points to the thread that created/loaded the JVM.
6445 + main_thread = thr_self();
6447 + // dynamic lookup of functions that may not be available in our lowest
6448 + // supported Solaris release
6449 + void * handle = dlopen("libc.so.1", RTLD_LAZY);
6450 + if (handle != NULL) {
6451 + Solaris::_pthread_setname_np = // from 11.3
6452 + (Solaris::pthread_setname_np_func_t)dlsym(handle, "pthread_setname_np");
6455 + // Shared Posix initialization
6456 + os::Posix::init();
6459 +// To install functions for atexit system call
6460 +extern "C" {
6461 + static void perfMemory_exit_helper() {
6462 + perfMemory_exit();
6466 +// this is called _after_ the global arguments have been parsed
6467 +jint os::init_2(void) {
6468 + Solaris::libthread_init();
6470 + if (UseNUMA) {
6471 + if (!Solaris::liblgrp_init()) {
6472 + FLAG_SET_ERGO(UseNUMA, false);
6473 + } else {
6474 + size_t lgrp_limit = os::numa_get_groups_num();
6475 + uint *lgrp_ids = NEW_C_HEAP_ARRAY(uint, lgrp_limit, mtInternal);
6476 + size_t lgrp_num = os::numa_get_leaf_groups(lgrp_ids, lgrp_limit);
6477 + FREE_C_HEAP_ARRAY(uint, lgrp_ids);
6478 + if (lgrp_num < 2) {
6479 + // There's only one locality group, disable NUMA
6480 + UseNUMA = false;
6485 + // When NUMA requested, not-NUMA-aware allocations default to interleaving.
6486 + if (UseNUMA && !UseNUMAInterleaving) {
6487 + FLAG_SET_ERGO_IF_DEFAULT(UseNUMAInterleaving, true);
6490 + if (PosixSignals::init() == JNI_ERR) {
6491 + return JNI_ERR;
6494 + // initialize synchronization primitives
6495 + Solaris::synchronization_init();
6496 + DEBUG_ONLY(os::set_mutex_init_done();)
6498 + if (MaxFDLimit) {
6499 + // set the number of file descriptors to max. print out error
6500 + // if getrlimit/setrlimit fails but continue regardless.
6501 + struct rlimit nbr_files;
6502 + int status = getrlimit(RLIMIT_NOFILE, &nbr_files);
6503 + if (status != 0) {
6504 + log_info(os)("os::init_2 getrlimit failed: %s", os::strerror(errno));
6505 + } else {
6506 + nbr_files.rlim_cur = nbr_files.rlim_max;
6507 + status = setrlimit(RLIMIT_NOFILE, &nbr_files);
6508 + if (status != 0) {
6509 + log_info(os)("os::init_2 setrlimit failed: %s", os::strerror(errno));
6514 + // Calculate theoretical max. size of Threads to guard gainst
6515 + // artifical out-of-memory situations, where all available address-
6516 + // space has been reserved by thread stacks. Default stack size is 1Mb.
6517 + size_t pre_thread_stack_size = (JavaThread::stack_size_at_create()) ?
6518 + JavaThread::stack_size_at_create() : (1*K*K);
6519 + assert(pre_thread_stack_size != 0, "Must have a stack");
6520 + // Solaris has a maximum of 4Gb of user programs. Calculate the thread limit when
6521 + // we should start doing Virtual Memory banging. Currently when the threads will
6522 + // have used all but 200Mb of space.
6523 + size_t max_address_space = ((unsigned int)4 * K * K * K) - (200 * K * K);
6524 + Solaris::_os_thread_limit = max_address_space / pre_thread_stack_size;
6526 + // at-exit methods are called in the reverse order of their registration.
6527 + // In Solaris 7 and earlier, atexit functions are called on return from
6528 + // main or as a result of a call to exit(3C). There can be only 32 of
6529 + // these functions registered and atexit() does not set errno. In Solaris
6530 + // 8 and later, there is no limit to the number of functions registered
6531 + // and atexit() sets errno. In addition, in Solaris 8 and later, atexit
6532 + // functions are called upon dlclose(3DL) in addition to return from main
6533 + // and exit(3C).
6535 + if (PerfAllowAtExitRegistration) {
6536 + // only register atexit functions if PerfAllowAtExitRegistration is set.
6537 + // atexit functions can be delayed until process exit time, which
6538 + // can be problematic for embedded VM situations. Embedded VMs should
6539 + // call DestroyJavaVM() to assure that VM resources are released.
6541 + // note: perfMemory_exit_helper atexit function may be removed in
6542 + // the future if the appropriate cleanup code can be added to the
6543 + // VM_Exit VMOperation's doit method.
6544 + if (atexit(perfMemory_exit_helper) != 0) {
6545 + warning("os::init2 atexit(perfMemory_exit_helper) failed");
6549 + // Init pset_loadavg function pointer
6550 + init_pset_getloadavg_ptr();
6552 + // Shared Posix initialization
6553 + os::Posix::init_2();
6555 + return JNI_OK;
6558 +// This code originates from JDK's sysOpen and open64_w
6559 +// from src/solaris/hpi/src/system_md.c
6561 +int os::open(const char *path, int oflag, int mode) {
6562 + if (strlen(path) > MAX_PATH - 1) {
6563 + errno = ENAMETOOLONG;
6564 + return -1;
6566 + int fd;
6568 + fd = ::open64(path, oflag, mode);
6569 + if (fd == -1) return -1;
6571 + // If the open succeeded, the file might still be a directory
6573 + struct stat64 buf64;
6574 + int ret = ::fstat64(fd, &buf64);
6575 + int st_mode = buf64.st_mode;
6577 + if (ret != -1) {
6578 + if ((st_mode & S_IFMT) == S_IFDIR) {
6579 + errno = EISDIR;
6580 + ::close(fd);
6581 + return -1;
6583 + } else {
6584 + ::close(fd);
6585 + return -1;
6589 + // All file descriptors that are opened in the JVM and not
6590 + // specifically destined for a subprocess should have the
6591 + // close-on-exec flag set. If we don't set it, then careless 3rd
6592 + // party native code might fork and exec without closing all
6593 + // appropriate file descriptors (e.g. as we do in closeDescriptors in
6594 + // UNIXProcess.c), and this in turn might:
6595 + //
6596 + // - cause end-of-file to fail to be detected on some file
6597 + // descriptors, resulting in mysterious hangs, or
6598 + //
6599 + // - might cause an fopen in the subprocess to fail on a system
6600 + // suffering from bug 1085341.
6601 + //
6602 + // (Yes, the default setting of the close-on-exec flag is a Unix
6603 + // design flaw)
6604 + //
6605 + // See:
6606 + // 1085341: 32-bit stdio routines should support file descriptors >255
6607 + // 4843136: (process) pipe file descriptor from Runtime.exec not being closed
6608 + // 6339493: (process) Runtime.exec does not close all file descriptors on Solaris 9
6609 + //
6610 +#ifdef FD_CLOEXEC
6612 + int flags = ::fcntl(fd, F_GETFD);
6613 + if (flags != -1) {
6614 + ::fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
6617 +#endif
6619 + return fd;
6622 +// create binary file, rewriting existing file if required
6623 +int os::create_binary_file(const char* path, bool rewrite_existing) {
6624 + int oflags = O_WRONLY | O_CREAT;
6625 + if (!rewrite_existing) {
6626 + oflags |= O_EXCL;
6628 + return ::open64(path, oflags, S_IREAD | S_IWRITE);
6631 +// return current position of file pointer
6632 +jlong os::current_file_offset(int fd) {
6633 + return (jlong)::lseek64(fd, (off64_t)0, SEEK_CUR);
6636 +// move file pointer to the specified offset
6637 +jlong os::seek_to_file_offset(int fd, jlong offset) {
6638 + return (jlong)::lseek64(fd, (off64_t)offset, SEEK_SET);
6641 +// Map a block of memory.
6642 +char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset,
6643 + char *addr, size_t bytes, bool read_only,
6644 + bool allow_exec) {
6645 + int prot;
6646 + int flags;
6648 + if (read_only) {
6649 + prot = PROT_READ;
6650 + flags = MAP_SHARED;
6651 + } else {
6652 + prot = PROT_READ | PROT_WRITE;
6653 + flags = MAP_PRIVATE;
6656 + if (allow_exec) {
6657 + prot |= PROT_EXEC;
6660 + if (addr != NULL) {
6661 + flags |= MAP_FIXED;
6664 + char* mapped_address = (char*)mmap(addr, (size_t)bytes, prot, flags,
6665 + fd, file_offset);
6666 + if (mapped_address == MAP_FAILED) {
6667 + return NULL;
6669 + return mapped_address;
6673 +// Remap a block of memory.
6674 +char* os::pd_remap_memory(int fd, const char* file_name, size_t file_offset,
6675 + char *addr, size_t bytes, bool read_only,
6676 + bool allow_exec) {
6677 + // same as map_memory() on this OS
6678 + return os::map_memory(fd, file_name, file_offset, addr, bytes, read_only,
6679 + allow_exec);
6683 +// Unmap a block of memory.
6684 +bool os::pd_unmap_memory(char* addr, size_t bytes) {
6685 + return munmap(addr, bytes) == 0;
6688 +const intptr_t thr_time_off = (intptr_t)(&((prusage_t *)(NULL))->pr_utime);
6689 +const intptr_t thr_time_size = (intptr_t)(&((prusage_t *)(NULL))->pr_ttime) -
6690 + (intptr_t)(&((prusage_t *)(NULL))->pr_utime);
6693 +// JVMTI & JVM monitoring and management support
6694 +// The thread_cpu_time() and current_thread_cpu_time() are only
6695 +// supported if is_thread_cpu_time_supported() returns true.
6696 +// They are not supported on Solaris T1.
6698 +// current_thread_cpu_time(bool) and thread_cpu_time(Thread*, bool)
6699 +// are used by JVM M&M and JVMTI to get user+sys or user CPU time
6700 +// of a thread.
6702 +// current_thread_cpu_time() and thread_cpu_time(Thread *)
6703 +// returns the fast estimate available on the platform.
6705 +// hrtime_t gethrvtime() return value includes
6706 +// user time but does not include system time
6707 +jlong os::current_thread_cpu_time() {
6708 + return (jlong) gethrvtime();
6711 +jlong os::thread_cpu_time(Thread *thread) {
6712 + // return user level CPU time only to be consistent with
6713 + // what current_thread_cpu_time returns.
6714 + // thread_cpu_time_info() must be changed if this changes
6715 + return os::thread_cpu_time(thread, false /* user time only */);
6718 +jlong os::current_thread_cpu_time(bool user_sys_cpu_time) {
6719 + if (user_sys_cpu_time) {
6720 + return os::thread_cpu_time(Thread::current(), user_sys_cpu_time);
6721 + } else {
6722 + return os::current_thread_cpu_time();
6726 +jlong os::thread_cpu_time(Thread *thread, bool user_sys_cpu_time) {
6727 + char proc_name[64];
6728 + int count;
6729 + prusage_t prusage;
6730 + jlong lwp_time;
6731 + int fd;
6733 + sprintf(proc_name, "/proc/%d/lwp/%d/lwpusage",
6734 + getpid(),
6735 + thread->osthread()->lwp_id());
6736 + fd = ::open(proc_name, O_RDONLY);
6737 + if (fd == -1) return -1;
6739 + do {
6740 + count = ::pread(fd,
6741 + (void *)&prusage.pr_utime,
6742 + thr_time_size,
6743 + thr_time_off);
6744 + } while (count < 0 && errno == EINTR);
6745 + ::close(fd);
6746 + if (count < 0) return -1;
6748 + if (user_sys_cpu_time) {
6749 + // user + system CPU time
6750 + lwp_time = (((jlong)prusage.pr_stime.tv_sec +
6751 + (jlong)prusage.pr_utime.tv_sec) * (jlong)1000000000) +
6752 + (jlong)prusage.pr_stime.tv_nsec +
6753 + (jlong)prusage.pr_utime.tv_nsec;
6754 + } else {
6755 + // user level CPU time only
6756 + lwp_time = ((jlong)prusage.pr_utime.tv_sec * (jlong)1000000000) +
6757 + (jlong)prusage.pr_utime.tv_nsec;
6760 + return (lwp_time);
6763 +void os::current_thread_cpu_time_info(jvmtiTimerInfo *info_ptr) {
6764 + info_ptr->max_value = ALL_64_BITS; // will not wrap in less than 64 bits
6765 + info_ptr->may_skip_backward = false; // elapsed time not wall time
6766 + info_ptr->may_skip_forward = false; // elapsed time not wall time
6767 + info_ptr->kind = JVMTI_TIMER_USER_CPU; // only user time is returned
6770 +void os::thread_cpu_time_info(jvmtiTimerInfo *info_ptr) {
6771 + info_ptr->max_value = ALL_64_BITS; // will not wrap in less than 64 bits
6772 + info_ptr->may_skip_backward = false; // elapsed time not wall time
6773 + info_ptr->may_skip_forward = false; // elapsed time not wall time
6774 + info_ptr->kind = JVMTI_TIMER_USER_CPU; // only user time is returned
6777 +bool os::is_thread_cpu_time_supported() {
6778 + return true;
6781 +// System loadavg support. Returns -1 if load average cannot be obtained.
6782 +// Return the load average for our processor set if the primitive exists
6783 +// (Solaris 9 and later). Otherwise just return system wide loadavg.
6784 +int os::loadavg(double loadavg[], int nelem) {
6785 + if (pset_getloadavg_ptr != NULL) {
6786 + return (*pset_getloadavg_ptr)(PS_MYID, loadavg, nelem);
6787 + } else {
6788 + return ::getloadavg(loadavg, nelem);
6792 +//---------------------------------------------------------------------------------
6794 +bool os::find(address addr, outputStream* st) {
6795 + Dl_info dlinfo;
6796 + memset(&dlinfo, 0, sizeof(dlinfo));
6797 + if (dladdr(addr, &dlinfo) != 0) {
6798 + st->print(PTR_FORMAT ": ", p2i(addr));
6799 + if (dlinfo.dli_sname != NULL && dlinfo.dli_saddr != NULL) {
6800 + st->print("%s+" PTR_FORMAT, dlinfo.dli_sname,
6801 + p2i(addr) - p2i(dlinfo.dli_saddr));
6802 + } else if (dlinfo.dli_fbase != NULL) {
6803 + st->print("<offset " PTR_FORMAT ">", p2i(addr) - p2i(dlinfo.dli_fbase));
6804 + } else {
6805 + st->print("<absolute address>");
6807 + if (dlinfo.dli_fname != NULL) {
6808 + st->print(" in %s", dlinfo.dli_fname);
6810 + if (dlinfo.dli_fbase != NULL) {
6811 + st->print(" at " PTR_FORMAT, p2i(dlinfo.dli_fbase));
6813 + st->cr();
6815 + if (Verbose) {
6816 + // decode some bytes around the PC
6817 + address begin = clamp_address_in_page(addr-40, addr, os::vm_page_size());
6818 + address end = clamp_address_in_page(addr+40, addr, os::vm_page_size());
6819 + address lowest = (address) dlinfo.dli_sname;
6820 + if (!lowest) lowest = (address) dlinfo.dli_fbase;
6821 + if (begin < lowest) begin = lowest;
6822 + Dl_info dlinfo2;
6823 + if (dladdr(end, &dlinfo2) != 0 && dlinfo2.dli_saddr != dlinfo.dli_saddr
6824 + && end > dlinfo2.dli_saddr && dlinfo2.dli_saddr > begin) {
6825 + end = (address) dlinfo2.dli_saddr;
6827 + Disassembler::decode(begin, end, st);
6829 + return true;
6831 + return false;
6834 +// Following function has been added to support HotSparc's libjvm.so running
6835 +// under Solaris production JDK 1.2.2 / 1.3.0. These came from
6836 +// src/solaris/hpi/native_threads in the EVM codebase.
6838 +// NOTE: This is no longer needed in the 1.3.1 and 1.4 production release
6839 +// libraries and should thus be removed. We will leave it behind for a while
6840 +// until we no longer want to able to run on top of 1.3.0 Solaris production
6841 +// JDK. See 4341971.
6843 +#define STACK_SLACK 0x800
6845 +extern "C" {
6846 + intptr_t sysThreadAvailableStackWithSlack() {
6847 + stack_t st;
6848 + intptr_t retval, stack_top;
6849 + retval = thr_stksegment(&st);
6850 + assert(retval == 0, "incorrect return value from thr_stksegment");
6851 + assert((address)&st < (address)st.ss_sp, "Invalid stack base returned");
6852 + assert((address)&st > (address)st.ss_sp-st.ss_size, "Invalid stack size returned");
6853 + stack_top=(intptr_t)st.ss_sp-st.ss_size;
6854 + return ((intptr_t)&stack_top - stack_top - STACK_SLACK);
6858 +// ObjectMonitor park-unpark infrastructure ...
6860 +// We implement Solaris and Linux PlatformEvents with the
6861 +// obvious condvar-mutex-flag triple.
6862 +// Another alternative that works quite well is pipes:
6863 +// Each PlatformEvent consists of a pipe-pair.
6864 +// The thread associated with the PlatformEvent
6865 +// calls park(), which reads from the input end of the pipe.
6866 +// Unpark() writes into the other end of the pipe.
6867 +// The write-side of the pipe must be set NDELAY.
6868 +// Unfortunately pipes consume a large # of handles.
6869 +// Native solaris lwp_park() and lwp_unpark() work nicely, too.
6870 +// Using pipes for the 1st few threads might be workable, however.
6872 +// park() is permitted to return spuriously.
6873 +// Callers of park() should wrap the call to park() in
6874 +// an appropriate loop. A litmus test for the correct
6875 +// usage of park is the following: if park() were modified
6876 +// to immediately return 0 your code should still work,
6877 +// albeit degenerating to a spin loop.
6879 +// In a sense, park()-unpark() just provides more polite spinning
6880 +// and polling with the key difference over naive spinning being
6881 +// that a parked thread needs to be explicitly unparked() in order
6882 +// to wake up and to poll the underlying condition.
6884 +// Assumption:
6885 +// Only one parker can exist on an event, which is why we allocate
6886 +// them per-thread. Multiple unparkers can coexist.
6888 +// _event transitions in park()
6889 +// -1 => -1 : illegal
6890 +// 1 => 0 : pass - return immediately
6891 +// 0 => -1 : block; then set _event to 0 before returning
6893 +// _event transitions in unpark()
6894 +// 0 => 1 : just return
6895 +// 1 => 1 : just return
6896 +// -1 => either 0 or 1; must signal target thread
6897 +// That is, we can safely transition _event from -1 to either
6898 +// 0 or 1.
6900 +// _event serves as a restricted-range semaphore.
6901 +// -1 : thread is blocked, i.e. there is a waiter
6902 +// 0 : neutral: thread is running or ready,
6903 +// could have been signaled after a wait started
6904 +// 1 : signaled - thread is running or ready
6906 +// Another possible encoding of _event would be with
6907 +// explicit "PARKED" == 01b and "SIGNALED" == 10b bits.
6909 +// TODO-FIXME: add DTRACE probes for:
6910 +// 1. Tx parks
6911 +// 2. Ty unparks Tx
6912 +// 3. Tx resumes from park
6914 +// JSR166
6915 +// -------------------------------------------------------
6917 +// The solaris and linux implementations of park/unpark are fairly
6918 +// conservative for now, but can be improved. They currently use a
6919 +// mutex/condvar pair, plus _counter.
6920 +// Park decrements _counter if > 0, else does a condvar wait. Unpark
6921 +// sets count to 1 and signals condvar. Only one thread ever waits
6922 +// on the condvar. Contention seen when trying to park implies that someone
6923 +// is unparking you, so don't wait. And spurious returns are fine, so there
6924 +// is no need to track notifications.
6926 +// Get the default path to the core file
6927 +// Returns the length of the string
6928 +int os::get_core_path(char* buffer, size_t bufferSize) {
6929 + const char* p = get_current_directory(buffer, bufferSize);
6931 + if (p == NULL) {
6932 + assert(p != NULL, "failed to get current directory");
6933 + return 0;
6936 + jio_snprintf(buffer, bufferSize, "%s/core or core.%d",
6937 + p, current_process_id());
6939 + return strlen(buffer);
6942 +bool os::supports_map_sync() {
6943 + return false;
6946 +#ifndef PRODUCT
6947 +void TestReserveMemorySpecial_test() {
6948 + // No tests available for this platform
6950 +#endif
6952 +bool os::start_debugging(char *buf, int buflen) {
6953 + int len = (int)strlen(buf);
6954 + char *p = &buf[len];
6956 + jio_snprintf(p, buflen-len,
6957 + "\n\n"
6958 + "Do you want to debug the problem?\n\n"
6959 + "To debug, run 'dbx - %d'; then switch to thread " INTX_FORMAT "\n"
6960 + "Enter 'yes' to launch dbx automatically (PATH must include dbx)\n"
6961 + "Otherwise, press RETURN to abort...",
6962 + os::current_process_id(), os::current_thread_id());
6964 + bool yes = os::message_box("Unexpected Error", buf);
6966 + if (yes) {
6967 + // yes, user asked VM to launch debugger
6968 + jio_snprintf(buf, sizeof(buf), "dbx - %d", os::current_process_id());
6970 + os::fork_and_exec(buf);
6971 + yes = false;
6973 + return yes;
6976 +void os::print_memory_mappings(char* addr, size_t bytes, outputStream* st) {}
6978 +#if INCLUDE_JFR
6980 +void os::jfr_report_memory_info() {}
6982 +#endif // INCLUDE_JFR
6984 +bool os::pd_dll_unload(void* libhandle, char* ebuf, int ebuflen) {
6986 + if (ebuf && ebuflen > 0) {
6987 + ebuf[0] = '\0';
6988 + ebuf[ebuflen - 1] = '\0';
6991 + bool res = (0 == ::dlclose(libhandle));
6992 + if (!res) {
6993 + // error analysis when dlopen fails
6994 + const char* error_report = ::dlerror();
6995 + if (error_report == nullptr) {
6996 + error_report = "dlerror returned no error description";
6998 + if (ebuf != nullptr && ebuflen > 0) {
6999 + snprintf(ebuf, ebuflen - 1, "%s", error_report);
7003 + return res;
7004 +} // end: os::pd_dll_unload()
7005 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os/solaris/os_solaris.hpp jdk22u-jdk-22.0.2-ga/src/hotspot/os/solaris/os_solaris.hpp
7006 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os/solaris/os_solaris.hpp 1970-01-01 01:00:00.000000000 +0100
7007 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/os/solaris/os_solaris.hpp 2024-08-17 19:34:03.900596348 +0200
7008 @@ -0,0 +1,201 @@
7010 + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
7011 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7013 + * This code is free software; you can redistribute it and/or modify it
7014 + * under the terms of the GNU General Public License version 2 only, as
7015 + * published by the Free Software Foundation.
7017 + * This code is distributed in the hope that it will be useful, but WITHOUT
7018 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7019 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7020 + * version 2 for more details (a copy is included in the LICENSE file that
7021 + * accompanied this code).
7023 + * You should have received a copy of the GNU General Public License version
7024 + * 2 along with this work; if not, write to the Free Software Foundation,
7025 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7027 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7028 + * or visit www.oracle.com if you need additional information or have any
7029 + * questions.
7031 + */
7033 +#ifndef OS_SOLARIS_OS_SOLARIS_HPP
7034 +#define OS_SOLARIS_OS_SOLARIS_HPP
7036 +#include "runtime/os.hpp"
7038 +// Solaris_OS defines the interface to Solaris operating systems
7040 +// see thr_setprio(3T) for the basis of these numbers
7041 +#define MinimumPriority 0
7042 +#define NormalPriority 64
7043 +#define MaximumPriority 127
7045 +// FX/60 is critical thread class/priority on T4
7046 +#define FXCriticalPriority 60
7048 +class os::Solaris {
7049 + friend class os;
7051 + private:
7053 + static bool _synchronization_initialized;
7055 + typedef uintptr_t lgrp_cookie_t;
7056 + typedef id_t lgrp_id_t;
7057 + typedef int lgrp_rsrc_t;
7058 + typedef enum lgrp_view {
7059 + LGRP_VIEW_CALLER, // what's available to the caller
7060 + LGRP_VIEW_OS // what's available to operating system
7061 + } lgrp_view_t;
7063 + typedef lgrp_id_t (*lgrp_home_func_t)(idtype_t idtype, id_t id);
7064 + typedef lgrp_cookie_t (*lgrp_init_func_t)(lgrp_view_t view);
7065 + typedef int (*lgrp_fini_func_t)(lgrp_cookie_t cookie);
7066 + typedef lgrp_id_t (*lgrp_root_func_t)(lgrp_cookie_t cookie);
7067 + typedef int (*lgrp_children_func_t)(lgrp_cookie_t cookie, lgrp_id_t parent,
7068 + lgrp_id_t *lgrp_array, uint_t lgrp_array_size);
7069 + typedef int (*lgrp_resources_func_t)(lgrp_cookie_t cookie, lgrp_id_t lgrp,
7070 + lgrp_id_t *lgrp_array, uint_t lgrp_array_size,
7071 + lgrp_rsrc_t type);
7072 + typedef int (*lgrp_nlgrps_func_t)(lgrp_cookie_t cookie);
7073 + typedef int (*lgrp_cookie_stale_func_t)(lgrp_cookie_t cookie);
7075 + static lgrp_home_func_t _lgrp_home;
7076 + static lgrp_init_func_t _lgrp_init;
7077 + static lgrp_fini_func_t _lgrp_fini;
7078 + static lgrp_root_func_t _lgrp_root;
7079 + static lgrp_children_func_t _lgrp_children;
7080 + static lgrp_resources_func_t _lgrp_resources;
7081 + static lgrp_nlgrps_func_t _lgrp_nlgrps;
7082 + static lgrp_cookie_stale_func_t _lgrp_cookie_stale;
7083 + static lgrp_cookie_t _lgrp_cookie;
7085 + // Large Page Support
7086 + static bool is_valid_page_size(size_t bytes);
7087 + static size_t page_size_for_alignment(size_t alignment);
7088 + static bool setup_large_pages(caddr_t start, size_t bytes, size_t align);
7090 + typedef int (*pthread_setname_np_func_t)(pthread_t, const char*);
7091 + static pthread_setname_np_func_t _pthread_setname_np;
7093 + public:
7094 + // Large Page Support--ISM.
7095 + static bool largepage_range(char* addr, size_t size);
7097 + static address handler_start, handler_end; // start and end pc of thr_sighndlrinfo
7099 + static bool valid_ucontext(Thread* thread, const ucontext_t* valid, const ucontext_t* suspect);
7100 + static const ucontext_t* get_valid_uc_in_signal_handler(Thread* thread,
7101 + const ucontext_t* uc);
7103 + static intptr_t* ucontext_get_sp(const ucontext_t* uc);
7104 + // ucontext_get_fp() is only used by Solaris X86 (see note below)
7105 + static intptr_t* ucontext_get_fp(const ucontext_t* uc);
7107 + static bool get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr);
7109 + static void init_thread_fpu_state(void);
7111 + protected:
7112 + // Solaris-specific interface goes here
7113 + static julong available_memory();
7114 + static julong free_memory();
7115 + static julong physical_memory() { return _physical_memory; }
7116 + static julong _physical_memory;
7117 + static void initialize_system_info();
7118 + static int _dev_zero_fd;
7119 + static int get_dev_zero_fd() { return _dev_zero_fd; }
7120 + static void set_dev_zero_fd(int fd) { _dev_zero_fd = fd; }
7121 + static int commit_memory_impl(char* addr, size_t bytes, bool exec);
7122 + static int commit_memory_impl(char* addr, size_t bytes,
7123 + size_t alignment_hint, bool exec);
7124 + static char* mmap_chunk(char *addr, size_t size, int flags, int prot);
7125 + static char* anon_mmap(char* requested_addr, size_t bytes);
7126 + static bool mpss_sanity_check(bool warn, size_t * page_size);
7128 + static address current_stack_base();
7129 + static size_t current_stack_size();
7131 + // Workaround for 4352906. thr_stksegment sometimes returns
7132 + // a bad value for the primordial thread's stack base when
7133 + // it is called more than one time.
7134 + // Workaround is to cache the initial value to avoid further
7135 + // calls to thr_stksegment.
7136 + // It appears that someone (Hotspot?) is trashing the user's
7137 + // proc_t structure (note that this is a system struct).
7138 + static address _main_stack_base;
7140 + static void print_distro_info(outputStream* st);
7141 + static void print_libversion_info(outputStream* st);
7143 + public:
7144 + static void libthread_init();
7145 + static void synchronization_init();
7146 + static bool liblgrp_init();
7148 + // alignment with os_posix means we use pthreads
7149 + static int mutex_lock(pthread_mutex_t *mx) { return pthread_mutex_lock(mx); }
7150 + static int mutex_trylock(pthread_mutex_t *mx) { return pthread_mutex_trylock(mx); }
7151 + static int mutex_unlock(pthread_mutex_t *mx) { return pthread_mutex_unlock(mx); }
7152 + static int mutex_init(pthread_mutex_t *mx) { return pthread_mutex_init(mx, NULL); }
7153 + static int mutex_destroy(pthread_mutex_t *mx) { return pthread_mutex_destroy(mx); }
7155 + static int cond_timedwait(pthread_cond_t *cv, pthread_mutex_t *mx, timestruc_t *abst) { return pthread_cond_timedwait(cv, mx, abst); }
7156 + static int cond_wait(pthread_cond_t *cv, pthread_mutex_t *mx) { return pthread_cond_wait(cv, mx); }
7157 + static int cond_signal(pthread_cond_t *cv) { return pthread_cond_signal(cv); }
7158 + static int cond_broadcast(pthread_cond_t *cv) { return pthread_cond_broadcast(cv); }
7159 + static int cond_init(pthread_cond_t *cv) { return pthread_cond_init(cv, NULL); }
7160 + static int cond_destroy(pthread_cond_t *cv) { return pthread_cond_destroy(cv); }
7162 + static bool synchronization_initialized() { return _synchronization_initialized; }
7164 + static void set_lgrp_home(lgrp_home_func_t func) { _lgrp_home = func; }
7165 + static void set_lgrp_init(lgrp_init_func_t func) { _lgrp_init = func; }
7166 + static void set_lgrp_fini(lgrp_fini_func_t func) { _lgrp_fini = func; }
7167 + static void set_lgrp_root(lgrp_root_func_t func) { _lgrp_root = func; }
7168 + static void set_lgrp_children(lgrp_children_func_t func) { _lgrp_children = func; }
7169 + static void set_lgrp_resources(lgrp_resources_func_t func) { _lgrp_resources = func; }
7170 + static void set_lgrp_nlgrps(lgrp_nlgrps_func_t func) { _lgrp_nlgrps = func; }
7171 + static void set_lgrp_cookie_stale(lgrp_cookie_stale_func_t func) { _lgrp_cookie_stale = func; }
7172 + static void set_lgrp_cookie(lgrp_cookie_t cookie) { _lgrp_cookie = cookie; }
7174 + static id_t lgrp_home(idtype_t type, id_t id) { return _lgrp_home != NULL ? _lgrp_home(type, id) : -1; }
7175 + static lgrp_cookie_t lgrp_init(lgrp_view_t view) { return _lgrp_init != NULL ? _lgrp_init(view) : 0; }
7176 + static int lgrp_fini(lgrp_cookie_t cookie) { return _lgrp_fini != NULL ? _lgrp_fini(cookie) : -1; }
7177 + static lgrp_id_t lgrp_root(lgrp_cookie_t cookie) { return _lgrp_root != NULL ? _lgrp_root(cookie) : -1; }
7178 + static int lgrp_children(lgrp_cookie_t cookie, lgrp_id_t parent,
7179 + lgrp_id_t *lgrp_array, uint_t lgrp_array_size) {
7180 + return _lgrp_children != NULL ? _lgrp_children(cookie, parent, lgrp_array, lgrp_array_size) : -1;
7182 + static int lgrp_resources(lgrp_cookie_t cookie, lgrp_id_t lgrp,
7183 + lgrp_id_t *lgrp_array, uint_t lgrp_array_size,
7184 + lgrp_rsrc_t type) {
7185 + return _lgrp_resources != NULL ? _lgrp_resources(cookie, lgrp, lgrp_array, lgrp_array_size, type) : -1;
7188 + static int lgrp_nlgrps(lgrp_cookie_t cookie) { return _lgrp_nlgrps != NULL ? _lgrp_nlgrps(cookie) : -1; }
7189 + static int lgrp_cookie_stale(lgrp_cookie_t cookie) {
7190 + return _lgrp_cookie_stale != NULL ? _lgrp_cookie_stale(cookie) : -1;
7192 + static lgrp_cookie_t lgrp_cookie() { return _lgrp_cookie; }
7194 + static sigset_t* unblocked_signals();
7195 + static sigset_t* vm_signals();
7197 + // %%% Following should be promoted to os.hpp:
7198 + // Trace number of created threads
7199 + static jint _os_thread_limit;
7200 + static volatile jint _os_thread_count;
7202 + static void correct_stack_boundaries_for_primordial_thread(Thread* thr);
7204 + // Stack repair handling
7206 + // none present
7209 +#endif // OS_SOLARIS_OS_SOLARIS_HPP
7210 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os/solaris/os_solaris.inline.hpp jdk22u-jdk-22.0.2-ga/src/hotspot/os/solaris/os_solaris.inline.hpp
7211 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os/solaris/os_solaris.inline.hpp 1970-01-01 01:00:00.000000000 +0100
7212 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/os/solaris/os_solaris.inline.hpp 2024-08-17 19:34:03.900886316 +0200
7213 @@ -0,0 +1,72 @@
7215 + * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
7216 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7218 + * This code is free software; you can redistribute it and/or modify it
7219 + * under the terms of the GNU General Public License version 2 only, as
7220 + * published by the Free Software Foundation.
7222 + * This code is distributed in the hope that it will be useful, but WITHOUT
7223 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7224 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7225 + * version 2 for more details (a copy is included in the LICENSE file that
7226 + * accompanied this code).
7228 + * You should have received a copy of the GNU General Public License version
7229 + * 2 along with this work; if not, write to the Free Software Foundation,
7230 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7232 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7233 + * or visit www.oracle.com if you need additional information or have any
7234 + * questions.
7236 + */
7238 +#ifndef OS_SOLARIS_OS_SOLARIS_INLINE_HPP
7239 +#define OS_SOLARIS_OS_SOLARIS_INLINE_HPP
7241 +#include "os_solaris.hpp"
7243 +#include "runtime/os.hpp"
7244 +#include "os_posix.inline.hpp"
7246 +// System includes
7247 +#include <sys/param.h>
7248 +#include <dlfcn.h>
7249 +#include <sys/socket.h>
7250 +#include <poll.h>
7251 +#include <sys/filio.h>
7252 +#include <unistd.h>
7253 +#include <netdb.h>
7254 +#include <setjmp.h>
7256 +inline bool os::zero_page_read_protected() {
7257 + return true;
7260 +inline bool os::uses_stack_guard_pages() {
7261 + return true;
7264 +inline bool os::must_commit_stack_guard_pages() {
7265 + assert(uses_stack_guard_pages(), "sanity check");
7266 + int r = thr_main() ;
7267 + guarantee (r == 0 || r == 1, "CR6501650 or CR6493689") ;
7268 + return r;
7272 +// Bang the shadow pages if they need to be touched to be mapped.
7273 +inline void os::map_stack_shadow_pages(address sp) {
7276 +// stubbed-out trim-native support
7277 +inline bool os::can_trim_native_heap() { return false; }
7278 +inline bool os::trim_native_heap(os::size_change_t* rss_change) { return false; }
7280 +//////////////////////////////////////////////////////////////////////////////
7281 +////////////////////////////////////////////////////////////////////////////////
7283 +inline bool os::numa_has_group_homing() { return true; }
7285 +#endif // OS_SOLARIS_OS_SOLARIS_INLINE_HPP
7286 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os/solaris/osThread_solaris.cpp jdk22u-jdk-22.0.2-ga/src/hotspot/os/solaris/osThread_solaris.cpp
7287 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os/solaris/osThread_solaris.cpp 1970-01-01 01:00:00.000000000 +0100
7288 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/os/solaris/osThread_solaris.cpp 2024-08-17 19:34:03.897487029 +0200
7289 @@ -0,0 +1,47 @@
7291 + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
7292 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7294 + * This code is free software; you can redistribute it and/or modify it
7295 + * under the terms of the GNU General Public License version 2 only, as
7296 + * published by the Free Software Foundation.
7298 + * This code is distributed in the hope that it will be useful, but WITHOUT
7299 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7300 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7301 + * version 2 for more details (a copy is included in the LICENSE file that
7302 + * accompanied this code).
7304 + * You should have received a copy of the GNU General Public License version
7305 + * 2 along with this work; if not, write to the Free Software Foundation,
7306 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7308 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7309 + * or visit www.oracle.com if you need additional information or have any
7310 + * questions.
7312 + */
7314 +// no precompiled headers
7315 +#include "runtime/handles.inline.hpp"
7316 +#include "runtime/mutexLocker.hpp"
7317 +#include "runtime/os.hpp"
7318 +#include "runtime/osThread.hpp"
7319 +#include "runtime/safepoint.hpp"
7320 +#include "runtime/vmThread.hpp"
7322 +#include <signal.h>
7324 + // ***************************************************************
7325 + // Platform dependent initialization and cleanup
7326 + // ***************************************************************
7328 +void OSThread::pd_initialize() {
7329 + _thread_id = 0;
7330 + sigemptyset(&_caller_sigmask);
7332 + _vm_created_thread = false;
7335 +void OSThread::pd_destroy() {
7337 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os/solaris/osThread_solaris.hpp jdk22u-jdk-22.0.2-ga/src/hotspot/os/solaris/osThread_solaris.hpp
7338 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os/solaris/osThread_solaris.hpp 1970-01-01 01:00:00.000000000 +0100
7339 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/os/solaris/osThread_solaris.hpp 2024-08-17 19:34:03.897774740 +0200
7340 @@ -0,0 +1,93 @@
7342 + * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
7343 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7345 + * This code is free software; you can redistribute it and/or modify it
7346 + * under the terms of the GNU General Public License version 2 only, as
7347 + * published by the Free Software Foundation.
7349 + * This code is distributed in the hope that it will be useful, but WITHOUT
7350 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7351 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7352 + * version 2 for more details (a copy is included in the LICENSE file that
7353 + * accompanied this code).
7355 + * You should have received a copy of the GNU General Public License version
7356 + * 2 along with this work; if not, write to the Free Software Foundation,
7357 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7359 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7360 + * or visit www.oracle.com if you need additional information or have any
7361 + * questions.
7363 + */
7365 +#ifndef OS_SOLARIS_OSTHREAD_SOLARIS_HPP
7366 +#define OS_SOLARIS_OSTHREAD_SOLARIS_HPP
7368 +// This is embedded via include into the class OSThread
7369 + public:
7370 + typedef thread_t thread_id_t;
7372 + private:
7373 + uint _lwp_id; // lwp ID, only used with bound threads
7374 + int _native_priority; // Saved native priority when starting
7375 + // a bound thread
7376 + sigset_t _caller_sigmask; // Caller's signal mask
7377 + bool _vm_created_thread; // true if the VM created this thread,
7378 + // false if primary thread or attached thread
7379 + public:
7380 + uint lwp_id() const { return _lwp_id; }
7381 + int native_priority() const { return _native_priority; }
7383 + // Set and get state of _vm_created_thread flag
7384 + void set_vm_created() { _vm_created_thread = true; }
7385 + bool is_vm_created() { return _vm_created_thread; }
7387 + // Methods to save/restore caller's signal mask
7388 + sigset_t caller_sigmask() const { return _caller_sigmask; }
7389 + void set_caller_sigmask(sigset_t sigmask) { _caller_sigmask = sigmask; }
7391 +#ifndef PRODUCT
7392 + // Used for debugging, return a unique integer for each thread.
7393 + int thread_identifier() const { return _thread_id; }
7394 +#endif
7395 +#ifdef ASSERT
7396 + // On solaris reposition can fail in two ways:
7397 + // 1: a mismatched pc, because signal is delivered too late, target thread
7398 + // is resumed.
7399 + // 2: on a timeout where signal is lost, target thread is resumed.
7400 + bool valid_reposition_failure() {
7401 + // only 1 and 2 can happen and we can handle both of them
7402 + return true;
7404 +#endif
7405 + void set_lwp_id(uint id) { _lwp_id = id; }
7406 + void set_native_priority(int prio) { _native_priority = prio; }
7408 + public:
7409 + pthread_t pthread_id() const {
7410 + // Here: same as OSThread::thread_id()
7411 + return _thread_id;
7413 + SuspendResume sr;
7415 + private:
7416 + void* _siginfo;
7417 + ucontext_t* _ucontext;
7419 + public:
7420 + void set_siginfo(void* ptr) { _siginfo = ptr; }
7421 + ucontext_t* ucontext() const { return _ucontext; }
7422 + void set_ucontext(ucontext_t* ptr) { _ucontext = ptr; }
7424 + // ***************************************************************
7425 + // Platform dependent initialization and cleanup
7426 + // ***************************************************************
7428 +private:
7430 + void pd_initialize();
7431 + void pd_destroy();
7433 +#endif // OS_SOLARIS_OSTHREAD_SOLARIS_HPP
7434 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os/solaris/vmStructs_solaris.hpp jdk22u-jdk-22.0.2-ga/src/hotspot/os/solaris/vmStructs_solaris.hpp
7435 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os/solaris/vmStructs_solaris.hpp 1970-01-01 01:00:00.000000000 +0100
7436 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/os/solaris/vmStructs_solaris.hpp 2024-08-17 19:34:03.901153378 +0200
7437 @@ -0,0 +1,44 @@
7439 + * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
7440 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7442 + * This code is free software; you can redistribute it and/or modify it
7443 + * under the terms of the GNU General Public License version 2 only, as
7444 + * published by the Free Software Foundation.
7446 + * This code is distributed in the hope that it will be useful, but WITHOUT
7447 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7448 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7449 + * version 2 for more details (a copy is included in the LICENSE file that
7450 + * accompanied this code).
7452 + * You should have received a copy of the GNU General Public License version
7453 + * 2 along with this work; if not, write to the Free Software Foundation,
7454 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7456 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7457 + * or visit www.oracle.com if you need additional information or have any
7458 + * questions.
7460 + */
7462 +#ifndef OS_SOLARIS_VMSTRUCTS_SOLARIS_HPP
7463 +#define OS_SOLARIS_VMSTRUCTS_SOLARIS_HPP
7465 +// These are the OS-specific fields, types and integer
7466 +// constants required by the Serviceability Agent. This file is
7467 +// referenced by vmStructs.cpp.
7469 +#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) \
7470 + nonstatic_field(OSThread, _thread_id, OSThread::thread_id_t)
7472 +#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) \
7473 + declare_unsigned_integer_type(OSThread::thread_id_t)
7475 +#define VM_INT_CONSTANTS_OS(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
7477 +#define VM_LONG_CONSTANTS_OS(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
7479 +#define VM_ADDRESSES_OS(declare_address, declare_preprocessor_address, declare_function)
7481 +#endif // OS_SOLARIS_VMSTRUCTS_SOLARIS_HPP
7482 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os_cpu/solaris_x86/assembler_solaris_x86.cpp jdk22u-jdk-22.0.2-ga/src/hotspot/os_cpu/solaris_x86/assembler_solaris_x86.cpp
7483 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os_cpu/solaris_x86/assembler_solaris_x86.cpp 1970-01-01 01:00:00.000000000 +0100
7484 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/os_cpu/solaris_x86/assembler_solaris_x86.cpp 2024-08-17 19:34:03.901522356 +0200
7485 @@ -0,0 +1,37 @@
7487 + * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
7488 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7490 + * This code is free software; you can redistribute it and/or modify it
7491 + * under the terms of the GNU General Public License version 2 only, as
7492 + * published by the Free Software Foundation.
7494 + * This code is distributed in the hope that it will be useful, but WITHOUT
7495 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7496 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7497 + * version 2 for more details (a copy is included in the LICENSE file that
7498 + * accompanied this code).
7500 + * You should have received a copy of the GNU General Public License version
7501 + * 2 along with this work; if not, write to the Free Software Foundation,
7502 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7504 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7505 + * or visit www.oracle.com if you need additional information or have any
7506 + * questions.
7508 + */
7510 +#include "precompiled.hpp"
7511 +#include "asm/macroAssembler.inline.hpp"
7512 +#include "runtime/os.hpp"
7514 +void MacroAssembler::int3() {
7515 + push(rax);
7516 + push(rdx);
7517 + push(rcx);
7518 + call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint)));
7519 + pop(rcx);
7520 + pop(rdx);
7521 + pop(rax);
7523 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os_cpu/solaris_x86/atomic_solaris_x86.hpp jdk22u-jdk-22.0.2-ga/src/hotspot/os_cpu/solaris_x86/atomic_solaris_x86.hpp
7524 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os_cpu/solaris_x86/atomic_solaris_x86.hpp 1970-01-01 01:00:00.000000000 +0100
7525 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/os_cpu/solaris_x86/atomic_solaris_x86.hpp 2024-08-17 19:34:03.901863981 +0200
7526 @@ -0,0 +1,182 @@
7528 + * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
7529 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7531 + * This code is free software; you can redistribute it and/or modify it
7532 + * under the terms of the GNU General Public License version 2 only, as
7533 + * published by the Free Software Foundation.
7535 + * This code is distributed in the hope that it will be useful, but WITHOUT
7536 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7537 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7538 + * version 2 for more details (a copy is included in the LICENSE file that
7539 + * accompanied this code).
7541 + * You should have received a copy of the GNU General Public License version
7542 + * 2 along with this work; if not, write to the Free Software Foundation,
7543 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7545 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7546 + * or visit www.oracle.com if you need additional information or have any
7547 + * questions.
7549 + */
7551 +#ifndef OS_CPU_SOLARIS_X86_ATOMIC_SOLARIS_X86_HPP
7552 +#define OS_CPU_SOLARIS_X86_ATOMIC_SOLARIS_X86_HPP
7554 +inline int32_t _Atomic_add(int32_t add_value, volatile int32_t* dest) {
7555 + int32_t rv = add_value;
7556 + __asm__ volatile ("lock xaddl %0,(%2)"
7557 + : "=r" (rv)
7558 + : "0" (rv), "r" (dest)
7559 + : "cc", "memory");
7560 + return rv + add_value;
7562 +inline int64_t _Atomic_add_long(int64_t add_value, volatile int64_t* dest) {
7563 + int64_t rv = add_value;
7564 + __asm__ volatile ("lock xaddq %0,(%2)"
7565 + : "=r" (rv)
7566 + : "0" (rv), "r" (dest)
7567 + : "cc", "memory");
7568 + return rv + add_value;
7570 +inline int32_t _Atomic_xchg(int32_t exchange_value, volatile int32_t* dest) {
7571 + __asm__ __volatile__ ("xchgl (%2),%0"
7572 + : "=r" (exchange_value)
7573 + : "0" (exchange_value), "r" (dest)
7574 + : "memory");
7575 + return exchange_value;
7577 +inline int64_t _Atomic_xchg_long(int64_t exchange_value, volatile int64_t* dest) {
7578 + __asm__ __volatile__ ("xchgq (%2),%0"
7579 + : "=r" (exchange_value)
7580 + : "0" (exchange_value), "r" (dest)
7581 + : "memory");
7582 + return exchange_value;
7584 +inline int8_t _Atomic_cmpxchg_byte(int8_t exchange_value, volatile int8_t* dest, int8_t compare_value) {
7585 + __asm__ volatile ("lock cmpxchgb %1,(%3)"
7586 + : "=a" (exchange_value)
7587 + : "q" (exchange_value), "a" (compare_value), "r" (dest)
7588 + : "cc", "memory");
7589 + return exchange_value;
7591 +inline int32_t _Atomic_cmpxchg(int32_t exchange_value, volatile int32_t* dest, int32_t compare_value) {
7592 + __asm__ volatile ("lock cmpxchgl %1,(%3)"
7593 + : "=a" (exchange_value)
7594 + : "q" (exchange_value), "a" (compare_value), "r" (dest)
7595 + : "cc", "memory");
7596 + return exchange_value;
7598 +inline int64_t _Atomic_cmpxchg_long(int64_t exchange_value, volatile int64_t* dest, int64_t compare_value) {
7599 + __asm__ volatile ("lock cmpxchgq %1,(%3)"
7600 + : "=a" (exchange_value)
7601 + : "q" (exchange_value), "a" (compare_value), "r" (dest)
7602 + : "cc", "memory");
7603 + return exchange_value;
7606 +template<size_t byte_size>
7607 +struct Atomic::PlatformAdd {
7608 + template<typename D, typename I>
7609 + D add_then_fetch(D volatile* dest, I add_value, atomic_memory_order order) const;
7611 + template<typename D, typename I>
7612 + D fetch_then_add(D volatile* dest, I add_value, atomic_memory_order order) const {
7613 + return add_then_fetch(dest, add_value, order) - add_value;
7617 +// Not using add_using_helper; see comment for cmpxchg.
7618 +template<>
7619 +template<typename D, typename I>
7620 +inline D Atomic::PlatformAdd<4>::add_then_fetch(D volatile* dest, I add_value,
7621 + atomic_memory_order order) const {
7622 + STATIC_ASSERT(4 == sizeof(I));
7623 + STATIC_ASSERT(4 == sizeof(D));
7624 + return PrimitiveConversions::cast<D>(
7625 + _Atomic_add(PrimitiveConversions::cast<int32_t>(add_value),
7626 + reinterpret_cast<int32_t volatile*>(dest)));
7629 +// Not using add_using_helper; see comment for cmpxchg.
7630 +template<>
7631 +template<typename D, typename I>
7632 +inline D Atomic::PlatformAdd<8>::add_then_fetch(D volatile* dest, I add_value,
7633 + atomic_memory_order order) const {
7634 + STATIC_ASSERT(8 == sizeof(I));
7635 + STATIC_ASSERT(8 == sizeof(D));
7636 + return PrimitiveConversions::cast<D>(
7637 + _Atomic_add_long(PrimitiveConversions::cast<int64_t>(add_value),
7638 + reinterpret_cast<int64_t volatile*>(dest)));
7641 +template<>
7642 +template<typename T>
7643 +inline T Atomic::PlatformXchg<4>::operator()(T volatile* dest,
7644 + T exchange_value,
7645 + atomic_memory_order order) const {
7646 + STATIC_ASSERT(4 == sizeof(T));
7647 + return PrimitiveConversions::cast<T>(
7648 + _Atomic_xchg(PrimitiveConversions::cast<int32_t>(exchange_value),
7649 + reinterpret_cast<int32_t volatile*>(dest)));
7652 +template<>
7653 +template<typename T>
7654 +inline T Atomic::PlatformXchg<8>::operator()(T volatile* dest,
7655 + T exchange_value,
7656 + atomic_memory_order order) const {
7657 + STATIC_ASSERT(8 == sizeof(T));
7658 + return PrimitiveConversions::cast<T>(
7659 + _Atomic_xchg_long(PrimitiveConversions::cast<int64_t>(exchange_value),
7660 + reinterpret_cast<int64_t volatile*>(dest)));
7663 +// Not using cmpxchg_using_helper here, because some configurations of
7664 +// Solaris compiler don't deal well with passing a "defined in .il"
7665 +// function as an argument. We *should* switch to using gcc-style
7666 +// inline assembly, but attempting to do so with Studio 12.4 ran into
7667 +// segfaults.
7669 +template<>
7670 +template<typename T>
7671 +inline T Atomic::PlatformCmpxchg<1>::operator()(T volatile* dest,
7672 + T compare_value,
7673 + T exchange_value,
7674 + atomic_memory_order order) const {
7675 + STATIC_ASSERT(1 == sizeof(T));
7676 + return PrimitiveConversions::cast<T>(
7677 + _Atomic_cmpxchg_byte(PrimitiveConversions::cast<int8_t>(exchange_value),
7678 + reinterpret_cast<int8_t volatile*>(dest),
7679 + PrimitiveConversions::cast<int8_t>(compare_value)));
7682 +template<>
7683 +template<typename T>
7684 +inline T Atomic::PlatformCmpxchg<4>::operator()(T volatile* dest,
7685 + T compare_value,
7686 + T exchange_value,
7687 + atomic_memory_order order) const {
7688 + STATIC_ASSERT(4 == sizeof(T));
7689 + return PrimitiveConversions::cast<T>(
7690 + _Atomic_cmpxchg(PrimitiveConversions::cast<int32_t>(exchange_value),
7691 + reinterpret_cast<int32_t volatile*>(dest),
7692 + PrimitiveConversions::cast<int32_t>(compare_value)));
7695 +template<>
7696 +template<typename T>
7697 +inline T Atomic::PlatformCmpxchg<8>::operator()(T volatile* dest,
7698 + T compare_value,
7699 + T exchange_value,
7700 + atomic_memory_order order) const {
7701 + STATIC_ASSERT(8 == sizeof(T));
7702 + return PrimitiveConversions::cast<T>(
7703 + _Atomic_cmpxchg_long(PrimitiveConversions::cast<int64_t>(exchange_value),
7704 + reinterpret_cast<int64_t volatile*>(dest),
7705 + PrimitiveConversions::cast<int64_t>(compare_value)));
7708 +#endif // OS_CPU_SOLARIS_X86_ATOMIC_SOLARIS_X86_HPP
7709 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os_cpu/solaris_x86/bytes_solaris_x86.hpp jdk22u-jdk-22.0.2-ga/src/hotspot/os_cpu/solaris_x86/bytes_solaris_x86.hpp
7710 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os_cpu/solaris_x86/bytes_solaris_x86.hpp 1970-01-01 01:00:00.000000000 +0100
7711 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/os_cpu/solaris_x86/bytes_solaris_x86.hpp 2024-08-17 19:34:03.902128588 +0200
7712 @@ -0,0 +1,60 @@
7714 + * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
7715 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7717 + * This code is free software; you can redistribute it and/or modify it
7718 + * under the terms of the GNU General Public License version 2 only, as
7719 + * published by the Free Software Foundation.
7721 + * This code is distributed in the hope that it will be useful, but WITHOUT
7722 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7723 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7724 + * version 2 for more details (a copy is included in the LICENSE file that
7725 + * accompanied this code).
7727 + * You should have received a copy of the GNU General Public License version
7728 + * 2 along with this work; if not, write to the Free Software Foundation,
7729 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7731 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7732 + * or visit www.oracle.com if you need additional information or have any
7733 + * questions.
7735 + */
7737 +#ifndef OS_CPU_SOLARIS_X86_BYTES_SOLARIS_X86_HPP
7738 +#define OS_CPU_SOLARIS_X86_BYTES_SOLARIS_X86_HPP
7740 +extern "C" {
7741 + inline u2 _raw_swap_u2(u2 x) {
7742 + unsigned short int __dest;
7743 + __asm__ ("rorw $8, %w0": "=r" (__dest): "0" (x): "cc");
7744 + return __dest;
7746 + inline u4 _raw_swap_u4(u4 x) {
7747 + unsigned int __dest;
7748 + __asm__ ("bswap %0" : "=r" (__dest) : "0" (x));
7749 + return __dest;
7751 + inline u8 _raw_swap_u8(u8 x) {
7752 + unsigned long __dest;
7753 + __asm__ ("bswap %q0" : "=r" (__dest) : "0" (x));
7754 + return __dest;
7758 +// Efficient swapping of data bytes from Java byte
7759 +// ordering to native byte ordering and vice versa.
7760 +inline u2 Bytes::swap_u2(u2 x) {
7761 + return _raw_swap_u2(x);
7764 +inline u4 Bytes::swap_u4(u4 x) {
7765 + return _raw_swap_u4(x);
7768 +inline u8 Bytes::swap_u8(u8 x) {
7769 + return _raw_swap_u8(x);
7772 +#endif // OS_CPU_SOLARIS_X86_BYTES_SOLARIS_X86_HPP
7773 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os_cpu/solaris_x86/copy_solaris_x86.hpp jdk22u-jdk-22.0.2-ga/src/hotspot/os_cpu/solaris_x86/copy_solaris_x86.hpp
7774 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os_cpu/solaris_x86/copy_solaris_x86.hpp 1970-01-01 01:00:00.000000000 +0100
7775 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/os_cpu/solaris_x86/copy_solaris_x86.hpp 2024-08-17 19:34:03.902386493 +0200
7776 @@ -0,0 +1,30 @@
7778 + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
7779 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7781 + * This code is free software; you can redistribute it and/or modify it
7782 + * under the terms of the GNU General Public License version 2 only, as
7783 + * published by the Free Software Foundation.
7785 + * This code is distributed in the hope that it will be useful, but WITHOUT
7786 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7787 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7788 + * version 2 for more details (a copy is included in the LICENSE file that
7789 + * accompanied this code).
7791 + * You should have received a copy of the GNU General Public License version
7792 + * 2 along with this work; if not, write to the Free Software Foundation,
7793 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7795 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7796 + * or visit www.oracle.com if you need additional information or have any
7797 + * questions.
7799 + */
7801 +#ifndef OS_CPU_SOLARIS_X86_COPY_SOLARIS_X86_HPP
7802 +#define OS_CPU_SOLARIS_X86_COPY_SOLARIS_X86_HPP
7804 +// now in central copy_x86.hpp
7806 +#endif // OS_CPU_SOLARIS_X86_COPY_SOLARIS_X86_HPP
7807 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os_cpu/solaris_x86/globals_solaris_x86.hpp jdk22u-jdk-22.0.2-ga/src/hotspot/os_cpu/solaris_x86/globals_solaris_x86.hpp
7808 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os_cpu/solaris_x86/globals_solaris_x86.hpp 1970-01-01 01:00:00.000000000 +0100
7809 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/os_cpu/solaris_x86/globals_solaris_x86.hpp 2024-08-17 19:34:03.902649654 +0200
7810 @@ -0,0 +1,40 @@
7812 + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
7813 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7815 + * This code is free software; you can redistribute it and/or modify it
7816 + * under the terms of the GNU General Public License version 2 only, as
7817 + * published by the Free Software Foundation.
7819 + * This code is distributed in the hope that it will be useful, but WITHOUT
7820 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7821 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7822 + * version 2 for more details (a copy is included in the LICENSE file that
7823 + * accompanied this code).
7825 + * You should have received a copy of the GNU General Public License version
7826 + * 2 along with this work; if not, write to the Free Software Foundation,
7827 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7829 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7830 + * or visit www.oracle.com if you need additional information or have any
7831 + * questions.
7833 + */
7835 +#ifndef OS_CPU_SOLARIS_X86_GLOBALS_SOLARIS_X86_HPP
7836 +#define OS_CPU_SOLARIS_X86_GLOBALS_SOLARIS_X86_HPP
7838 +// Sets the default values for platform dependent flags used by the runtime system.
7839 +// (see globals.hpp)
7841 +define_pd_global(bool, DontYieldALot, true); // Determined in the design center
7842 +define_pd_global(intx, CompilerThreadStackSize, 1024);
7843 +define_pd_global(intx, ThreadStackSize, 1024); // 0 => use system default
7844 +define_pd_global(intx, VMThreadStackSize, 1024);
7845 +define_pd_global(size_t, JVMInvokeMethodSlack, 8*K);
7847 +// Used on 64 bit platforms for UseCompressedOops base address
7848 +define_pd_global(size_t, HeapBaseMinAddress, 2*G);
7850 +#endif // OS_CPU_SOLARIS_X86_GLOBALS_SOLARIS_X86_HPP
7851 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os_cpu/solaris_x86/javaThread_solaris_x86.cpp jdk22u-jdk-22.0.2-ga/src/hotspot/os_cpu/solaris_x86/javaThread_solaris_x86.cpp
7852 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os_cpu/solaris_x86/javaThread_solaris_x86.cpp 1970-01-01 01:00:00.000000000 +0100
7853 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/os_cpu/solaris_x86/javaThread_solaris_x86.cpp 2024-08-17 19:34:03.904990898 +0200
7854 @@ -0,0 +1,97 @@
7856 + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
7857 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7859 + * This code is free software; you can redistribute it and/or modify it
7860 + * under the terms of the GNU General Public License version 2 only, as
7861 + * published by the Free Software Foundation.
7863 + * This code is distributed in the hope that it will be useful, but WITHOUT
7864 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7865 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7866 + * version 2 for more details (a copy is included in the LICENSE file that
7867 + * accompanied this code).
7869 + * You should have received a copy of the GNU General Public License version
7870 + * 2 along with this work; if not, write to the Free Software Foundation,
7871 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7873 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7874 + * or visit www.oracle.com if you need additional information or have any
7875 + * questions.
7877 + */
7879 +#include "precompiled.hpp"
7880 +#include "runtime/frame.inline.hpp"
7881 +#include "runtime/javaThread.hpp"
7883 +frame JavaThread::pd_last_frame() {
7884 + assert(has_last_Java_frame(), "must have last_Java_sp() when suspended");
7885 + vmassert(_anchor.last_Java_pc() != NULL, "not walkable");
7886 + return frame(_anchor.last_Java_sp(), _anchor.last_Java_fp(), _anchor.last_Java_pc());
7889 +// For Forte Analyzer AsyncGetCallTrace profiling support - thread is
7890 +// currently interrupted by SIGPROF
7891 +bool JavaThread::pd_get_top_frame_for_signal_handler(frame* fr_addr,
7892 + void* ucontext, bool isInJava) {
7893 + assert(Thread::current() == this, "caller must be current thread");
7894 + return pd_get_top_frame(fr_addr, ucontext, isInJava);
7897 +bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr,
7898 + void* ucontext, bool isInJava) {
7899 + return pd_get_top_frame(fr_addr, ucontext, isInJava);
7902 +bool JavaThread::pd_get_top_frame(frame* fr_addr,
7903 + void* ucontext, bool isInJava) {
7904 + assert(this->is_Java_thread(), "must be JavaThread");
7905 + JavaThread* jt = (JavaThread *)this;
7907 + // There is small window where last_Java_frame is not walkable or safe
7908 + if (jt->has_last_Java_frame() && jt->frame_anchor()->walkable()) {
7909 + *fr_addr = jt->pd_last_frame();
7910 + return true;
7913 + ucontext_t* uc = (ucontext_t*) ucontext;
7915 + // We always want to use the initial frame we create from the ucontext as
7916 + // it certainly signals where we currently are. However that frame may not
7917 + // be safe for calling sender. In that case if we have a last_Java_frame
7918 + // then the forte walker will switch to that frame as the virtual sender
7919 + // for the frame we create here which is not sender safe.
7921 + intptr_t* ret_fp;
7922 + intptr_t* ret_sp;
7923 + address addr = os::fetch_frame_from_context(uc, &ret_sp, &ret_fp);
7925 + // Something would really have to be screwed up to get a NULL pc
7927 + if (addr == NULL) {
7928 + // ucontext wasn't useful
7929 + return false;
7932 + // If sp and fp are nonsense just leave them out
7934 + if (!jt->is_in_full_stack((address)ret_sp)) {
7935 + ret_sp = NULL;
7936 + ret_fp = NULL;
7937 + } else {
7938 + // sp is reasonable is fp reasonable?
7939 + if (!jt->is_in_stack_range_incl((address)ret_fp, (address)ret_sp)) {
7940 + ret_fp = NULL;
7944 + frame ret_frame(ret_sp, ret_fp, addr);
7946 + *fr_addr = ret_frame;
7947 + return true;
7951 +void JavaThread::cache_global_variables() { }
7952 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os_cpu/solaris_x86/javaThread_solaris_x86.hpp jdk22u-jdk-22.0.2-ga/src/hotspot/os_cpu/solaris_x86/javaThread_solaris_x86.hpp
7953 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os_cpu/solaris_x86/javaThread_solaris_x86.hpp 1970-01-01 01:00:00.000000000 +0100
7954 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/os_cpu/solaris_x86/javaThread_solaris_x86.hpp 2024-08-17 19:34:03.905257522 +0200
7955 @@ -0,0 +1,59 @@
7957 + * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
7958 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7960 + * This code is free software; you can redistribute it and/or modify it
7961 + * under the terms of the GNU General Public License version 2 only, as
7962 + * published by the Free Software Foundation.
7964 + * This code is distributed in the hope that it will be useful, but WITHOUT
7965 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7966 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7967 + * version 2 for more details (a copy is included in the LICENSE file that
7968 + * accompanied this code).
7970 + * You should have received a copy of the GNU General Public License version
7971 + * 2 along with this work; if not, write to the Free Software Foundation,
7972 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7974 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7975 + * or visit www.oracle.com if you need additional information or have any
7976 + * questions.
7978 + */
7980 +#ifndef OS_CPU_SOLARIS_X86_JAVATHREAD_SOLARIS_X86_HPP
7981 +#define OS_CPU_SOLARIS_X86_JAVATHREAD_SOLARIS_X86_HPP
7983 + private:
7984 + void pd_initialize() { _anchor.clear(); }
7986 + frame pd_last_frame();
7988 + public:
7990 + void set_base_of_stack_pointer(intptr_t* base_sp) {}
7992 + static ByteSize last_Java_fp_offset() {
7993 + return byte_offset_of(JavaThread, _anchor) + JavaFrameAnchor::last_Java_fp_offset();
7996 + intptr_t* base_of_stack_pointer() { return NULL; }
7997 + void record_base_of_stack_pointer() {}
7999 + bool pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext,
8000 + bool isInJava);
8001 + bool pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext,
8002 + bool isInJava);
8003 +private:
8004 + bool pd_get_top_frame(frame* fr_addr, void* ucontext,
8005 + bool isInJava);
8006 +public:
8008 + // These routines are only used on cpu architectures that
8009 + // have separate register stacks (Itanium).
8010 + static bool register_stack_overflow() { return false; }
8011 + static void enable_register_stack_guard() {}
8012 + static void disable_register_stack_guard() {}
8014 +#endif // OS_CPU_SOLARIS_X86_JAVATHREAD_SOLARIS_X86_HPP
8015 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os_cpu/solaris_x86/orderAccess_solaris_x86.hpp jdk22u-jdk-22.0.2-ga/src/hotspot/os_cpu/solaris_x86/orderAccess_solaris_x86.hpp
8016 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os_cpu/solaris_x86/orderAccess_solaris_x86.hpp 1970-01-01 01:00:00.000000000 +0100
8017 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/os_cpu/solaris_x86/orderAccess_solaris_x86.hpp 2024-08-17 19:34:03.902921019 +0200
8018 @@ -0,0 +1,58 @@
8020 + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
8021 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8023 + * This code is free software; you can redistribute it and/or modify it
8024 + * under the terms of the GNU General Public License version 2 only, as
8025 + * published by the Free Software Foundation.
8027 + * This code is distributed in the hope that it will be useful, but WITHOUT
8028 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8029 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
8030 + * version 2 for more details (a copy is included in the LICENSE file that
8031 + * accompanied this code).
8033 + * You should have received a copy of the GNU General Public License version
8034 + * 2 along with this work; if not, write to the Free Software Foundation,
8035 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
8037 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
8038 + * or visit www.oracle.com if you need additional information or have any
8039 + * questions.
8041 + */
8043 +#ifndef OS_CPU_SOLARIS_X86_ORDERACCESS_SOLARIS_X86_HPP
8044 +#define OS_CPU_SOLARIS_X86_ORDERACCESS_SOLARIS_X86_HPP
8046 +// Included in orderAccess.hpp header file.
8048 +// Compiler version last used for testing: solaris studio 12u3
8049 +// Please update this information when this file changes
8051 +// Implementation of class OrderAccess.
8053 +// A compiler barrier, forcing the C++ compiler to invalidate all memory assumptions
8054 +inline void compiler_barrier() {
8055 + __asm__ volatile ("" : : : "memory");
8058 +inline void OrderAccess::loadload() { compiler_barrier(); }
8059 +inline void OrderAccess::storestore() { compiler_barrier(); }
8060 +inline void OrderAccess::loadstore() { compiler_barrier(); }
8061 +inline void OrderAccess::storeload() { fence(); }
8063 +inline void OrderAccess::acquire() { compiler_barrier(); }
8064 +inline void OrderAccess::release() { compiler_barrier(); }
8066 +inline void OrderAccess::fence() {
8067 + __asm__ volatile ("lock; addl $0,0(%%rsp)" : : : "cc", "memory");
8068 + compiler_barrier();
8071 +inline void OrderAccess::cross_modify_fence_impl() {
8072 + int idx = 0;
8073 + __asm__ volatile ("cpuid " : "+a" (idx) : : "ebx", "ecx", "edx", "memory");
8076 +#endif // OS_CPU_SOLARIS_X86_ORDERACCESS_SOLARIS_X86_HPP
8077 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.cpp jdk22u-jdk-22.0.2-ga/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.cpp
8078 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.cpp 1970-01-01 01:00:00.000000000 +0100
8079 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.cpp 2024-08-17 19:34:03.903488156 +0200
8080 @@ -0,0 +1,662 @@
8082 + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.
8083 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8085 + * This code is free software; you can redistribute it and/or modify it
8086 + * under the terms of the GNU General Public License version 2 only, as
8087 + * published by the Free Software Foundation.
8089 + * This code is distributed in the hope that it will be useful, but WITHOUT
8090 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8091 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
8092 + * version 2 for more details (a copy is included in the LICENSE file that
8093 + * accompanied this code).
8095 + * You should have received a copy of the GNU General Public License version
8096 + * 2 along with this work; if not, write to the Free Software Foundation,
8097 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
8099 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
8100 + * or visit www.oracle.com if you need additional information or have any
8101 + * questions.
8103 + */
8105 +// no precompiled headers
8106 +#include "jvm.h"
8107 +#include "asm/macroAssembler.hpp"
8108 +#include "classfile/classLoader.hpp"
8109 +#include "classfile/systemDictionary.hpp"
8110 +#include "classfile/vmSymbols.hpp"
8111 +#include "code/codeCache.hpp"
8112 +#include "code/icBuffer.hpp"
8113 +#include "code/vtableStubs.hpp"
8114 +#include "interpreter/interpreter.hpp"
8115 +#include "logging/log.hpp"
8116 +#include "memory/allocation.inline.hpp"
8117 +#include "os_solaris.hpp"
8118 +#include "os_posix.hpp"
8119 +#include "prims/jniFastGetField.hpp"
8120 +#include "prims/jvm_misc.hpp"
8121 +#include "runtime/arguments.hpp"
8122 +#include "runtime/frame.inline.hpp"
8123 +#include "runtime/interfaceSupport.inline.hpp"
8124 +#include "runtime/java.hpp"
8125 +#include "runtime/javaCalls.hpp"
8126 +#include "runtime/mutexLocker.hpp"
8127 +#include "runtime/osThread.hpp"
8128 +#include "runtime/safepointMechanism.hpp"
8129 +#include "runtime/sharedRuntime.hpp"
8130 +#include "runtime/stubRoutines.hpp"
8131 +#include "runtime/thread.inline.hpp"
8132 +#include "runtime/timer.hpp"
8133 +#include "signals_posix.hpp"
8134 +#include "utilities/align.hpp"
8135 +#include "utilities/events.hpp"
8136 +#include "utilities/vmError.hpp"
8138 +// put OS-includes here
8139 +# include <sys/types.h>
8140 +# include <sys/mman.h>
8141 +# include <pthread.h>
8142 +# include <signal.h>
8143 +# include <setjmp.h>
8144 +# include <errno.h>
8145 +# include <dlfcn.h>
8146 +# include <stdio.h>
8147 +# include <unistd.h>
8148 +# include <sys/resource.h>
8149 +# include <thread.h>
8150 +# include <sys/stat.h>
8151 +# include <sys/time.h>
8152 +# include <sys/filio.h>
8153 +# include <sys/utsname.h>
8154 +# include <sys/systeminfo.h>
8155 +# include <sys/socket.h>
8156 +# include <sys/trap.h>
8157 +# include <sys/lwp.h>
8158 +# include <poll.h>
8159 +# include <sys/lwp.h>
8160 +# include <procfs.h>
8163 +#define MAX_PATH (2 * K)
8165 +// Minimum usable stack sizes required to get to user code. Space for
8166 +// HotSpot guard pages is added later.
8167 +#ifdef _LP64
8168 +// The adlc generated method 'State::MachNodeGenerator(int)' used by the C2 compiler
8169 +// threads requires a large stack with the Solaris Studio C++ compiler version 5.13
8170 +// and product VM builds (debug builds require significantly less stack space).
8171 +size_t os::_compiler_thread_min_stack_allowed = 325 * K;
8172 +size_t os::_java_thread_min_stack_allowed = 48 * K;
8173 +size_t os::_vm_internal_thread_min_stack_allowed = 224 * K;
8174 +#else
8175 +size_t os::_compiler_thread_min_stack_allowed = 32 * K;
8176 +size_t os::_java_thread_min_stack_allowed = 32 * K;
8177 +size_t os::_vm_internal_thread_min_stack_allowed = 64 * K;
8178 +#endif // _LP64
8180 +#ifdef AMD64
8181 +#define REG_SP REG_RSP
8182 +#define REG_PC REG_RIP
8183 +#define REG_FP REG_RBP
8184 +#else
8185 +#define REG_SP UESP
8186 +#define REG_PC EIP
8187 +#define REG_FP EBP
8188 +// 4900493 counter to prevent runaway LDTR refresh attempt
8190 +static volatile int ldtr_refresh = 0;
8191 +// the libthread instruction that faults because of the stale LDTR
8193 +static const unsigned char movlfs[] = { 0x8e, 0xe0 // movl %eax,%fs
8194 + };
8195 +#endif // AMD64
8197 +char* os::non_memory_address_word() {
8198 + // Must never look like an address returned by reserve_memory,
8199 + // even in its subfields (as defined by the CPU immediate fields,
8200 + // if the CPU splits constants across multiple instructions).
8201 + return (char*) -1;
8205 +// Validate a ucontext retrieved from walking a uc_link of a ucontext.
8206 +// There are issues with libthread giving out uc_links for different threads
8207 +// on the same uc_link chain and bad or circular links.
8209 +bool os::Solaris::valid_ucontext(Thread* thread, const ucontext_t* valid, const ucontext_t* suspect) {
8210 + if (valid >= suspect ||
8211 + valid->uc_stack.ss_flags != suspect->uc_stack.ss_flags ||
8212 + valid->uc_stack.ss_sp != suspect->uc_stack.ss_sp ||
8213 + valid->uc_stack.ss_size != suspect->uc_stack.ss_size) {
8214 + DEBUG_ONLY(tty->print_cr("valid_ucontext: failed test 1");)
8215 + return false;
8218 + if (thread->is_Java_thread()) {
8219 + if (!thread->is_in_full_stack_checked((address)suspect)) {
8220 + DEBUG_ONLY(tty->print_cr("valid_ucontext: uc_link not in thread stack");)
8221 + return false;
8223 + if (!thread->is_in_full_stack_checked((address) suspect->uc_mcontext.gregs[REG_SP])) {
8224 + DEBUG_ONLY(tty->print_cr("valid_ucontext: stackpointer not in thread stack");)
8225 + return false;
8228 + return true;
8231 +// We will only follow one level of uc_link since there are libthread
8232 +// issues with ucontext linking and it is better to be safe and just
8233 +// let caller retry later.
8234 +const ucontext_t* os::Solaris::get_valid_uc_in_signal_handler(Thread *thread,
8235 + const ucontext_t *uc) {
8237 + const ucontext_t *retuc = NULL;
8239 + if (uc != NULL) {
8240 + if (uc->uc_link == NULL) {
8241 + // cannot validate without uc_link so accept current ucontext
8242 + retuc = uc;
8243 + } else if (os::Solaris::valid_ucontext(thread, uc, uc->uc_link)) {
8244 + // first ucontext is valid so try the next one
8245 + uc = uc->uc_link;
8246 + if (uc->uc_link == NULL) {
8247 + // cannot validate without uc_link so accept current ucontext
8248 + retuc = uc;
8249 + } else if (os::Solaris::valid_ucontext(thread, uc, uc->uc_link)) {
8250 + // the ucontext one level down is also valid so return it
8251 + retuc = uc;
8255 + return retuc;
8258 +void os::Posix::ucontext_set_pc(ucontext_t* uc, address pc) {
8259 + uc->uc_mcontext.gregs [REG_PC] = (greg_t) pc;
8262 +// Assumes ucontext is valid
8263 +intptr_t* os::Solaris::ucontext_get_sp(const ucontext_t *uc) {
8264 + return (intptr_t*)uc->uc_mcontext.gregs[REG_SP];
8267 +// Assumes ucontext is valid
8268 +intptr_t* os::Solaris::ucontext_get_fp(const ucontext_t *uc) {
8269 + return (intptr_t*)uc->uc_mcontext.gregs[REG_FP];
8272 +address os::Posix::ucontext_get_pc(const ucontext_t *uc) {
8273 + return (address) uc->uc_mcontext.gregs[REG_PC];
8276 +address os::fetch_frame_from_context(const void* ucVoid,
8277 + intptr_t** ret_sp, intptr_t** ret_fp) {
8279 + address epc;
8280 + const ucontext_t *uc = (const ucontext_t*)ucVoid;
8282 + if (uc != NULL) {
8283 + epc = os::Posix::ucontext_get_pc(uc);
8284 + if (ret_sp) *ret_sp = os::Solaris::ucontext_get_sp(uc);
8285 + if (ret_fp) *ret_fp = os::Solaris::ucontext_get_fp(uc);
8286 + } else {
8287 + epc = NULL;
8288 + if (ret_sp) *ret_sp = (intptr_t *)NULL;
8289 + if (ret_fp) *ret_fp = (intptr_t *)NULL;
8292 + return epc;
8295 +frame os::fetch_frame_from_context(const void* ucVoid) {
8296 + intptr_t* sp;
8297 + intptr_t* fp;
8298 + address epc = fetch_frame_from_context(ucVoid, &sp, &fp);
8299 + return frame(sp, fp, epc);
8302 +bool os::Solaris::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr) {
8303 + address pc = (address) os::Solaris::ucontext_get_pc(uc);
8304 + if (Interpreter::contains(pc)) {
8305 + // interpreter performs stack banging after the fixed frame header has
8306 + // been generated while the compilers perform it before. To maintain
8307 + // semantic consistency between interpreted and compiled frames, the
8308 + // method returns the Java sender of the current frame.
8309 + *fr = os::fetch_frame_from_context(uc);
8310 + if (!fr->is_first_java_frame()) {
8311 + // get_frame_at_stack_banging_point() is only called when we
8312 + // have well defined stacks so java_sender() calls do not need
8313 + // to assert safe_for_sender() first.
8314 + *fr = fr->java_sender();
8316 + } else {
8317 + // more complex code with compiled code
8318 + assert(!Interpreter::contains(pc), "Interpreted methods should have been handled above");
8319 + CodeBlob* cb = CodeCache::find_blob(pc);
8320 + if (cb == NULL || !cb->is_nmethod() || cb->is_frame_complete_at(pc)) {
8321 + // Not sure where the pc points to, fallback to default
8322 + // stack overflow handling
8323 + return false;
8324 + } else {
8325 + // in compiled code, the stack banging is performed just after the return pc
8326 + // has been pushed on the stack
8327 + intptr_t* fp = os::Solaris::ucontext_get_fp(uc);
8328 + intptr_t* sp = os::Solaris::ucontext_get_sp(uc);
8329 + *fr = frame(sp + 1, fp, (address)*sp);
8330 + if (!fr->is_java_frame()) {
8331 + // See java_sender() comment above.
8332 + *fr = fr->java_sender();
8336 + assert(fr->is_java_frame(), "Safety check");
8337 + return true;
8340 +frame os::get_sender_for_C_frame(frame* fr) {
8341 + return frame(fr->sender_sp(), fr->link(), fr->sender_pc());
8344 +extern "C" intptr_t *_get_current_sp() {
8345 + register intptr_t *rsp __asm__ ("rsp");
8346 + return rsp;
8349 +address os::current_stack_pointer() {
8350 + return (address)_get_current_sp();
8353 +extern "C" intptr_t *_get_current_fp() {
8354 + register intptr_t **rbp __asm__ ("rbp");
8355 + return (intptr_t*) *rbp;
8358 +frame os::current_frame() {
8359 + intptr_t* fp = _get_current_fp(); // it's inlined so want current fp
8360 + // fp is for os::current_frame. We want the fp for our caller.
8361 + frame myframe((intptr_t*)os::current_stack_pointer(),
8362 + (intptr_t*)fp,
8363 + CAST_FROM_FN_PTR(address, os::current_frame));
8364 + frame caller_frame = os::get_sender_for_C_frame(&myframe);
8366 + if (os::is_first_C_frame(&caller_frame)) {
8367 + // stack is not walkable
8368 + frame ret; // This will be a null useless frame
8369 + return ret;
8370 + } else {
8371 + // return frame for our caller's caller
8372 + return os::get_sender_for_C_frame(&caller_frame);
8377 +bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info,
8378 + ucontext_t* uc, JavaThread* thread) {
8380 + if (info == NULL || info->si_code <= 0 || info->si_code == SI_NOINFO) {
8381 + // can't decode this kind of signal
8382 + info = NULL;
8383 + } else {
8384 + assert(sig == info->si_signo, "bad siginfo");
8387 + // decide if this trap can be handled by a stub
8388 + address stub = NULL;
8390 + address pc = NULL;
8392 + //%note os_trap_1
8393 + if (info != NULL && uc != NULL && thread != NULL) {
8394 + // factor me: getPCfromContext
8395 + pc = (address) uc->uc_mcontext.gregs[REG_PC];
8397 + // Handle ALL stack overflow variations here
8398 + if (sig == SIGSEGV && info->si_code == SEGV_ACCERR) {
8399 + address addr = (address) info->si_addr;
8400 + if (thread->in_stack_yellow_reserved_zone(addr)) {
8401 + if (thread->thread_state() == _thread_in_Java) {
8402 + if (thread->in_stack_reserved_zone(addr)) {
8403 + frame fr;
8404 + if (os::Solaris::get_frame_at_stack_banging_point(thread, uc, &fr)) {
8405 + assert(fr.is_java_frame(), "Must be Java frame");
8406 + frame activation = SharedRuntime::look_for_reserved_stack_annotated_method(thread, fr);
8407 + if (activation.sp() != NULL) {
8408 + thread->disable_stack_reserved_zone();
8409 + if (activation.is_interpreted_frame()) {
8410 + thread->set_reserved_stack_activation((address)(
8411 + activation.fp() + frame::interpreter_frame_initial_sp_offset));
8412 + } else {
8413 + thread->set_reserved_stack_activation((address)activation.unextended_sp());
8415 + return true;
8419 + // Throw a stack overflow exception. Guard pages will be reenabled
8420 + // while unwinding the stack.
8421 + thread->disable_stack_yellow_reserved_zone();
8422 + stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW);
8423 + } else {
8424 + // Thread was in the vm or native code. Return and try to finish.
8425 + thread->disable_stack_yellow_reserved_zone();
8426 + return true;
8428 + } else if (thread->in_stack_red_zone(addr)) {
8429 + // Fatal red zone violation. Disable the guard pages and fall through
8430 + // to handle_unexpected_exception way down below.
8431 + thread->disable_stack_red_zone();
8432 + tty->print_raw_cr("An irrecoverable stack overflow has occurred.");
8436 + if ((sig == SIGSEGV) && VM_Version::is_cpuinfo_segv_addr(pc)) {
8437 + // Verify that OS save/restore AVX registers.
8438 + stub = VM_Version::cpuinfo_cont_addr();
8441 + if (thread->thread_state() == _thread_in_vm ||
8442 + thread->thread_state() == _thread_in_native) {
8443 + if (sig == SIGBUS && info->si_code == BUS_OBJERR && thread->doing_unsafe_access()) {
8444 + address next_pc = Assembler::locate_next_instruction(pc);
8445 + if (UnsafeCopyMemory::contains_pc(pc)) {
8446 + next_pc = UnsafeCopyMemory::page_error_continue_pc(pc);
8448 + stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
8452 + if (thread->thread_state() == _thread_in_Java) {
8453 + // Support Safepoint Polling
8454 + if ( sig == SIGSEGV && SafepointMechanism::is_poll_address((address)info->si_addr)) {
8455 + stub = SharedRuntime::get_poll_stub(pc);
8457 + else if (sig == SIGBUS && info->si_code == BUS_OBJERR) {
8458 + // BugId 4454115: A read from a MappedByteBuffer can fault
8459 + // here if the underlying file has been truncated.
8460 + // Do not crash the VM in such a case.
8461 + CodeBlob* cb = CodeCache::find_blob(pc);
8462 + if (cb != NULL) {
8463 + CompiledMethod* nm = cb->as_compiled_method_or_null();
8464 + bool is_unsafe_arraycopy = thread->doing_unsafe_access() && UnsafeCopyMemory::contains_pc(pc);
8465 + if ((nm != NULL && nm->has_unsafe_access()) || is_unsafe_arraycopy) {
8466 + address next_pc = Assembler::locate_next_instruction(pc);
8467 + if (is_unsafe_arraycopy) {
8468 + next_pc = UnsafeCopyMemory::page_error_continue_pc(pc);
8470 + stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
8474 + else
8475 + if (sig == SIGFPE && info->si_code == FPE_INTDIV) {
8476 + // integer divide by zero
8477 + stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_DIVIDE_BY_ZERO);
8479 +#ifndef AMD64
8480 + else if (sig == SIGFPE && info->si_code == FPE_FLTDIV) {
8481 + // floating-point divide by zero
8482 + stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_DIVIDE_BY_ZERO);
8484 + else if (sig == SIGFPE && info->si_code == FPE_FLTINV) {
8485 + // The encoding of D2I in i486.ad can cause an exception prior
8486 + // to the fist instruction if there was an invalid operation
8487 + // pending. We want to dismiss that exception. From the win_32
8488 + // side it also seems that if it really was the fist causing
8489 + // the exception that we do the d2i by hand with different
8490 + // rounding. Seems kind of weird. QQQ TODO
8491 + // Note that we take the exception at the NEXT floating point instruction.
8492 + if (pc[0] == 0xDB) {
8493 + assert(pc[0] == 0xDB, "not a FIST opcode");
8494 + assert(pc[1] == 0x14, "not a FIST opcode");
8495 + assert(pc[2] == 0x24, "not a FIST opcode");
8496 + return true;
8497 + } else {
8498 + assert(pc[-3] == 0xDB, "not an flt invalid opcode");
8499 + assert(pc[-2] == 0x14, "not an flt invalid opcode");
8500 + assert(pc[-1] == 0x24, "not an flt invalid opcode");
8503 + else if (sig == SIGFPE ) {
8504 + tty->print_cr("caught SIGFPE, info 0x%x.", info->si_code);
8506 +#endif // !AMD64
8508 + // QQQ It doesn't seem that we need to do this on x86 because we should be able
8509 + // to return properly from the handler without this extra stuff on the back side.
8511 + else if (sig == SIGSEGV && info->si_code > 0 &&
8512 + MacroAssembler::uses_implicit_null_check(info->si_addr)) {
8513 + // Determination of interpreter/vtable stub/compiled code null exception
8514 + stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL);
8518 + // jni_fast_Get<Primitive>Field can trap at certain pc's if a GC kicks in
8519 + // and the heap gets shrunk before the field access.
8520 + if ((sig == SIGSEGV) || (sig == SIGBUS)) {
8521 + address addr = JNI_FastGetField::find_slowcase_pc(pc);
8522 + if (addr != (address)-1) {
8523 + stub = addr;
8528 + // Execution protection violation
8529 + //
8530 + // Preventative code for future versions of Solaris which may
8531 + // enable execution protection when running the 32-bit VM on AMD64.
8532 + //
8533 + // This should be kept as the last step in the triage. We don't
8534 + // have a dedicated trap number for a no-execute fault, so be
8535 + // conservative and allow other handlers the first shot.
8536 + //
8537 + // Note: We don't test that info->si_code == SEGV_ACCERR here.
8538 + // this si_code is so generic that it is almost meaningless; and
8539 + // the si_code for this condition may change in the future.
8540 + // Furthermore, a false-positive should be harmless.
8541 + if (UnguardOnExecutionViolation > 0 &&
8542 + (sig == SIGSEGV || sig == SIGBUS) &&
8543 + uc->uc_mcontext.gregs[TRAPNO] == T_PGFLT) { // page fault
8544 + int page_size = os::vm_page_size();
8545 + address addr = (address) info->si_addr;
8546 + address pc = (address) uc->uc_mcontext.gregs[REG_PC];
8547 + // Make sure the pc and the faulting address are sane.
8548 + //
8549 + // If an instruction spans a page boundary, and the page containing
8550 + // the beginning of the instruction is executable but the following
8551 + // page is not, the pc and the faulting address might be slightly
8552 + // different - we still want to unguard the 2nd page in this case.
8553 + //
8554 + // 15 bytes seems to be a (very) safe value for max instruction size.
8555 + bool pc_is_near_addr =
8556 + (pointer_delta((void*) addr, (void*) pc, sizeof(char)) < 15);
8557 + bool instr_spans_page_boundary =
8558 + (align_down((intptr_t) pc ^ (intptr_t) addr,
8559 + (intptr_t) page_size) > 0);
8561 + if (pc == addr || (pc_is_near_addr && instr_spans_page_boundary)) {
8562 + static volatile address last_addr =
8563 + (address) os::non_memory_address_word();
8565 + // In conservative mode, don't unguard unless the address is in the VM
8566 + if (addr != last_addr &&
8567 + (UnguardOnExecutionViolation > 1 || os::address_is_in_vm(addr))) {
8569 + // Make memory rwx and retry
8570 + address page_start = align_down(addr, page_size);
8571 + bool res = os::protect_memory((char*) page_start, page_size,
8572 + os::MEM_PROT_RWX);
8574 + log_debug(os)("Execution protection violation "
8575 + "at " INTPTR_FORMAT
8576 + ", unguarding " INTPTR_FORMAT ": %s, errno=%d", p2i(addr),
8577 + p2i(page_start), (res ? "success" : "failed"), errno);
8578 + stub = pc;
8580 + // Set last_addr so if we fault again at the same address, we don't end
8581 + // up in an endless loop.
8582 + //
8583 + // There are two potential complications here. Two threads trapping at
8584 + // the same address at the same time could cause one of the threads to
8585 + // think it already unguarded, and abort the VM. Likely very rare.
8586 + //
8587 + // The other race involves two threads alternately trapping at
8588 + // different addresses and failing to unguard the page, resulting in
8589 + // an endless loop. This condition is probably even more unlikely than
8590 + // the first.
8591 + //
8592 + // Although both cases could be avoided by using locks or thread local
8593 + // last_addr, these solutions are unnecessary complication: this
8594 + // handler is a best-effort safety net, not a complete solution. It is
8595 + // disabled by default and should only be used as a workaround in case
8596 + // we missed any no-execute-unsafe VM code.
8598 + last_addr = addr;
8603 + if (stub != NULL) {
8604 + // save all thread context in case we need to restore it
8606 + if (thread != NULL) thread->set_saved_exception_pc(pc);
8607 + // 12/02/99: On Sparc it appears that the full context is also saved
8608 + // but as yet, no one looks at or restores that saved context
8609 + os::Posix::ucontext_set_pc(uc, stub);
8610 + return true;
8613 + return false;
8616 +void os::print_context(outputStream *st, const void *context) {
8617 + if (context == NULL) return;
8619 + const ucontext_t *uc = (const ucontext_t*)context;
8620 + st->print_cr("Registers:");
8621 +#ifdef AMD64
8622 + st->print( "RAX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RAX]);
8623 + st->print(", RBX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RBX]);
8624 + st->print(", RCX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RCX]);
8625 + st->print(", RDX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RDX]);
8626 + st->cr();
8627 + st->print( "RSP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RSP]);
8628 + st->print(", RBP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RBP]);
8629 + st->print(", RSI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RSI]);
8630 + st->print(", RDI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RDI]);
8631 + st->cr();
8632 + st->print( "R8 =" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R8]);
8633 + st->print(", R9 =" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R9]);
8634 + st->print(", R10=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R10]);
8635 + st->print(", R11=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R11]);
8636 + st->cr();
8637 + st->print( "R12=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R12]);
8638 + st->print(", R13=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R13]);
8639 + st->print(", R14=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R14]);
8640 + st->print(", R15=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R15]);
8641 + st->cr();
8642 + st->print( "RIP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RIP]);
8643 + st->print(", RFLAGS=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RFL]);
8644 +#else
8645 + st->print( "EAX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EAX]);
8646 + st->print(", EBX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EBX]);
8647 + st->print(", ECX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[ECX]);
8648 + st->print(", EDX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EDX]);
8649 + st->cr();
8650 + st->print( "ESP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[UESP]);
8651 + st->print(", EBP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EBP]);
8652 + st->print(", ESI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[ESI]);
8653 + st->print(", EDI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EDI]);
8654 + st->cr();
8655 + st->print( "EIP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EIP]);
8656 + st->print(", EFLAGS=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EFL]);
8657 +#endif // AMD64
8658 + st->cr();
8659 + st->cr();
8662 +void os::print_tos_pc(outputStream *st, const void *context) {
8663 + if (context == NULL) return;
8665 + const ucontext_t* uc = (const ucontext_t*)context;
8667 + intptr_t *sp = (intptr_t *)os::Solaris::ucontext_get_sp(uc);
8668 + st->print_cr("Top of Stack: (sp=" INTPTR_FORMAT ")", (intptr_t)sp);
8669 + print_hex_dump(st, (address)sp, (address)(sp + 8*sizeof(intptr_t)), sizeof(intptr_t));
8670 + st->cr();
8672 + // Note: it may be unsafe to inspect memory near pc. For example, pc may
8673 + // point to garbage if entry point in an nmethod is corrupted. Leave
8674 + // this at the end, and hope for the best.
8675 + address pc = os::Posix::ucontext_get_pc(uc);
8676 + print_instructions(st, pc, sizeof(char));
8677 + st->cr();
8680 +void os::print_register_info(outputStream *st, const void *context, int& continuation) {
8681 + const int register_count = AMD64_ONLY(16) NOT_AMD64(8);
8682 + int n = continuation;
8683 + assert(n >= 0 && n <= register_count, "Invalid continuation value");
8684 + if (context == nullptr || n == register_count) {
8685 + return;
8688 + const ucontext_t *uc = (const ucontext_t*)context;
8689 + while (n < register_count) {
8690 + // Update continuation with next index before printing location
8691 + continuation = n + 1;
8692 +# define CASE_PRINT_REG(n, str, id) case n: st->print(str); print_location(st, uc->uc_mcontext.gregs[REG_##id]);
8693 + switch (n) {
8694 +#ifdef AMD64
8695 + CASE_PRINT_REG( 0, "RAX=", RAX); break;
8696 + CASE_PRINT_REG( 1, "RBX=", RBX); break;
8697 + CASE_PRINT_REG( 2, "RCX=", RCX); break;
8698 + CASE_PRINT_REG( 3, "RDX=", RDX); break;
8699 + CASE_PRINT_REG( 4, "RSP=", RSP); break;
8700 + CASE_PRINT_REG( 5, "RBP=", RBP); break;
8701 + CASE_PRINT_REG( 6, "RSI=", RSI); break;
8702 + CASE_PRINT_REG( 7, "RDI=", RDI); break;
8703 + CASE_PRINT_REG( 8, "R8 =", R8); break;
8704 + CASE_PRINT_REG( 9, "R9 =", R9); break;
8705 + CASE_PRINT_REG(10, "R10=", R10); break;
8706 + CASE_PRINT_REG(11, "R11=", R11); break;
8707 + CASE_PRINT_REG(12, "R12=", R12); break;
8708 + CASE_PRINT_REG(13, "R13=", R13); break;
8709 + CASE_PRINT_REG(14, "R14=", R14); break;
8710 + CASE_PRINT_REG(15, "R15=", R15); break;
8711 +#else
8712 + CASE_PRINT_REG(0, "EAX=", EAX); break;
8713 + CASE_PRINT_REG(1, "EBX=", EBX); break;
8714 + CASE_PRINT_REG(2, "ECX=", ECX); break;
8715 + CASE_PRINT_REG(3, "EDX=", EDX); break;
8716 + CASE_PRINT_REG(4, "ESP=", ESP); break;
8717 + CASE_PRINT_REG(5, "EBP=", EBP); break;
8718 + CASE_PRINT_REG(6, "ESI=", ESI); break;
8719 + CASE_PRINT_REG(7, "EDI=", EDI); break;
8720 +#endif // AMD64
8722 +# undef CASE_PRINT_REG
8723 + ++n;
8728 +void os::Solaris::init_thread_fpu_state(void) {
8729 + // Nothing to do
8731 +void os::setup_fpu() {}
8733 +#ifndef PRODUCT
8734 +void os::verify_stack_alignment() {
8735 + assert(((intptr_t)os::current_stack_pointer() & (StackAlignmentInBytes-1)) == 0, "incorrect stack alignment");
8737 +#endif
8739 +int os::extra_bang_size_in_bytes() {
8740 + // JDK-8050147 requires the full cache line bang for x86.
8741 + return VM_Version::L1_line_size();
8743 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.hpp jdk22u-jdk-22.0.2-ga/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.hpp
8744 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.hpp 1970-01-01 01:00:00.000000000 +0100
8745 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.hpp 2024-08-17 19:34:03.903759987 +0200
8746 @@ -0,0 +1,55 @@
8748 + * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
8749 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8751 + * This code is free software; you can redistribute it and/or modify it
8752 + * under the terms of the GNU General Public License version 2 only, as
8753 + * published by the Free Software Foundation.
8755 + * This code is distributed in the hope that it will be useful, but WITHOUT
8756 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8757 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
8758 + * version 2 for more details (a copy is included in the LICENSE file that
8759 + * accompanied this code).
8761 + * You should have received a copy of the GNU General Public License version
8762 + * 2 along with this work; if not, write to the Free Software Foundation,
8763 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
8765 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
8766 + * or visit www.oracle.com if you need additional information or have any
8767 + * questions.
8769 + */
8771 +#ifndef OS_CPU_SOLARIS_X86_OS_SOLARIS_X86_HPP
8772 +#define OS_CPU_SOLARIS_X86_OS_SOLARIS_X86_HPP
8774 + //
8775 + // NOTE: we are back in class os here, not Solaris
8776 + //
8777 +#ifdef AMD64
8778 + static void setup_fpu() {}
8779 +#else
8780 + static int32_t (*atomic_xchg_func) (int32_t, volatile int32_t*);
8781 + static int32_t (*atomic_cmpxchg_func) (int32_t, volatile int32_t*, int32_t);
8782 + static int64_t (*atomic_cmpxchg_long_func)(int64_t, volatile int64_t*, int64_t);
8783 + static int32_t (*atomic_add_func) (int32_t, volatile int32_t*);
8785 + static int32_t atomic_xchg_bootstrap (int32_t, volatile int32_t*);
8786 + static int32_t atomic_cmpxchg_bootstrap (int32_t, volatile int32_t*, int32_t);
8787 + static int64_t atomic_cmpxchg_long_bootstrap(int64_t, volatile int64_t*, int64_t);
8788 + static int32_t atomic_add_bootstrap (int32_t, volatile int32_t*);
8790 + static void setup_fpu();
8791 +#endif // AMD64
8793 + static jlong rdtsc();
8795 + static bool is_allocatable(size_t bytes);
8797 + // Used to register dynamic code cache area with the OS
8798 + // Note: Currently only used in 64 bit Windows implementations
8799 + static bool register_code_area(char *low, char *high) { return true; }
8801 +#endif // OS_CPU_SOLARIS_X86_OS_SOLARIS_X86_HPP
8802 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.inline.hpp jdk22u-jdk-22.0.2-ga/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.inline.hpp
8803 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.inline.hpp 1970-01-01 01:00:00.000000000 +0100
8804 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.inline.hpp 2024-08-17 19:34:03.904028056 +0200
8805 @@ -0,0 +1,39 @@
8807 + * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
8808 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8810 + * This code is free software; you can redistribute it and/or modify it
8811 + * under the terms of the GNU General Public License version 2 only, as
8812 + * published by the Free Software Foundation.
8814 + * This code is distributed in the hope that it will be useful, but WITHOUT
8815 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8816 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
8817 + * version 2 for more details (a copy is included in the LICENSE file that
8818 + * accompanied this code).
8820 + * You should have received a copy of the GNU General Public License version
8821 + * 2 along with this work; if not, write to the Free Software Foundation,
8822 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
8824 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
8825 + * or visit www.oracle.com if you need additional information or have any
8826 + * questions.
8828 + */
8830 +#ifndef OS_CPU_SOLARIS_X86_OS_SOLARIS_X86_INLINE_HPP
8831 +#define OS_CPU_SOLARIS_X86_OS_SOLARIS_X86_INLINE_HPP
8833 +#include "runtime/os.hpp"
8835 +// See http://www.technovelty.org/code/c/reading-rdtsc.htl for details
8836 +inline jlong os::rdtsc() {
8837 + uint64_t res;
8838 + uint32_t ts1, ts2;
8839 + __asm__ __volatile__ ("rdtsc" : "=a" (ts1), "=d" (ts2));
8840 + res = ((uint64_t)ts1 | (uint64_t)ts2 << 32);
8841 + return (jlong)res;
8844 +#endif // OS_CPU_SOLARIS_X86_OS_SOLARIS_X86_INLINE_HPP
8845 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os_cpu/solaris_x86/prefetch_solaris_x86.inline.hpp jdk22u-jdk-22.0.2-ga/src/hotspot/os_cpu/solaris_x86/prefetch_solaris_x86.inline.hpp
8846 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os_cpu/solaris_x86/prefetch_solaris_x86.inline.hpp 1970-01-01 01:00:00.000000000 +0100
8847 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/os_cpu/solaris_x86/prefetch_solaris_x86.inline.hpp 2024-08-17 19:34:03.904288349 +0200
8848 @@ -0,0 +1,42 @@
8850 + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
8851 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8853 + * This code is free software; you can redistribute it and/or modify it
8854 + * under the terms of the GNU General Public License version 2 only, as
8855 + * published by the Free Software Foundation.
8857 + * This code is distributed in the hope that it will be useful, but WITHOUT
8858 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8859 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
8860 + * version 2 for more details (a copy is included in the LICENSE file that
8861 + * accompanied this code).
8863 + * You should have received a copy of the GNU General Public License version
8864 + * 2 along with this work; if not, write to the Free Software Foundation,
8865 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
8867 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
8868 + * or visit www.oracle.com if you need additional information or have any
8869 + * questions.
8871 + */
8873 +#ifndef OS_CPU_SOLARIS_X86_PREFETCH_SOLARIS_X86_INLINE_HPP
8874 +#define OS_CPU_SOLARIS_X86_PREFETCH_SOLARIS_X86_INLINE_HPP
8876 +#include "runtime/prefetch.hpp"
8878 +inline void Prefetch::read (const void *loc, intx interval) {
8879 +#ifdef AMD64
8880 + __asm__ ("prefetcht0 (%0,%1,1)" : : "r" (loc), "r" (interval));
8881 +#endif // AMD64
8884 +inline void Prefetch::write(void *loc, intx interval) {
8885 +#ifdef AMD64
8886 + __asm__ ("prefetcht0 (%0,%1,1)" : : "r" (loc), "r" (interval));
8887 +#endif // AMD64
8890 +#endif // OS_CPU_SOLARIS_X86_PREFETCH_SOLARIS_X86_INLINE_HPP
8891 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os_cpu/solaris_x86/solaris_x86_64.S jdk22u-jdk-22.0.2-ga/src/hotspot/os_cpu/solaris_x86/solaris_x86_64.S
8892 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os_cpu/solaris_x86/solaris_x86_64.S 1970-01-01 01:00:00.000000000 +0100
8893 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/os_cpu/solaris_x86/solaris_x86_64.S 2024-08-17 19:34:03.904705030 +0200
8894 @@ -0,0 +1,386 @@
8896 +# Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
8897 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8899 +# This code is free software; you can redistribute it and/or modify it
8900 +# under the terms of the GNU General Public License version 2 only, as
8901 +# published by the Free Software Foundation.
8903 +# This code is distributed in the hope that it will be useful, but WITHOUT
8904 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8905 +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
8906 +# version 2 for more details (a copy is included in the LICENSE file that
8907 +# accompanied this code).
8909 +# You should have received a copy of the GNU General Public License version
8910 +# 2 along with this work; if not, write to the Free Software Foundation,
8911 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
8913 +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
8914 +# or visit www.oracle.com if you need additional information or have any
8915 +# questions.
8918 + .globl fs_load
8919 + .globl fs_thread
8921 + ## NOTE WELL! The _Copy functions are called directly
8922 + ## from server-compiler-generated code via CallLeafNoFP,
8923 + ## which means that they *must* either not use floating
8924 + ## point or use it in the same manner as does the server
8925 + ## compiler.
8927 + .globl _Copy_arrayof_conjoint_bytes
8928 + .globl _Copy_conjoint_jshorts_atomic
8929 + .globl _Copy_arrayof_conjoint_jshorts
8930 + .globl _Copy_conjoint_jints_atomic
8931 + .globl _Copy_arrayof_conjoint_jints
8932 + .globl _Copy_conjoint_jlongs_atomic
8933 + .globl _Copy_arrayof_conjoint_jlongs
8935 + .section .text,"ax"
8937 + # Fast thread accessors, used by threadLS_solaris_amd64.cpp
8938 + .align 16
8939 +fs_load:
8940 + movq %fs:(%rdi),%rax
8941 + ret
8943 + .align 16
8944 +fs_thread:
8945 + movq %fs:0x0,%rax
8946 + ret
8948 + .globl SpinPause
8949 + .align 16
8950 +SpinPause:
8951 + rep
8952 + nop
8953 + movq $1, %rax
8954 + ret
8957 + # Support for void Copy::arrayof_conjoint_bytes(void* from,
8958 + # void* to,
8959 + # size_t count)
8960 + # rdi - from
8961 + # rsi - to
8962 + # rdx - count, treated as ssize_t
8964 + .align 16
8965 +_Copy_arrayof_conjoint_bytes:
8966 + movq %rdx,%r8 # byte count
8967 + shrq $3,%rdx # qword count
8968 + cmpq %rdi,%rsi
8969 + leaq -1(%rdi,%r8,1),%rax # from + bcount*1 - 1
8970 + jbe acb_CopyRight
8971 + cmpq %rax,%rsi
8972 + jbe acb_CopyLeft
8973 +acb_CopyRight:
8974 + leaq -8(%rdi,%rdx,8),%rax # from + qcount*8 - 8
8975 + leaq -8(%rsi,%rdx,8),%rcx # to + qcount*8 - 8
8976 + negq %rdx
8977 + jmp 7f
8978 + .align 16
8979 +1: movq 8(%rax,%rdx,8),%rsi
8980 + movq %rsi,8(%rcx,%rdx,8)
8981 + addq $1,%rdx
8982 + jnz 1b
8983 +2: testq $4,%r8 # check for trailing dword
8984 + jz 3f
8985 + movl 8(%rax),%esi # copy trailing dword
8986 + movl %esi,8(%rcx)
8987 + addq $4,%rax
8988 + addq $4,%rcx # original %rsi is trashed, so we
8989 + # can't use it as a base register
8990 +3: testq $2,%r8 # check for trailing word
8991 + jz 4f
8992 + movw 8(%rax),%si # copy trailing word
8993 + movw %si,8(%rcx)
8994 + addq $2,%rcx
8995 +4: testq $1,%r8 # check for trailing byte
8996 + jz 5f
8997 + movb -1(%rdi,%r8,1),%al # copy trailing byte
8998 + movb %al,8(%rcx)
8999 +5: ret
9000 + .align 16
9001 +6: movq -24(%rax,%rdx,8),%rsi
9002 + movq %rsi,-24(%rcx,%rdx,8)
9003 + movq -16(%rax,%rdx,8),%rsi
9004 + movq %rsi,-16(%rcx,%rdx,8)
9005 + movq -8(%rax,%rdx,8),%rsi
9006 + movq %rsi,-8(%rcx,%rdx,8)
9007 + movq (%rax,%rdx,8),%rsi
9008 + movq %rsi,(%rcx,%rdx,8)
9009 +7: addq $4,%rdx
9010 + jle 6b
9011 + subq $4,%rdx
9012 + jl 1b
9013 + jmp 2b
9014 +acb_CopyLeft:
9015 + testq $1,%r8 # check for trailing byte
9016 + jz 1f
9017 + movb -1(%rdi,%r8,1),%cl # copy trailing byte
9018 + movb %cl,-1(%rsi,%r8,1)
9019 + subq $1,%r8 # adjust for possible trailing word
9020 +1: testq $2,%r8 # check for trailing word
9021 + jz 2f
9022 + movw -2(%rdi,%r8,1),%cx # copy trailing word
9023 + movw %cx,-2(%rsi,%r8,1)
9024 +2: testq $4,%r8 # check for trailing dword
9025 + jz 5f
9026 + movl (%rdi,%rdx,8),%ecx # copy trailing dword
9027 + movl %ecx,(%rsi,%rdx,8)
9028 + jmp 5f
9029 + .align 16
9030 +3: movq -8(%rdi,%rdx,8),%rcx
9031 + movq %rcx,-8(%rsi,%rdx,8)
9032 + subq $1,%rdx
9033 + jnz 3b
9034 + ret
9035 + .align 16
9036 +4: movq 24(%rdi,%rdx,8),%rcx
9037 + movq %rcx,24(%rsi,%rdx,8)
9038 + movq 16(%rdi,%rdx,8),%rcx
9039 + movq %rcx,16(%rsi,%rdx,8)
9040 + movq 8(%rdi,%rdx,8),%rcx
9041 + movq %rcx,8(%rsi,%rdx,8)
9042 + movq (%rdi,%rdx,8),%rcx
9043 + movq %rcx,(%rsi,%rdx,8)
9044 +5: subq $4,%rdx
9045 + jge 4b
9046 + addq $4,%rdx
9047 + jg 3b
9048 + ret
9050 + # Support for void Copy::arrayof_conjoint_jshorts(void* from,
9051 + # void* to,
9052 + # size_t count)
9053 + # Equivalent to
9054 + # conjoint_jshorts_atomic
9056 + # If 'from' and/or 'to' are aligned on 4- or 2-byte boundaries, we
9057 + # let the hardware handle it. The tow or four words within dwords
9058 + # or qwords that span cache line boundaries will still be loaded
9059 + # and stored atomically.
9061 + # rdi - from
9062 + # rsi - to
9063 + # rdx - count, treated as ssize_t
9065 + .align 16
9066 +_Copy_arrayof_conjoint_jshorts:
9067 +_Copy_conjoint_jshorts_atomic:
9068 + movq %rdx,%r8 # word count
9069 + shrq $2,%rdx # qword count
9070 + cmpq %rdi,%rsi
9071 + leaq -2(%rdi,%r8,2),%rax # from + wcount*2 - 2
9072 + jbe acs_CopyRight
9073 + cmpq %rax,%rsi
9074 + jbe acs_CopyLeft
9075 +acs_CopyRight:
9076 + leaq -8(%rdi,%rdx,8),%rax # from + qcount*8 - 8
9077 + leaq -8(%rsi,%rdx,8),%rcx # to + qcount*8 - 8
9078 + negq %rdx
9079 + jmp 6f
9080 +1: movq 8(%rax,%rdx,8),%rsi
9081 + movq %rsi,8(%rcx,%rdx,8)
9082 + addq $1,%rdx
9083 + jnz 1b
9084 +2: testq $2,%r8 # check for trailing dword
9085 + jz 3f
9086 + movl 8(%rax),%esi # copy trailing dword
9087 + movl %esi,8(%rcx)
9088 + addq $4,%rcx # original %rsi is trashed, so we
9089 + # can't use it as a base register
9090 +3: testq $1,%r8 # check for trailing word
9091 + jz 4f
9092 + movw -2(%rdi,%r8,2),%si # copy trailing word
9093 + movw %si,8(%rcx)
9094 +4: ret
9095 + .align 16
9096 +5: 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 +6: addq $4,%rdx
9105 + jle 5b
9106 + subq $4,%rdx
9107 + jl 1b
9108 + jmp 2b
9109 +acs_CopyLeft:
9110 + testq $1,%r8 # check for trailing word
9111 + jz 1f
9112 + movw -2(%rdi,%r8,2),%cx # copy trailing word
9113 + movw %cx,-2(%rsi,%r8,2)
9114 +1: testq $2,%r8 # check for trailing dword
9115 + jz 4f
9116 + movl (%rdi,%rdx,8),%ecx # copy trailing dword
9117 + movl %ecx,(%rsi,%rdx,8)
9118 + jmp 4f
9119 +2: movq -8(%rdi,%rdx,8),%rcx
9120 + movq %rcx,-8(%rsi,%rdx,8)
9121 + subq $1,%rdx
9122 + jnz 2b
9123 + ret
9124 + .align 16
9125 +3: movq 24(%rdi,%rdx,8),%rcx
9126 + movq %rcx,24(%rsi,%rdx,8)
9127 + movq 16(%rdi,%rdx,8),%rcx
9128 + movq %rcx,16(%rsi,%rdx,8)
9129 + movq 8(%rdi,%rdx,8),%rcx
9130 + movq %rcx,8(%rsi,%rdx,8)
9131 + movq (%rdi,%rdx,8),%rcx
9132 + movq %rcx,(%rsi,%rdx,8)
9133 +4: subq $4,%rdx
9134 + jge 3b
9135 + addq $4,%rdx
9136 + jg 2b
9137 + ret
9139 + # Support for void Copy::arrayof_conjoint_jints(jint* from,
9140 + # jint* to,
9141 + # size_t count)
9142 + # Equivalent to
9143 + # conjoint_jints_atomic
9145 + # If 'from' and/or 'to' are aligned on 4-byte boundaries, we let
9146 + # the hardware handle it. The two dwords within qwords that span
9147 + # cache line boundaries will still be loaded and stored atomically.
9149 + # rdi - from
9150 + # rsi - to
9151 + # rdx - count, treated as ssize_t
9153 + .align 16
9154 +_Copy_arrayof_conjoint_jints:
9155 +_Copy_conjoint_jints_atomic:
9156 + movq %rdx,%r8 # dword count
9157 + shrq %rdx # qword count
9158 + cmpq %rdi,%rsi
9159 + leaq -4(%rdi,%r8,4),%rax # from + dcount*4 - 4
9160 + jbe aci_CopyRight
9161 + cmpq %rax,%rsi
9162 + jbe aci_CopyLeft
9163 +aci_CopyRight:
9164 + leaq -8(%rdi,%rdx,8),%rax # from + qcount*8 - 8
9165 + leaq -8(%rsi,%rdx,8),%rcx # to + qcount*8 - 8
9166 + negq %rdx
9167 + jmp 5f
9168 + .align 16
9169 +1: movq 8(%rax,%rdx,8),%rsi
9170 + movq %rsi,8(%rcx,%rdx,8)
9171 + addq $1,%rdx
9172 + jnz 1b
9173 +2: testq $1,%r8 # check for trailing dword
9174 + jz 3f
9175 + movl 8(%rax),%esi # copy trailing dword
9176 + movl %esi,8(%rcx)
9177 +3: ret
9178 + .align 16
9179 +4: movq -24(%rax,%rdx,8),%rsi
9180 + movq %rsi,-24(%rcx,%rdx,8)
9181 + movq -16(%rax,%rdx,8),%rsi
9182 + movq %rsi,-16(%rcx,%rdx,8)
9183 + movq -8(%rax,%rdx,8),%rsi
9184 + movq %rsi,-8(%rcx,%rdx,8)
9185 + movq (%rax,%rdx,8),%rsi
9186 + movq %rsi,(%rcx,%rdx,8)
9187 +5: addq $4,%rdx
9188 + jle 4b
9189 + subq $4,%rdx
9190 + jl 1b
9191 + jmp 2b
9192 +aci_CopyLeft:
9193 + testq $1,%r8 # check for trailing dword
9194 + jz 3f
9195 + movl -4(%rdi,%r8,4),%ecx # copy trailing dword
9196 + movl %ecx,-4(%rsi,%r8,4)
9197 + jmp 3f
9198 +1: movq -8(%rdi,%rdx,8),%rcx
9199 + movq %rcx,-8(%rsi,%rdx,8)
9200 + subq $1,%rdx
9201 + jnz 1b
9202 + ret
9203 + .align 16
9204 +2: movq 24(%rdi,%rdx,8),%rcx
9205 + movq %rcx,24(%rsi,%rdx,8)
9206 + movq 16(%rdi,%rdx,8),%rcx
9207 + movq %rcx,16(%rsi,%rdx,8)
9208 + movq 8(%rdi,%rdx,8),%rcx
9209 + movq %rcx,8(%rsi,%rdx,8)
9210 + movq (%rdi,%rdx,8),%rcx
9211 + movq %rcx,(%rsi,%rdx,8)
9212 +3: subq $4,%rdx
9213 + jge 2b
9214 + addq $4,%rdx
9215 + jg 1b
9216 + ret
9218 + # Support for void Copy::arrayof_conjoint_jlongs(jlong* from,
9219 + # jlong* to,
9220 + # size_t count)
9221 + # Equivalent to
9222 + # conjoint_jlongs_atomic
9223 + # arrayof_conjoint_oops
9224 + # conjoint_oops_atomic
9226 + # rdi - from
9227 + # rsi - to
9228 + # rdx - count, treated as ssize_t
9230 + .align 16
9231 +_Copy_arrayof_conjoint_jlongs:
9232 +_Copy_conjoint_jlongs_atomic:
9233 + cmpq %rdi,%rsi
9234 + leaq -8(%rdi,%rdx,8),%rax # from + count*8 - 8
9235 + jbe acl_CopyRight
9236 + cmpq %rax,%rsi
9237 + jbe acl_CopyLeft
9238 +acl_CopyRight:
9239 + leaq -8(%rsi,%rdx,8),%rcx # to + count*8 - 8
9240 + negq %rdx
9241 + jmp 3f
9242 +1: movq 8(%rax,%rdx,8),%rsi
9243 + movq %rsi,8(%rcx,%rdx,8)
9244 + addq $1,%rdx
9245 + jnz 1b
9246 + ret
9247 + .align 16
9248 +2: movq -24(%rax,%rdx,8),%rsi
9249 + movq %rsi,-24(%rcx,%rdx,8)
9250 + movq -16(%rax,%rdx,8),%rsi
9251 + movq %rsi,-16(%rcx,%rdx,8)
9252 + movq -8(%rax,%rdx,8),%rsi
9253 + movq %rsi,-8(%rcx,%rdx,8)
9254 + movq (%rax,%rdx,8),%rsi
9255 + movq %rsi,(%rcx,%rdx,8)
9256 +3: addq $4,%rdx
9257 + jle 2b
9258 + subq $4,%rdx
9259 + jl 1b
9260 + ret
9261 +4: movq -8(%rdi,%rdx,8),%rcx
9262 + movq %rcx,-8(%rsi,%rdx,8)
9263 + subq $1,%rdx
9264 + jnz 4b
9265 + ret
9266 + .align 16
9267 +5: movq 24(%rdi,%rdx,8),%rcx
9268 + movq %rcx,24(%rsi,%rdx,8)
9269 + movq 16(%rdi,%rdx,8),%rcx
9270 + movq %rcx,16(%rsi,%rdx,8)
9271 + movq 8(%rdi,%rdx,8),%rcx
9272 + movq %rcx,8(%rsi,%rdx,8)
9273 + movq (%rdi,%rdx,8),%rcx
9274 + movq %rcx,(%rsi,%rdx,8)
9275 +acl_CopyLeft:
9276 + subq $4,%rdx
9277 + jge 5b
9278 + addq $4,%rdx
9279 + jg 4b
9280 + ret
9281 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os_cpu/solaris_x86/vm_version_solaris_x86.cpp jdk22u-jdk-22.0.2-ga/src/hotspot/os_cpu/solaris_x86/vm_version_solaris_x86.cpp
9282 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os_cpu/solaris_x86/vm_version_solaris_x86.cpp 1970-01-01 01:00:00.000000000 +0100
9283 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/os_cpu/solaris_x86/vm_version_solaris_x86.cpp 2024-08-17 19:34:03.905773721 +0200
9284 @@ -0,0 +1,28 @@
9286 + * Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved.
9287 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
9289 + * This code is free software; you can redistribute it and/or modify it
9290 + * under the terms of the GNU General Public License version 2 only, as
9291 + * published by the Free Software Foundation.
9293 + * This code is distributed in the hope that it will be useful, but WITHOUT
9294 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
9295 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
9296 + * version 2 for more details (a copy is included in the LICENSE file that
9297 + * accompanied this code).
9299 + * You should have received a copy of the GNU General Public License version
9300 + * 2 along with this work; if not, write to the Free Software Foundation,
9301 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
9303 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
9304 + * or visit www.oracle.com if you need additional information or have any
9305 + * questions.
9307 + */
9309 +#include "precompiled.hpp"
9310 +#include "runtime/os.hpp"
9311 +#include "runtime/vm_version.hpp"
9313 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os_cpu/solaris_x86/vmStructs_solaris_x86.hpp jdk22u-jdk-22.0.2-ga/src/hotspot/os_cpu/solaris_x86/vmStructs_solaris_x86.hpp
9314 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/os_cpu/solaris_x86/vmStructs_solaris_x86.hpp 1970-01-01 01:00:00.000000000 +0100
9315 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/os_cpu/solaris_x86/vmStructs_solaris_x86.hpp 2024-08-17 19:34:03.905519369 +0200
9316 @@ -0,0 +1,40 @@
9318 + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
9319 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
9321 + * This code is free software; you can redistribute it and/or modify it
9322 + * under the terms of the GNU General Public License version 2 only, as
9323 + * published by the Free Software Foundation.
9325 + * This code is distributed in the hope that it will be useful, but WITHOUT
9326 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
9327 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
9328 + * version 2 for more details (a copy is included in the LICENSE file that
9329 + * accompanied this code).
9331 + * You should have received a copy of the GNU General Public License version
9332 + * 2 along with this work; if not, write to the Free Software Foundation,
9333 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
9335 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
9336 + * or visit www.oracle.com if you need additional information or have any
9337 + * questions.
9339 + */
9341 +#ifndef OS_CPU_SOLARIS_X86_VMSTRUCTS_SOLARIS_X86_HPP
9342 +#define OS_CPU_SOLARIS_X86_VMSTRUCTS_SOLARIS_X86_HPP
9344 +// These are the OS and CPU-specific fields, types and integer
9345 +// constants required by the Serviceability Agent. This file is
9346 +// referenced by vmStructs.cpp.
9348 +#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)
9350 +#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)
9352 +#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
9354 +#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
9356 +#endif // OS_CPU_SOLARIS_X86_VMSTRUCTS_SOLARIS_X86_HPP
9357 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/share/c1/c1_LIR.cpp jdk22u-jdk-22.0.2-ga/src/hotspot/share/c1/c1_LIR.cpp
9358 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/share/c1/c1_LIR.cpp 2024-06-04 18:47:50.000000000 +0200
9359 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/share/c1/c1_LIR.cpp 2024-08-17 19:34:03.849386892 +0200
9360 @@ -446,6 +446,8 @@
9361 case lir_monaddr: // input and result always valid, info always invalid
9362 case lir_null_check: // input and info always valid, result always invalid
9363 case lir_move: // input and result always valid, may have info
9364 + case lir_pack64: // input and result always valid
9365 + case lir_unpack64: // input and result always valid
9367 assert(op->as_Op1() != nullptr, "must be");
9368 LIR_Op1* op1 = (LIR_Op1*)op;
9369 @@ -1726,6 +1728,8 @@
9370 case lir_convert: s = "convert"; break;
9371 case lir_alloc_object: s = "alloc_obj"; break;
9372 case lir_monaddr: s = "mon_addr"; break;
9373 + case lir_pack64: s = "pack64"; break;
9374 + case lir_unpack64: s = "unpack64"; break;
9375 // LIR_Op2
9376 case lir_cmp: s = "cmp"; break;
9377 case lir_cmp_l2i: s = "cmp_l2i"; break;
9378 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/share/c1/c1_LIR.hpp jdk22u-jdk-22.0.2-ga/src/hotspot/share/c1/c1_LIR.hpp
9379 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/share/c1/c1_LIR.hpp 2024-06-04 18:47:50.000000000 +0200
9380 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/share/c1/c1_LIR.hpp 2024-08-17 19:34:03.850198091 +0200
9381 @@ -939,6 +939,8 @@
9382 , lir_monaddr
9383 , lir_roundfp
9384 , lir_safepoint
9385 + , lir_pack64
9386 + , lir_unpack64
9387 , lir_unwind
9388 , lir_load_klass
9389 , end_op1
9390 @@ -2234,6 +2236,9 @@
9391 void logical_or (LIR_Opr left, LIR_Opr right, LIR_Opr dst) { append(new LIR_Op2(lir_logic_or, left, right, dst)); }
9392 void logical_xor (LIR_Opr left, LIR_Opr right, LIR_Opr dst) { append(new LIR_Op2(lir_logic_xor, left, right, dst)); }
9394 + void pack64(LIR_Opr src, LIR_Opr dst) { append(new LIR_Op1(lir_pack64, src, dst, T_LONG, lir_patch_none, NULL)); }
9395 + void unpack64(LIR_Opr src, LIR_Opr dst) { append(new LIR_Op1(lir_unpack64, src, dst, T_LONG, lir_patch_none, NULL)); }
9397 void null_check(LIR_Opr opr, CodeEmitInfo* info, bool deoptimize_on_null = false);
9398 void throw_exception(LIR_Opr exceptionPC, LIR_Opr exceptionOop, CodeEmitInfo* info) {
9399 append(new LIR_Op2(lir_throw, exceptionPC, exceptionOop, LIR_OprFact::illegalOpr, info));
9400 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/share/cds/classListParser.cpp jdk22u-jdk-22.0.2-ga/src/hotspot/share/cds/classListParser.cpp
9401 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/share/cds/classListParser.cpp 2024-06-04 18:47:50.000000000 +0200
9402 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/share/cds/classListParser.cpp 2024-08-17 19:34:03.850737444 +0200
9403 @@ -453,7 +453,7 @@
9404 // This function is used for loading classes for customized class loaders
9405 // during archive dumping.
9406 InstanceKlass* ClassListParser::load_class_from_source(Symbol* class_name, TRAPS) {
9407 -#if !(defined(_LP64) && (defined(LINUX) || defined(__APPLE__) || defined(_WINDOWS)))
9408 +#if !(defined(_LP64) && (defined(LINUX)|| defined(SOLARIS) || defined(__APPLE__) || defined(_WINDOWS)))
9409 // The only supported platforms are: (1) Linux/64-bit and (2) Solaris/64-bit and
9410 // (3) MacOSX/64-bit and (4) Windowss/64-bit
9411 // This #if condition should be in sync with the areCustomLoadersSupportedForCDS
9412 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/share/nmt/memTracker.cpp jdk22u-jdk-22.0.2-ga/src/hotspot/share/nmt/memTracker.cpp
9413 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/share/nmt/memTracker.cpp 2024-06-04 18:47:50.000000000 +0200
9414 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/share/nmt/memTracker.cpp 2024-08-17 19:34:03.852144362 +0200
9415 @@ -48,6 +48,12 @@
9416 #include <windows.h>
9417 #endif
9419 +#ifdef SOLARIS
9420 + volatile bool NMT_stack_walkable = false;
9421 +#else
9422 + volatile bool NMT_stack_walkable = true;
9423 +#endif
9425 NMT_TrackingLevel MemTracker::_tracking_level = NMT_unknown;
9427 MemBaseline MemTracker::_baseline;
9428 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/share/nmt/memTracker.hpp jdk22u-jdk-22.0.2-ga/src/hotspot/share/nmt/memTracker.hpp
9429 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/share/nmt/memTracker.hpp 2024-06-04 18:47:50.000000000 +0200
9430 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/share/nmt/memTracker.hpp 2024-08-17 19:34:03.852503051 +0200
9431 @@ -34,9 +34,11 @@
9432 #include "utilities/debug.hpp"
9433 #include "utilities/nativeCallStack.hpp"
9435 -#define CURRENT_PC ((MemTracker::tracking_level() == NMT_detail) ? \
9436 +extern volatile bool NMT_stack_walkable;
9438 +#define CURRENT_PC ((MemTracker::tracking_level() == NMT_detail && NMT_stack_walkable) ? \
9439 NativeCallStack(0) : FAKE_CALLSTACK)
9440 -#define CALLER_PC ((MemTracker::tracking_level() == NMT_detail) ? \
9441 +#define CALLER_PC ((MemTracker::tracking_level() == NMT_detail && NMT_stack_walkable) ? \
9442 NativeCallStack(1) : FAKE_CALLSTACK)
9444 class MemBaseline;
9445 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/share/runtime/abstract_vm_version.cpp jdk22u-jdk-22.0.2-ga/src/hotspot/share/runtime/abstract_vm_version.cpp
9446 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/share/runtime/abstract_vm_version.cpp 2024-06-04 18:47:50.000000000 +0200
9447 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/share/runtime/abstract_vm_version.cpp 2024-08-17 19:34:03.851311220 +0200
9448 @@ -169,6 +169,7 @@
9450 #define OS LINUX_ONLY("linux") \
9451 WINDOWS_ONLY("windows") \
9452 + SOLARIS_ONLY("solaris") \
9453 AIX_ONLY("aix") \
9454 BSD_ONLY("bsd")
9456 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/share/runtime/semaphore.hpp jdk22u-jdk-22.0.2-ga/src/hotspot/share/runtime/semaphore.hpp
9457 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/share/runtime/semaphore.hpp 2024-06-04 18:47:50.000000000 +0200
9458 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/share/runtime/semaphore.hpp 2024-08-17 19:34:03.851642763 +0200
9459 @@ -28,7 +28,7 @@
9460 #include "memory/allocation.hpp"
9461 #include "utilities/globalDefinitions.hpp"
9463 -#if defined(LINUX) || defined(AIX)
9464 +#if defined(LINUX) || defined(SOLARIS) || defined(AIX)
9465 # include "semaphore_posix.hpp"
9466 #else
9467 # include OS_HEADER(semaphore)
9468 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/share/services/dtraceAttacher.cpp jdk22u-jdk-22.0.2-ga/src/hotspot/share/services/dtraceAttacher.cpp
9469 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/share/services/dtraceAttacher.cpp 1970-01-01 01:00:00.000000000 +0100
9470 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/share/services/dtraceAttacher.cpp 2024-08-17 19:34:03.906139465 +0200
9471 @@ -0,0 +1,99 @@
9473 + * Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved.
9474 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
9476 + * This code is free software; you can redistribute it and/or modify it
9477 + * under the terms of the GNU General Public License version 2 only, as
9478 + * published by the Free Software Foundation.
9480 + * This code is distributed in the hope that it will be useful, but WITHOUT
9481 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
9482 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
9483 + * version 2 for more details (a copy is included in the LICENSE file that
9484 + * accompanied this code).
9486 + * You should have received a copy of the GNU General Public License version
9487 + * 2 along with this work; if not, write to the Free Software Foundation,
9488 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
9490 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
9491 + * or visit www.oracle.com if you need additional information or have any
9492 + * questions.
9494 + */
9496 +#include "precompiled.hpp"
9497 +#include "code/codeCache.hpp"
9498 +#include "memory/resourceArea.hpp"
9499 +#include "runtime/deoptimization.hpp"
9500 +#include "runtime/flags/jvmFlag.hpp"
9501 +#include "runtime/vmThread.hpp"
9502 +#include "runtime/vmOperations.hpp"
9503 +#include "services/dtraceAttacher.hpp"
9504 +#include "runtime/flags/jvmFlagAccess.hpp"
9506 +#ifdef SOLARIS
9508 +static void set_bool_flag(const char* name, bool value) {
9509 + JVMFlag* flag = JVMFlag::find_flag(name);
9510 + JVMFlagAccess::set_bool(flag, &value, JVMFlagOrigin::ATTACH_ON_DEMAND);
9513 +// Enable the "fine grained" flags.
9514 +void DTrace::enable_dprobes(int probes) {
9515 + bool changed = false;
9516 + if (!DTraceAllocProbes && (probes & DTRACE_ALLOC_PROBES)) {
9517 + set_bool_flag("DTraceAllocProbes", true);
9518 + changed = true;
9520 + if (!DTraceMethodProbes && (probes & DTRACE_METHOD_PROBES)) {
9521 + set_bool_flag("DTraceMethodProbes", true);
9522 + changed = true;
9524 + if (!DTraceMonitorProbes && (probes & DTRACE_MONITOR_PROBES)) {
9525 + set_bool_flag("DTraceMonitorProbes", true);
9526 + changed = true;
9529 + if (changed) {
9530 + // one or more flags changed, need to deoptimize
9531 + DeoptimizationScope deopt_scope;
9532 + CodeCache::mark_all_nmethods_for_deoptimization(&deopt_scope);
9533 + deopt_scope.deoptimize_marked();
9537 +// Disable the "fine grained" flags.
9538 +void DTrace::disable_dprobes(int probes) {
9539 + bool changed = false;
9540 + if (DTraceAllocProbes && (probes & DTRACE_ALLOC_PROBES)) {
9541 + set_bool_flag("DTraceAllocProbes", false);
9542 + changed = true;
9544 + if (DTraceMethodProbes && (probes & DTRACE_METHOD_PROBES)) {
9545 + set_bool_flag("DTraceMethodProbes", false);
9546 + changed = true;
9548 + if (DTraceMonitorProbes && (probes & DTRACE_MONITOR_PROBES)) {
9549 + set_bool_flag("DTraceMonitorProbes", false);
9550 + changed = true;
9552 + if (changed) {
9553 + // one or more flags changed, need to deoptimize
9554 + DeoptimizationScope deopt_scope;
9555 + CodeCache::mark_all_nmethods_for_deoptimization(&deopt_scope);
9556 + deopt_scope.deoptimize_marked();
9560 +// Do clean-up on "all door clients detached" event.
9561 +void DTrace::detach_all_clients() {
9562 + disable_dprobes(DTRACE_ALL_PROBES);
9565 +void DTrace::set_monitor_dprobes(bool flag) {
9566 + // explicit setting of DTraceMonitorProbes flag
9567 + set_bool_flag("DTraceMonitorProbes", flag);
9570 +#endif /* SOLARIS */
9571 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/share/utilities/debug.cpp jdk22u-jdk-22.0.2-ga/src/hotspot/share/utilities/debug.cpp
9572 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/share/utilities/debug.cpp 2024-06-04 18:47:50.000000000 +0200
9573 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/share/utilities/debug.cpp 2024-08-17 19:34:03.853083603 +0200
9574 @@ -609,11 +609,12 @@
9575 tty->print_cr(" findm(intptr_t pc) - finds Method*");
9576 tty->print_cr(" find(intptr_t x) - finds & prints nmethod/stub/bytecode/oop based on pointer into it");
9577 tty->print_cr(" pns(void* sp, void* fp, void* pc) - print native (i.e. mixed) stack trace. E.g.");
9578 - tty->print_cr(" pns($sp, $rbp, $pc) on Linux/amd64 or");
9579 + tty->print_cr(" pns($sp, $rbp, $pc) on Linux/amd64 and Solaris/amd64 or");
9580 tty->print_cr(" pns($sp, $ebp, $pc) on Linux/x86 or");
9581 tty->print_cr(" pns($sp, $fp, $pc) on Linux/AArch64 or");
9582 tty->print_cr(" pns($sp, 0, $pc) on Linux/ppc64 or");
9583 tty->print_cr(" pns($sp, $s8, $pc) on Linux/mips or");
9584 + tty->print_cr(" pns($sp + 0x7ff, 0, $pc) on Solaris/SPARC");
9585 tty->print_cr(" - in gdb do 'set overload-resolution off' before calling pns()");
9586 tty->print_cr(" - in dbx do 'frame 1' before calling pns()");
9587 tty->print_cr("class metadata.");
9588 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/share/utilities/globalDefinitions_gcc.hpp jdk22u-jdk-22.0.2-ga/src/hotspot/share/utilities/globalDefinitions_gcc.hpp
9589 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/share/utilities/globalDefinitions_gcc.hpp 2024-06-04 18:47:50.000000000 +0200
9590 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/share/utilities/globalDefinitions_gcc.hpp 2024-08-17 19:34:03.853572764 +0200
9591 @@ -39,15 +39,36 @@
9592 #include <stdlib.h>
9593 #include <wchar.h>
9595 +#ifdef SOLARIS
9596 +#include <ieeefp.h>
9597 +#endif // SOLARIS
9599 #include <math.h>
9600 #include <time.h>
9601 #include <fcntl.h>
9602 #include <dlfcn.h>
9603 #include <pthread.h>
9605 +#ifdef SOLARIS
9606 +#include <thread.h>
9607 +#endif // SOLARIS
9609 #include <limits.h>
9610 #include <errno.h>
9612 +#ifdef SOLARIS
9613 +#include <sys/trap.h>
9614 +#include <sys/regset.h>
9615 +#include <sys/procset.h>
9616 +#include <ucontext.h>
9617 +#include <setjmp.h>
9618 +#include <inttypes.h>
9619 +#endif // SOLARIS
9621 +# ifdef SOLARIS_MUTATOR_LIBTHREAD
9622 +# include <sys/procfs.h>
9623 +# endif
9625 #if defined(LINUX) || defined(_ALLBSD_SOURCE)
9626 #include <inttypes.h>
9627 #include <signal.h>
9628 @@ -61,6 +82,34 @@
9629 #include <sys/time.h>
9630 #endif // LINUX || _ALLBSD_SOURCE
9632 +// 4810578: varargs unsafe on 32-bit integer/64-bit pointer architectures
9633 +// When __cplusplus is defined, NULL is defined as 0 (32-bit constant) in
9634 +// system header files. On 32-bit architectures, there is no problem.
9635 +// On 64-bit architectures, defining NULL as a 32-bit constant can cause
9636 +// problems with varargs functions: C++ integral promotion rules say for
9637 +// varargs, we pass the argument 0 as an int. So, if NULL was passed to a
9638 +// varargs function it will remain 32-bits. Depending on the calling
9639 +// convention of the machine, if the argument is passed on the stack then
9640 +// only 32-bits of the "NULL" pointer may be initialized to zero. The
9641 +// other 32-bits will be garbage. If the varargs function is expecting a
9642 +// pointer when it extracts the argument, then we have a problem.
9644 +// Solution: For 64-bit architectures, redefine NULL as 64-bit constant 0.
9646 +// Note: this fix doesn't work well on Linux because NULL will be overwritten
9647 +// whenever a system header file is included. Linux handles NULL correctly
9648 +// through a special type '__null'.
9649 +#ifdef SOLARIS
9650 + #ifdef _LP64
9651 + #undef NULL
9652 + #define NULL 0L
9653 + #else
9654 + #ifndef NULL
9655 + #define NULL 0
9656 + #endif
9657 + #endif
9658 +#endif
9660 // NULL vs NULL_WORD:
9661 // On Linux NULL is defined as a special type '__null'. Assigning __null to
9662 // integer variable will cause gcc warning. Use NULL_WORD in places where a
9663 @@ -101,8 +150,52 @@
9665 #endif // !LINUX && !_ALLBSD_SOURCE
9668 +#ifdef SOLARIS
9669 +// ANSI C++ fixes
9670 +// NOTE:In the ANSI committee's continuing attempt to make each version
9671 +// of C++ incompatible with the previous version, you can no longer cast
9672 +// pointers to functions without specifying linkage unless you want to get
9673 +// warnings.
9675 +// This also means that pointers to functions can no longer be "hidden"
9676 +// in opaque types like void * because at the invocation point warnings
9677 +// will be generated. While this makes perfect sense from a type safety
9678 +// point of view it causes a lot of warnings on old code using C header
9679 +// files. Here are some typedefs to make the job of silencing warnings
9680 +// a bit easier.
9682 +// The final kick in the teeth is that you can only have extern "C" linkage
9683 +// specified at file scope. So these typedefs are here rather than in the
9684 +// .hpp for the class (os:Solaris usually) that needs them.
9686 +extern "C" {
9687 + typedef int (*int_fnP_thread_t_iP_uP_stack_tP_gregset_t)(thread_t, int*, unsigned *, stack_t*, gregset_t);
9688 + typedef int (*int_fnP_thread_t_i_gregset_t)(thread_t, int, gregset_t);
9689 + typedef int (*int_fnP_thread_t_i)(thread_t, int);
9690 + typedef int (*int_fnP_thread_t)(thread_t);
9692 + typedef int (*int_fnP_cond_tP_mutex_tP_timestruc_tP)(cond_t *cv, mutex_t *mx, timestruc_t *abst);
9693 + typedef int (*int_fnP_cond_tP_mutex_tP)(cond_t *cv, mutex_t *mx);
9695 + // typedef for missing API in libc
9696 + typedef int (*int_fnP_mutex_tP_i_vP)(mutex_t *, int, void *);
9697 + typedef int (*int_fnP_mutex_tP)(mutex_t *);
9698 + typedef int (*int_fnP_cond_tP_i_vP)(cond_t *cv, int scope, void *arg);
9699 + typedef int (*int_fnP_cond_tP)(cond_t *cv);
9701 +#endif // SOLARIS
9703 // checking for nanness
9704 -#if defined(__APPLE__)
9705 +#ifdef SOLARIS
9706 +#ifdef SPARC
9707 +inline int g_isnan(float f) { return isnanf(f); }
9708 +#else
9709 +// isnanf() broken on Intel Solaris use isnand()
9710 +inline int g_isnan(float f) { return isnand(f); }
9711 +#endif
9712 +inline int g_isnan(double f) { return isnand(f); }
9713 +#elif defined(__APPLE__)
9714 inline int g_isnan(double f) { return isnan(f); }
9715 #elif defined(LINUX) || defined(_ALLBSD_SOURCE)
9716 inline int g_isnan(float f) { return isnan(f); }
9717 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/share/utilities/macros.hpp jdk22u-jdk-22.0.2-ga/src/hotspot/share/utilities/macros.hpp
9718 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/share/utilities/macros.hpp 2024-06-04 18:47:50.000000000 +0200
9719 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/share/utilities/macros.hpp 2024-08-17 19:34:03.853991975 +0200
9720 @@ -401,6 +401,14 @@
9721 #define NOT_AIX(code) code
9722 #endif
9724 +#ifdef SOLARIS
9725 +#define SOLARIS_ONLY(code) code
9726 +#define NOT_SOLARIS(code)
9727 +#else
9728 +#define SOLARIS_ONLY(code)
9729 +#define NOT_SOLARIS(code) code
9730 +#endif
9732 #ifdef _WINDOWS
9733 #define WINDOWS_ONLY(code) code
9734 #define NOT_WINDOWS(code)
9735 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/share/utilities/ostream.cpp jdk22u-jdk-22.0.2-ga/src/hotspot/share/utilities/ostream.cpp
9736 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/share/utilities/ostream.cpp 2024-06-04 18:47:50.000000000 +0200
9737 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/share/utilities/ostream.cpp 2024-08-17 19:34:03.854506281 +0200
9738 @@ -1055,7 +1055,7 @@
9740 #ifndef PRODUCT
9742 -#if defined(LINUX) || defined(AIX) || defined(_ALLBSD_SOURCE)
9743 +#if defined(SOLARIS) || defined(LINUX) || defined(AIX) || defined(_ALLBSD_SOURCE)
9744 #include <sys/types.h>
9745 #include <sys/socket.h>
9746 #include <netinet/in.h>
9747 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/hotspot/share/utilities/vmError.cpp jdk22u-jdk-22.0.2-ga/src/hotspot/share/utilities/vmError.cpp
9748 --- jdk22u-jdk-22.0.2-ga.orig/src/hotspot/share/utilities/vmError.cpp 2024-06-04 18:47:50.000000000 +0200
9749 +++ jdk22u-jdk-22.0.2-ga/src/hotspot/share/utilities/vmError.cpp 2024-08-17 19:34:03.855271238 +0200
9750 @@ -1903,6 +1903,8 @@
9751 out.print_raw ("# Executing ");
9752 #if defined(LINUX) || defined(_ALLBSD_SOURCE)
9753 out.print_raw ("/bin/sh -c ");
9754 +#elif defined(SOLARIS)
9755 + out.print_raw ("/usr/bin/sh -c ");
9756 #elif defined(_WINDOWS)
9757 out.print_raw ("cmd /C ");
9758 #endif
9759 @@ -1967,6 +1969,8 @@
9760 tty->print("# Executing ");
9761 #if defined(LINUX)
9762 tty->print ("/bin/sh -c ");
9763 +#elif defined(SOLARIS)
9764 + tty->print ("/usr/bin/sh -c ");
9765 #endif
9766 tty->print_cr("\"%s\"...", cmd);
9768 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/share/classes/sun/net/sdp/SdpSupport.java jdk22u-jdk-22.0.2-ga/src/java.base/share/classes/sun/net/sdp/SdpSupport.java
9769 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/share/classes/sun/net/sdp/SdpSupport.java 2024-06-04 18:47:50.000000000 +0200
9770 +++ jdk22u-jdk-22.0.2-ga/src/java.base/share/classes/sun/net/sdp/SdpSupport.java 2024-08-17 19:34:03.855743694 +0200
9771 @@ -39,7 +39,7 @@
9774 public final class SdpSupport {
9775 - private static final boolean isSupported = OperatingSystem.isLinux();
9776 + private static final boolean isSupported = (OperatingSystem.isSolaris() || OperatingSystem.isLinux());
9777 private static final JavaIOFileDescriptorAccess fdAccess =
9778 SharedSecrets.getJavaIOFileDescriptorAccess();
9780 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/share/classes/sun/nio/ch/Net.java jdk22u-jdk-22.0.2-ga/src/java.base/share/classes/sun/nio/ch/Net.java
9781 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/share/classes/sun/nio/ch/Net.java 2024-06-04 18:47:50.000000000 +0200
9782 +++ jdk22u-jdk-22.0.2-ga/src/java.base/share/classes/sun/nio/ch/Net.java 2024-08-17 19:34:03.856363336 +0200
9783 @@ -512,7 +512,7 @@
9784 private static native boolean isReusePortAvailable0();
9787 - * Returns 1 for Windows and -1 for Linux/Mac OS
9788 + * Returns 1 for Windows and -1 for Solaris/Linux/Mac OS
9790 private static native int isExclusiveBindAvailable();
9792 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/share/classes/sun/nio/ch/SocketOptionRegistry.java.template jdk22u-jdk-22.0.2-ga/src/java.base/share/classes/sun/nio/ch/SocketOptionRegistry.java.template
9793 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/share/classes/sun/nio/ch/SocketOptionRegistry.java.template 2024-06-04 18:47:50.000000000 +0200
9794 +++ jdk22u-jdk-22.0.2-ga/src/java.base/share/classes/sun/nio/ch/SocketOptionRegistry.java.template 2024-08-17 19:34:03.856793127 +0200
9795 @@ -43,6 +43,8 @@
9796 #define SO_REUSEPORT 0
9797 #elif defined(__linux__)
9798 #define SO_REUSEPORT 15
9799 +#elif defined(__solaris__)
9800 +#define SO_REUSEPORT 0x100e
9801 #elif defined(AIX) || defined(MACOSX)
9802 #define SO_REUSEPORT 0x0200
9803 #else
9804 @@ -50,6 +52,10 @@
9805 #endif
9806 #endif
9808 +/* On Solaris, "sun" is defined as a macro. Undefine to make package
9809 + declaration valid */
9810 +#undef sun
9812 /* To be able to name the Java constants the same as the C constants without
9813 having the preprocessor rewrite those identifiers, add PREFIX_ to all
9814 identifiers matching a C constant. The PREFIX_ is filtered out in the
9815 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/share/conf/security/java.security jdk22u-jdk-22.0.2-ga/src/java.base/share/conf/security/java.security
9816 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/share/conf/security/java.security 2024-06-04 18:47:50.000000000 +0200
9817 +++ jdk22u-jdk-22.0.2-ga/src/java.base/share/conf/security/java.security 2024-08-17 19:34:03.857478089 +0200
9818 @@ -83,7 +83,11 @@
9819 #ifdef macosx
9820 security.provider.tbd=Apple
9821 #endif
9822 +#ifdef solaris
9823 +security.provider.tbd=SunPKCS11 ${java.home}/conf/security/sunpkcs11-solaris.cfg
9824 +#else
9825 security.provider.tbd=SunPKCS11
9826 +#endif
9829 # A list of preferred providers for specific algorithms. These providers will
9830 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/share/native/libjli/jli_util.h jdk22u-jdk-22.0.2-ga/src/java.base/share/native/libjli/jli_util.h
9831 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/share/native/libjli/jli_util.h 2024-06-04 18:47:50.000000000 +0200
9832 +++ jdk22u-jdk-22.0.2-ga/src/java.base/share/native/libjli/jli_util.h 2024-08-17 19:34:03.857866422 +0200
9833 @@ -100,6 +100,9 @@
9834 #define JLI_StrCaseCmp(p1, p2) strcasecmp((p1), (p2))
9835 #define JLI_StrNCaseCmp(p1, p2, p3) strncasecmp((p1), (p2), (p3))
9836 #define JLI_Open open
9837 +#ifdef __solaris__
9838 +#define JLI_Lseek llseek
9839 +#endif
9840 #ifdef __linux__
9841 #define _LARGFILE64_SOURCE
9842 #define JLI_Lseek lseek64
9843 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/share/native/libnet/net_util.c jdk22u-jdk-22.0.2-ga/src/java.base/share/native/libnet/net_util.c
9844 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/share/native/libnet/net_util.c 2024-06-04 18:47:50.000000000 +0200
9845 +++ jdk22u-jdk-22.0.2-ga/src/java.base/share/native/libnet/net_util.c 2024-08-17 19:34:03.858287752 +0200
9846 @@ -81,6 +81,7 @@
9848 /* check if SO_REUSEPORT is supported on this platform */
9849 REUSEPORT_available = reuseport_supported(IPv6_available);
9850 + parseExclusiveBindProperty(env);
9852 return JNI_VERSION_1_2;
9854 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/share/native/libnet/net_util.h jdk22u-jdk-22.0.2-ga/src/java.base/share/native/libnet/net_util.h
9855 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/share/native/libnet/net_util.h 2024-06-04 18:47:50.000000000 +0200
9856 +++ jdk22u-jdk-22.0.2-ga/src/java.base/share/native/libnet/net_util.h 2024-08-17 19:34:03.858664448 +0200
9857 @@ -142,6 +142,8 @@
9858 JNIEXPORT jobject JNICALL
9859 NET_SockaddrToInetAddress(JNIEnv *env, SOCKETADDRESS *sa, int *port);
9861 +void parseExclusiveBindProperty(JNIEnv *env);
9863 JNIEXPORT jint JNICALL NET_GetPortFromSockaddr(SOCKETADDRESS *sa);
9865 JNIEXPORT jboolean JNICALL
9866 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java jdk22u-jdk-22.0.2-ga/src/java.base/solaris/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java
9867 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java 1970-01-01 01:00:00.000000000 +0100
9868 +++ jdk22u-jdk-22.0.2-ga/src/java.base/solaris/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java 2024-08-17 19:34:03.906639703 +0200
9869 @@ -0,0 +1,47 @@
9871 + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
9872 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
9874 + * This code is free software; you can redistribute it and/or modify it
9875 + * under the terms of the GNU General Public License version 2 only, as
9876 + * published by the Free Software Foundation. Oracle designates this
9877 + * particular file as subject to the "Classpath" exception as provided
9878 + * by Oracle in the LICENSE file that accompanied this code.
9880 + * This code is distributed in the hope that it will be useful, but WITHOUT
9881 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
9882 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
9883 + * version 2 for more details (a copy is included in the LICENSE file that
9884 + * accompanied this code).
9886 + * You should have received a copy of the GNU General Public License version
9887 + * 2 along with this work; if not, write to the Free Software Foundation,
9888 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
9890 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
9891 + * or visit www.oracle.com if you need additional information or have any
9892 + * questions.
9893 + */
9895 +package sun.nio.ch;
9897 +import java.nio.channels.spi.AsynchronousChannelProvider;
9899 +/**
9900 + * Creates this platform's default AsynchronousChannelProvider
9901 + */
9903 +public class DefaultAsynchronousChannelProvider {
9905 + /**
9906 + * Prevent instantiation.
9907 + */
9908 + private DefaultAsynchronousChannelProvider() { }
9910 + /**
9911 + * Returns the default AsynchronousChannelProvider.
9912 + */
9913 + public static AsynchronousChannelProvider create() {
9914 + return new SolarisAsynchronousChannelProvider();
9917 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/classes/sun/nio/ch/DefaultSelectorProvider.java jdk22u-jdk-22.0.2-ga/src/java.base/solaris/classes/sun/nio/ch/DefaultSelectorProvider.java
9918 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/classes/sun/nio/ch/DefaultSelectorProvider.java 1970-01-01 01:00:00.000000000 +0100
9919 +++ jdk22u-jdk-22.0.2-ga/src/java.base/solaris/classes/sun/nio/ch/DefaultSelectorProvider.java 2024-08-17 19:34:03.906924465 +0200
9920 @@ -0,0 +1,54 @@
9922 + * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
9923 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
9925 + * This code is free software; you can redistribute it and/or modify it
9926 + * under the terms of the GNU General Public License version 2 only, as
9927 + * published by the Free Software Foundation. Oracle designates this
9928 + * particular file as subject to the "Classpath" exception as provided
9929 + * by Oracle in the LICENSE file that accompanied this code.
9931 + * This code is distributed in the hope that it will be useful, but WITHOUT
9932 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
9933 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
9934 + * version 2 for more details (a copy is included in the LICENSE file that
9935 + * accompanied this code).
9937 + * You should have received a copy of the GNU General Public License version
9938 + * 2 along with this work; if not, write to the Free Software Foundation,
9939 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
9941 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
9942 + * or visit www.oracle.com if you need additional information or have any
9943 + * questions.
9944 + */
9946 +package sun.nio.ch;
9948 +import java.security.AccessController;
9949 +import java.security.PrivilegedAction;
9951 +/**
9952 + * Creates this platform's default SelectorProvider
9953 + */
9955 +@SuppressWarnings("removal")
9956 +public class DefaultSelectorProvider {
9957 + private static final SelectorProviderImpl INSTANCE;
9958 + static {
9959 + PrivilegedAction<SelectorProviderImpl> pa = DevPollSelectorProvider::new;
9960 + INSTANCE = AccessController.doPrivileged(pa);
9963 + /**
9964 + * Prevent instantiation.
9965 + */
9966 + private DefaultSelectorProvider() { }
9968 + /**
9969 + * Returns the default SelectorProvider implementation.
9970 + */
9971 + public static SelectorProviderImpl get() {
9972 + return INSTANCE;
9975 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java jdk22u-jdk-22.0.2-ga/src/java.base/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java
9976 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java 1970-01-01 01:00:00.000000000 +0100
9977 +++ jdk22u-jdk-22.0.2-ga/src/java.base/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java 2024-08-17 19:34:03.907231451 +0200
9978 @@ -0,0 +1,127 @@
9980 + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
9981 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
9983 + * This code is free software; you can redistribute it and/or modify it
9984 + * under the terms of the GNU General Public License version 2 only, as
9985 + * published by the Free Software Foundation. Oracle designates this
9986 + * particular file as subject to the "Classpath" exception as provided
9987 + * by Oracle in the LICENSE file that accompanied this code.
9989 + * This code is distributed in the hope that it will be useful, but WITHOUT
9990 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
9991 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
9992 + * version 2 for more details (a copy is included in the LICENSE file that
9993 + * accompanied this code).
9995 + * You should have received a copy of the GNU General Public License version
9996 + * 2 along with this work; if not, write to the Free Software Foundation,
9997 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
9999 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
10000 + * or visit www.oracle.com if you need additional information or have any
10001 + * questions.
10002 + */
10004 +package sun.nio.ch;
10006 +import java.io.IOException;
10008 +/**
10009 + * Manipulates a native array of pollfd structs on Solaris:
10011 + * typedef struct pollfd {
10012 + * int fd;
10013 + * short events;
10014 + * short revents;
10015 + * } pollfd_t;
10017 + * @author Mike McCloskey
10018 + * @since 1.4
10019 + */
10021 +class DevPollArrayWrapper {
10023 + // special event to remove a file descriptor from the driver
10024 + static final short POLLREMOVE = 0x0800;
10026 + // struct pollfd constants
10027 + static final short SIZE_POLLFD = 8;
10028 + static final short FD_OFFSET = 0;
10029 + static final short EVENT_OFFSET = 4;
10030 + static final short REVENT_OFFSET = 6;
10032 + // maximum number of pollfd structure to poll or update at a time
10033 + // dpwrite/ioctl(DP_POLL) allows up to file descriptor limit minus 1
10034 + static final int NUM_POLLFDS = Math.min(IOUtil.fdLimit()-1, 1024);
10036 + // The pollfd array for results from devpoll driver
10037 + private final AllocatedNativeObject pollArray;
10039 + // Base address of the native pollArray
10040 + private final long pollArrayAddress;
10042 + // The fd of the devpoll driver
10043 + private int wfd;
10045 + DevPollArrayWrapper() throws IOException {
10046 + this.wfd = init();
10048 + int allocationSize = NUM_POLLFDS * SIZE_POLLFD;
10049 + this.pollArray = new AllocatedNativeObject(allocationSize, true);
10050 + this.pollArrayAddress = pollArray.address();
10053 + void close() throws IOException {
10054 + FileDispatcherImpl.closeIntFD(wfd);
10055 + pollArray.free();
10058 + void register(int fd, int ops) throws IOException {
10059 + register(wfd, fd, ops);
10062 + void registerMultiple(int numfds) throws IOException {
10063 + registerMultiple(wfd, pollArrayAddress, numfds);
10066 + int poll(long timeout) throws IOException {
10067 + return poll0(pollArrayAddress, NUM_POLLFDS, timeout, wfd);
10070 + int getDescriptor(int i) {
10071 + int offset = SIZE_POLLFD * i + FD_OFFSET;
10072 + return pollArray.getInt(offset);
10075 + short getEventOps(int i) {
10076 + int offset = SIZE_POLLFD * i + EVENT_OFFSET;
10077 + return pollArray.getShort(offset);
10080 + short getReventOps(int i) {
10081 + int offset = SIZE_POLLFD * i + REVENT_OFFSET;
10082 + return pollArray.getShort(offset);
10085 + /**
10086 + * Updates the pollfd structure at the given index
10087 + */
10088 + void putPollFD(int index, int fd, short event) {
10089 + int structIndex = SIZE_POLLFD * index;
10090 + pollArray.putInt(structIndex + FD_OFFSET, fd);
10091 + pollArray.putShort(structIndex + EVENT_OFFSET, event);
10092 + pollArray.putShort(structIndex + REVENT_OFFSET, (short)0);
10095 + private native int init() throws IOException;
10096 + private native void register(int wfd, int fd, int mask) throws IOException;
10097 + private native void registerMultiple(int wfd, long address, int len)
10098 + throws IOException;
10099 + private native int poll0(long pollAddress, int numfds, long timeout, int wfd)
10100 + throws IOException;
10102 + static {
10103 + IOUtil.load();
10106 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java jdk22u-jdk-22.0.2-ga/src/java.base/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java
10107 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java 1970-01-01 01:00:00.000000000 +0100
10108 +++ jdk22u-jdk-22.0.2-ga/src/java.base/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java 2024-08-17 19:34:03.907598740 +0200
10109 @@ -0,0 +1,263 @@
10111 + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
10112 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
10114 + * This code is free software; you can redistribute it and/or modify it
10115 + * under the terms of the GNU General Public License version 2 only, as
10116 + * published by the Free Software Foundation. Oracle designates this
10117 + * particular file as subject to the "Classpath" exception as provided
10118 + * by Oracle in the LICENSE file that accompanied this code.
10120 + * This code is distributed in the hope that it will be useful, but WITHOUT
10121 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10122 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
10123 + * version 2 for more details (a copy is included in the LICENSE file that
10124 + * accompanied this code).
10126 + * You should have received a copy of the GNU General Public License version
10127 + * 2 along with this work; if not, write to the Free Software Foundation,
10128 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
10130 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
10131 + * or visit www.oracle.com if you need additional information or have any
10132 + * questions.
10133 + */
10135 +package sun.nio.ch;
10137 +import java.io.IOException;
10138 +import java.nio.channels.ClosedSelectorException;
10139 +import java.nio.channels.SelectionKey;
10140 +import java.nio.channels.Selector;
10141 +import java.nio.channels.spi.SelectorProvider;
10142 +import java.util.ArrayDeque;
10143 +import java.util.Deque;
10144 +import java.util.HashMap;
10145 +import java.util.Map;
10146 +import java.util.concurrent.TimeUnit;
10147 +import java.util.function.Consumer;
10149 +import static sun.nio.ch.DevPollArrayWrapper.NUM_POLLFDS;
10150 +import static sun.nio.ch.DevPollArrayWrapper.POLLREMOVE;
10152 +/**
10153 + * Solaris /dev/poll based Selector implementation
10154 + */
10156 +class DevPollSelectorImpl
10157 + extends SelectorImpl
10159 + // provides access to /dev/poll driver
10160 + private final DevPollArrayWrapper pollWrapper;
10162 + // file descriptors used for interrupt
10163 + private final int fd0;
10164 + private final int fd1;
10166 + // maps file descriptor to selection key, synchronize on selector
10167 + private final Map<Integer, SelectionKeyImpl> fdToKey = new HashMap<>();
10169 + // pending new registrations/updates, queued by setEventOps
10170 + private final Object updateLock = new Object();
10171 + private final Deque<SelectionKeyImpl> updateKeys = new ArrayDeque<>();
10173 + // interrupt triggering and clearing
10174 + private final Object interruptLock = new Object();
10175 + private boolean interruptTriggered;
10177 + DevPollSelectorImpl(SelectorProvider sp) throws IOException {
10178 + super(sp);
10179 + this.pollWrapper = new DevPollArrayWrapper();
10180 + try {
10181 + long fds = IOUtil.makePipe(false);
10182 + this.fd0 = (int) (fds >>> 32);
10183 + this.fd1 = (int) fds;
10184 + } catch (IOException ioe) {
10185 + pollWrapper.close();
10186 + throw ioe;
10189 + // register one end of the socket pair for wakeups
10190 + pollWrapper.register(fd0, Net.POLLIN);
10193 + private void ensureOpen() {
10194 + if (!isOpen())
10195 + throw new ClosedSelectorException();
10198 + @Override
10199 + protected int doSelect(Consumer<SelectionKey> action, long timeout)
10200 + throws IOException
10202 + assert Thread.holdsLock(this);
10204 + long to = timeout;
10205 + boolean blocking = (to != 0);
10206 + boolean timedPoll = (to > 0);
10208 + int numEntries;
10209 + processUpdateQueue();
10210 + processDeregisterQueue();
10211 + try {
10212 + begin(blocking);
10214 + do {
10215 + long startTime = timedPoll ? System.nanoTime() : 0;
10216 + numEntries = pollWrapper.poll(to);
10217 + if (numEntries == IOStatus.INTERRUPTED && timedPoll) {
10218 + // timed poll interrupted so need to adjust timeout
10219 + long adjust = System.nanoTime() - startTime;
10220 + to -= TimeUnit.MILLISECONDS.convert(adjust, TimeUnit.NANOSECONDS);
10221 + if (to <= 0) {
10222 + // timeout expired so no retry
10223 + numEntries = 0;
10226 + } while (numEntries == IOStatus.INTERRUPTED);
10227 + assert IOStatus.check(numEntries);
10229 + } finally {
10230 + end(blocking);
10232 + processDeregisterQueue();
10233 + return processEvents(numEntries, action);
10236 + /**
10237 + * Process changes to the interest ops.
10238 + */
10239 + private void processUpdateQueue() throws IOException {
10240 + assert Thread.holdsLock(this);
10242 + synchronized (updateLock) {
10243 + SelectionKeyImpl ski;
10245 + // Translate the queued updates to changes to the set of monitored
10246 + // file descriptors. The changes are written to the /dev/poll driver
10247 + // in bulk.
10248 + int index = 0;
10249 + while ((ski = updateKeys.pollFirst()) != null) {
10250 + if (ski.isValid()) {
10251 + int fd = ski.getFDVal();
10252 + // add to fdToKey if needed
10253 + SelectionKeyImpl previous = fdToKey.putIfAbsent(fd, ski);
10254 + assert (previous == null) || (previous == ski);
10256 + int newEvents = ski.translateInterestOps();
10257 + int registeredEvents = ski.registeredEvents();
10258 + if (newEvents != registeredEvents) {
10259 + if (registeredEvents != 0)
10260 + pollWrapper.putPollFD(index++, fd, POLLREMOVE);
10261 + if (newEvents != 0)
10262 + pollWrapper.putPollFD(index++, fd, (short)newEvents);
10263 + ski.registeredEvents(newEvents);
10265 + // write to /dev/poll
10266 + if (index > (NUM_POLLFDS-2)) {
10267 + pollWrapper.registerMultiple(index);
10268 + index = 0;
10274 + // write any remaining changes
10275 + if (index > 0)
10276 + pollWrapper.registerMultiple(index);
10280 + /**
10281 + * Process the polled events.
10282 + * If the interrupt fd has been selected, drain it and clear the interrupt.
10283 + */
10284 + private int processEvents(int numEntries, Consumer<SelectionKey> action)
10285 + throws IOException
10287 + assert Thread.holdsLock(this);
10289 + boolean interrupted = false;
10290 + int numKeysUpdated = 0;
10291 + for (int i=0; i<numEntries; i++) {
10292 + int fd = pollWrapper.getDescriptor(i);
10293 + if (fd == fd0) {
10294 + interrupted = true;
10295 + } else {
10296 + SelectionKeyImpl ski = fdToKey.get(fd);
10297 + if (ski != null) {
10298 + int rOps = pollWrapper.getReventOps(i);
10299 + numKeysUpdated += processReadyEvents(rOps, ski, action);
10304 + if (interrupted) {
10305 + clearInterrupt();
10308 + return numKeysUpdated;
10311 + @Override
10312 + protected void implClose() throws IOException {
10313 + assert !isOpen();
10314 + assert Thread.holdsLock(this);
10316 + // prevent further wakeup
10317 + synchronized (interruptLock) {
10318 + interruptTriggered = true;
10321 + pollWrapper.close();
10322 + FileDispatcherImpl.closeIntFD(fd0);
10323 + FileDispatcherImpl.closeIntFD(fd1);
10327 + @Override
10328 + protected void implDereg(SelectionKeyImpl ski) throws IOException {
10329 + assert !ski.isValid();
10330 + assert Thread.holdsLock(this);
10332 + int fd = ski.getFDVal();
10333 + if (fdToKey.remove(fd) != null) {
10334 + if (ski.registeredEvents() != 0) {
10335 + pollWrapper.register(fd, POLLREMOVE);
10336 + ski.registeredEvents(0);
10338 + } else {
10339 + assert ski.registeredEvents() == 0;
10343 + @Override
10344 + public void setEventOps(SelectionKeyImpl ski) {
10345 + ensureOpen();
10346 + synchronized (updateLock) {
10347 + updateKeys.addLast(ski);
10351 + @Override
10352 + public Selector wakeup() {
10353 + synchronized (interruptLock) {
10354 + if (!interruptTriggered) {
10355 + try {
10356 + IOUtil.write1(fd1, (byte)0);
10357 + } catch (IOException ioe) {
10358 + throw new InternalError(ioe);
10360 + interruptTriggered = true;
10363 + return this;
10366 + private void clearInterrupt() throws IOException {
10367 + synchronized (interruptLock) {
10368 + IOUtil.drain(fd0);
10369 + interruptTriggered = false;
10373 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/classes/sun/nio/ch/DevPollSelectorProvider.java jdk22u-jdk-22.0.2-ga/src/java.base/solaris/classes/sun/nio/ch/DevPollSelectorProvider.java
10374 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/classes/sun/nio/ch/DevPollSelectorProvider.java 1970-01-01 01:00:00.000000000 +0100
10375 +++ jdk22u-jdk-22.0.2-ga/src/java.base/solaris/classes/sun/nio/ch/DevPollSelectorProvider.java 2024-08-17 19:34:03.907870923 +0200
10376 @@ -0,0 +1,42 @@
10378 + * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
10379 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
10381 + * This code is free software; you can redistribute it and/or modify it
10382 + * under the terms of the GNU General Public License version 2 only, as
10383 + * published by the Free Software Foundation. Oracle designates this
10384 + * particular file as subject to the "Classpath" exception as provided
10385 + * by Oracle in the LICENSE file that accompanied this code.
10387 + * This code is distributed in the hope that it will be useful, but WITHOUT
10388 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10389 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
10390 + * version 2 for more details (a copy is included in the LICENSE file that
10391 + * accompanied this code).
10393 + * You should have received a copy of the GNU General Public License version
10394 + * 2 along with this work; if not, write to the Free Software Foundation,
10395 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
10397 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
10398 + * or visit www.oracle.com if you need additional information or have any
10399 + * questions.
10400 + */
10402 +package sun.nio.ch;
10404 +import java.io.IOException;
10405 +import java.nio.channels.*;
10406 +import java.nio.channels.spi.*;
10408 +public class DevPollSelectorProvider
10409 + extends SelectorProviderImpl
10411 + public AbstractSelector openSelector() throws IOException {
10412 + return new DevPollSelectorImpl(this);
10415 + public Channel inheritedChannel() throws IOException {
10416 + return InheritedChannel.getChannel();
10419 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/classes/sun/nio/ch/EventPortSelectorImpl.java jdk22u-jdk-22.0.2-ga/src/java.base/solaris/classes/sun/nio/ch/EventPortSelectorImpl.java
10420 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/classes/sun/nio/ch/EventPortSelectorImpl.java 1970-01-01 01:00:00.000000000 +0100
10421 +++ jdk22u-jdk-22.0.2-ga/src/java.base/solaris/classes/sun/nio/ch/EventPortSelectorImpl.java 2024-08-17 19:34:03.908264527 +0200
10422 @@ -0,0 +1,308 @@
10424 + * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
10425 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
10427 + * This code is free software; you can redistribute it and/or modify it
10428 + * under the terms of the GNU General Public License version 2 only, as
10429 + * published by the Free Software Foundation. Oracle designates this
10430 + * particular file as subject to the "Classpath" exception as provided
10431 + * by Oracle in the LICENSE file that accompanied this code.
10433 + * This code is distributed in the hope that it will be useful, but WITHOUT
10434 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10435 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
10436 + * version 2 for more details (a copy is included in the LICENSE file that
10437 + * accompanied this code).
10439 + * You should have received a copy of the GNU General Public License version
10440 + * 2 along with this work; if not, write to the Free Software Foundation,
10441 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
10443 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
10444 + * or visit www.oracle.com if you need additional information or have any
10445 + * questions.
10446 + */
10448 +package sun.nio.ch;
10450 +import java.io.IOException;
10451 +import java.nio.channels.ClosedSelectorException;
10452 +import java.nio.channels.SelectionKey;
10453 +import java.nio.channels.Selector;
10454 +import java.nio.channels.spi.SelectorProvider;
10455 +import java.util.ArrayDeque;
10456 +import java.util.Deque;
10457 +import java.util.HashMap;
10458 +import java.util.Map;
10459 +import java.util.concurrent.TimeUnit;
10460 +import java.util.function.Consumer;
10462 +import static sun.nio.ch.SolarisEventPort.PORT_SOURCE_FD;
10463 +import static sun.nio.ch.SolarisEventPort.PORT_SOURCE_USER;
10464 +import static sun.nio.ch.SolarisEventPort.SIZEOF_PORT_EVENT;
10465 +import static sun.nio.ch.SolarisEventPort.OFFSETOF_EVENTS;
10466 +import static sun.nio.ch.SolarisEventPort.OFFSETOF_SOURCE;
10467 +import static sun.nio.ch.SolarisEventPort.OFFSETOF_OBJECT;
10468 +import static sun.nio.ch.SolarisEventPort.port_create;
10469 +import static sun.nio.ch.SolarisEventPort.port_close;
10470 +import static sun.nio.ch.SolarisEventPort.port_associate;
10471 +import static sun.nio.ch.SolarisEventPort.port_dissociate;
10472 +import static sun.nio.ch.SolarisEventPort.port_getn;
10473 +import static sun.nio.ch.SolarisEventPort.port_send;
10475 +/**
10476 + * Selector implementation based on the Solaris event port mechanism.
10477 + */
10479 +class EventPortSelectorImpl
10480 + extends SelectorImpl
10482 + // maximum number of events to retrive in one call to port_getn
10483 + static final int MAX_EVENTS = Math.min(IOUtil.fdLimit()-1, 1024);
10485 + // port file descriptor
10486 + private final int pfd;
10488 + // the poll array (populated by port_getn)
10489 + private final long pollArrayAddress;
10490 + private final AllocatedNativeObject pollArray;
10492 + // maps file descriptor to selection key, synchronize on selector
10493 + private final Map<Integer, SelectionKeyImpl> fdToKey = new HashMap<>();
10495 + // the last update operation, incremented by processUpdateQueue
10496 + private int lastUpdate;
10498 + // pending new registrations/updates, queued by setEventOps and
10499 + // updateSelectedKeys
10500 + private final Object updateLock = new Object();
10501 + private final Deque<SelectionKeyImpl> updateKeys = new ArrayDeque<>();
10503 + // interrupt triggering and clearing
10504 + private final Object interruptLock = new Object();
10505 + private boolean interruptTriggered;
10507 + EventPortSelectorImpl(SelectorProvider sp) throws IOException {
10508 + super(sp);
10510 + this.pfd = port_create();
10512 + int allocationSize = MAX_EVENTS * SIZEOF_PORT_EVENT;
10513 + this.pollArray = new AllocatedNativeObject(allocationSize, false);
10514 + this.pollArrayAddress = pollArray.address();
10517 + private void ensureOpen() {
10518 + if (!isOpen())
10519 + throw new ClosedSelectorException();
10522 + @Override
10523 + protected int doSelect(Consumer<SelectionKey> action, long timeout)
10524 + throws IOException
10526 + assert Thread.holdsLock(this);
10528 + long to = timeout;
10529 + boolean blocking = (to != 0);
10530 + boolean timedPoll = (to > 0);
10532 + int numEvents;
10533 + processUpdateQueue();
10534 + processDeregisterQueue();
10535 + try {
10536 + begin(blocking);
10538 + do {
10539 + long startTime = timedPoll ? System.nanoTime() : 0;
10540 + numEvents = port_getn(pfd, pollArrayAddress, MAX_EVENTS, to);
10541 + if (numEvents == IOStatus.INTERRUPTED && timedPoll) {
10542 + // timed poll interrupted so need to adjust timeout
10543 + long adjust = System.nanoTime() - startTime;
10544 + to -= TimeUnit.MILLISECONDS.convert(adjust, TimeUnit.NANOSECONDS);
10545 + if (to <= 0) {
10546 + // timeout also expired so no retry
10547 + numEvents = 0;
10550 + } while (numEvents == IOStatus.INTERRUPTED);
10551 + assert IOStatus.check(numEvents);
10553 + } finally {
10554 + end(blocking);
10556 + processDeregisterQueue();
10557 + return processPortEvents(numEvents, action);
10560 + /**
10561 + * Process new registrations and changes to the interest ops.
10562 + */
10563 + private void processUpdateQueue() throws IOException {
10564 + assert Thread.holdsLock(this);
10566 + // bump lastUpdate to ensure that the interest ops are changed at most
10567 + // once per bulk update
10568 + lastUpdate++;
10570 + synchronized (updateLock) {
10571 + SelectionKeyImpl ski;
10572 + while ((ski = updateKeys.pollFirst()) != null) {
10573 + if (ski.isValid()) {
10574 + int fd = ski.getFDVal();
10575 + // add to fdToKey if needed
10576 + SelectionKeyImpl previous = fdToKey.putIfAbsent(fd, ski);
10577 + assert (previous == null) || (previous == ski);
10579 + int newEvents = ski.translateInterestOps();
10580 + if (newEvents != ski.registeredEvents()) {
10581 + if (newEvents == 0) {
10582 + port_dissociate(pfd, PORT_SOURCE_FD, fd);
10583 + } else {
10584 + port_associate(pfd, PORT_SOURCE_FD, fd, newEvents);
10586 + ski.registeredEvents(newEvents);
10593 + /**
10594 + * Process the polled events and re-queue the selected keys so the file
10595 + * descriptors are re-associated at the next select operation.
10596 + */
10597 + private int processPortEvents(int numEvents, Consumer<SelectionKey> action)
10598 + throws IOException
10600 + assert Thread.holdsLock(this);
10602 + int numKeysUpdated = 0;
10603 + boolean interrupted = false;
10605 + // Process the polled events while holding the update lock. This allows
10606 + // keys to be queued for ready file descriptors so they can be
10607 + // re-associated at the next select. The selected-key can be updated
10608 + // in this pass.
10609 + synchronized (updateLock) {
10610 + for (int i = 0; i < numEvents; i++) {
10611 + short source = getSource(i);
10612 + if (source == PORT_SOURCE_FD) {
10613 + int fd = getDescriptor(i);
10614 + SelectionKeyImpl ski = fdToKey.get(fd);
10615 + if (ski != null) {
10616 + ski.registeredEvents(0);
10617 + updateKeys.addLast(ski);
10619 + // update selected-key set if no action specified
10620 + if (action == null) {
10621 + int rOps = getEventOps(i);
10622 + numKeysUpdated += processReadyEvents(rOps, ski, null);
10626 + } else if (source == PORT_SOURCE_USER) {
10627 + interrupted = true;
10628 + } else {
10629 + assert false;
10634 + // if an action specified then iterate over the polled events again so
10635 + // that the action is performed without holding the update lock.
10636 + if (action != null) {
10637 + for (int i = 0; i < numEvents; i++) {
10638 + short source = getSource(i);
10639 + if (source == PORT_SOURCE_FD) {
10640 + int fd = getDescriptor(i);
10641 + SelectionKeyImpl ski = fdToKey.get(fd);
10642 + if (ski != null) {
10643 + int rOps = getEventOps(i);
10644 + numKeysUpdated += processReadyEvents(rOps, ski, action);
10650 + if (interrupted) {
10651 + clearInterrupt();
10653 + return numKeysUpdated;
10656 + @Override
10657 + protected void implClose() throws IOException {
10658 + assert !isOpen();
10659 + assert Thread.holdsLock(this);
10661 + // prevent further wakeup
10662 + synchronized (interruptLock) {
10663 + interruptTriggered = true;
10666 + port_close(pfd);
10667 + pollArray.free();
10670 + @Override
10671 + protected void implDereg(SelectionKeyImpl ski) throws IOException {
10672 + assert !ski.isValid();
10673 + assert Thread.holdsLock(this);
10675 + int fd = ski.getFDVal();
10676 + if (fdToKey.remove(fd) != null) {
10677 + if (ski.registeredEvents() != 0) {
10678 + port_dissociate(pfd, PORT_SOURCE_FD, fd);
10679 + ski.registeredEvents(0);
10681 + } else {
10682 + assert ski.registeredEvents() == 0;
10686 + @Override
10687 + public void setEventOps(SelectionKeyImpl ski) {
10688 + ensureOpen();
10689 + synchronized (updateLock) {
10690 + updateKeys.addLast(ski);
10694 + @Override
10695 + public Selector wakeup() {
10696 + synchronized (interruptLock) {
10697 + if (!interruptTriggered) {
10698 + try {
10699 + port_send(pfd, 0);
10700 + } catch (IOException ioe) {
10701 + throw new InternalError(ioe);
10703 + interruptTriggered = true;
10706 + return this;
10709 + private void clearInterrupt() throws IOException {
10710 + synchronized (interruptLock) {
10711 + interruptTriggered = false;
10715 + private short getSource(int i) {
10716 + int offset = SIZEOF_PORT_EVENT * i + OFFSETOF_SOURCE;
10717 + return pollArray.getShort(offset);
10720 + private int getEventOps(int i) {
10721 + int offset = SIZEOF_PORT_EVENT * i + OFFSETOF_EVENTS;
10722 + return pollArray.getInt(offset);
10725 + private int getDescriptor(int i) {
10726 + //assert Unsafe.getUnsafe().addressSize() == 8;
10727 + int offset = SIZEOF_PORT_EVENT * i + OFFSETOF_OBJECT;
10728 + return (int) pollArray.getLong(offset);
10731 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/classes/sun/nio/ch/EventPortSelectorProvider.java jdk22u-jdk-22.0.2-ga/src/java.base/solaris/classes/sun/nio/ch/EventPortSelectorProvider.java
10732 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/classes/sun/nio/ch/EventPortSelectorProvider.java 1970-01-01 01:00:00.000000000 +0100
10733 +++ jdk22u-jdk-22.0.2-ga/src/java.base/solaris/classes/sun/nio/ch/EventPortSelectorProvider.java 2024-08-17 19:34:03.908535926 +0200
10734 @@ -0,0 +1,42 @@
10736 + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
10737 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
10739 + * This code is free software; you can redistribute it and/or modify it
10740 + * under the terms of the GNU General Public License version 2 only, as
10741 + * published by the Free Software Foundation. Oracle designates this
10742 + * particular file as subject to the "Classpath" exception as provided
10743 + * by Oracle in the LICENSE file that accompanied this code.
10745 + * This code is distributed in the hope that it will be useful, but WITHOUT
10746 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10747 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
10748 + * version 2 for more details (a copy is included in the LICENSE file that
10749 + * accompanied this code).
10751 + * You should have received a copy of the GNU General Public License version
10752 + * 2 along with this work; if not, write to the Free Software Foundation,
10753 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
10755 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
10756 + * or visit www.oracle.com if you need additional information or have any
10757 + * questions.
10758 + */
10760 +package sun.nio.ch;
10762 +import java.io.IOException;
10763 +import java.nio.channels.*;
10764 +import java.nio.channels.spi.*;
10766 +public class EventPortSelectorProvider
10767 + extends SelectorProviderImpl
10769 + public AbstractSelector openSelector() throws IOException {
10770 + return new EventPortSelectorImpl(this);
10773 + public Channel inheritedChannel() throws IOException {
10774 + return InheritedChannel.getChannel();
10777 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/classes/sun/nio/ch/SolarisAsynchronousChannelProvider.java jdk22u-jdk-22.0.2-ga/src/java.base/solaris/classes/sun/nio/ch/SolarisAsynchronousChannelProvider.java
10778 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/classes/sun/nio/ch/SolarisAsynchronousChannelProvider.java 1970-01-01 01:00:00.000000000 +0100
10779 +++ jdk22u-jdk-22.0.2-ga/src/java.base/solaris/classes/sun/nio/ch/SolarisAsynchronousChannelProvider.java 2024-08-17 19:34:03.908998153 +0200
10780 @@ -0,0 +1,93 @@
10782 + * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
10783 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
10785 + * This code is free software; you can redistribute it and/or modify it
10786 + * under the terms of the GNU General Public License version 2 only, as
10787 + * published by the Free Software Foundation. Oracle designates this
10788 + * particular file as subject to the "Classpath" exception as provided
10789 + * by Oracle in the LICENSE file that accompanied this code.
10791 + * This code is distributed in the hope that it will be useful, but WITHOUT
10792 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10793 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
10794 + * version 2 for more details (a copy is included in the LICENSE file that
10795 + * accompanied this code).
10797 + * You should have received a copy of the GNU General Public License version
10798 + * 2 along with this work; if not, write to the Free Software Foundation,
10799 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
10801 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
10802 + * or visit www.oracle.com if you need additional information or have any
10803 + * questions.
10804 + */
10806 +package sun.nio.ch;
10808 +import java.nio.channels.*;
10809 +import java.nio.channels.spi.AsynchronousChannelProvider;
10810 +import java.util.concurrent.ExecutorService;
10811 +import java.util.concurrent.ThreadFactory;
10812 +import java.io.IOException;
10814 +public class SolarisAsynchronousChannelProvider
10815 + extends AsynchronousChannelProvider
10817 + private static volatile SolarisEventPort defaultEventPort;
10819 + private SolarisEventPort defaultEventPort() throws IOException {
10820 + if (defaultEventPort == null) {
10821 + synchronized (SolarisAsynchronousChannelProvider.class) {
10822 + if (defaultEventPort == null) {
10823 + defaultEventPort =
10824 + new SolarisEventPort(this, ThreadPool.getDefault()).start();
10828 + return defaultEventPort;
10831 + public SolarisAsynchronousChannelProvider() {
10834 + @Override
10835 + public AsynchronousChannelGroup openAsynchronousChannelGroup(int nThreads, ThreadFactory factory)
10836 + throws IOException
10838 + return new SolarisEventPort(this, ThreadPool.create(nThreads, factory)).start();
10841 + @Override
10842 + public AsynchronousChannelGroup openAsynchronousChannelGroup(ExecutorService executor, int initialSize)
10843 + throws IOException
10845 + return new SolarisEventPort(this, ThreadPool.wrap(executor, initialSize)).start();
10848 + private SolarisEventPort toEventPort(AsynchronousChannelGroup group)
10849 + throws IOException
10851 + if (group == null) {
10852 + return defaultEventPort();
10853 + } else {
10854 + if (!(group instanceof SolarisEventPort))
10855 + throw new IllegalChannelGroupException();
10856 + return (SolarisEventPort)group;
10860 + @Override
10861 + public AsynchronousServerSocketChannel openAsynchronousServerSocketChannel(AsynchronousChannelGroup group)
10862 + throws IOException
10864 + return new UnixAsynchronousServerSocketChannelImpl(toEventPort(group));
10867 + @Override
10868 + public AsynchronousSocketChannel openAsynchronousSocketChannel(AsynchronousChannelGroup group)
10869 + throws IOException
10871 + return new UnixAsynchronousSocketChannelImpl(toEventPort(group));
10874 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/classes/sun/nio/ch/SolarisEventPort.java jdk22u-jdk-22.0.2-ga/src/java.base/solaris/classes/sun/nio/ch/SolarisEventPort.java
10875 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/classes/sun/nio/ch/SolarisEventPort.java 1970-01-01 01:00:00.000000000 +0100
10876 +++ jdk22u-jdk-22.0.2-ga/src/java.base/solaris/classes/sun/nio/ch/SolarisEventPort.java 2024-08-17 19:34:03.909374188 +0200
10877 @@ -0,0 +1,273 @@
10879 + * Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved.
10880 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
10882 + * This code is free software; you can redistribute it and/or modify it
10883 + * under the terms of the GNU General Public License version 2 only, as
10884 + * published by the Free Software Foundation. Oracle designates this
10885 + * particular file as subject to the "Classpath" exception as provided
10886 + * by Oracle in the LICENSE file that accompanied this code.
10888 + * This code is distributed in the hope that it will be useful, but WITHOUT
10889 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10890 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
10891 + * version 2 for more details (a copy is included in the LICENSE file that
10892 + * accompanied this code).
10894 + * You should have received a copy of the GNU General Public License version
10895 + * 2 along with this work; if not, write to the Free Software Foundation,
10896 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
10898 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
10899 + * or visit www.oracle.com if you need additional information or have any
10900 + * questions.
10901 + */
10903 +package sun.nio.ch;
10905 +import java.nio.channels.spi.AsynchronousChannelProvider;
10906 +import java.util.concurrent.RejectedExecutionException;
10907 +import java.io.IOException;
10908 +import jdk.internal.misc.Unsafe;
10910 +/**
10911 + * Provides an AsynchronousChannelGroup implementation based on the Solaris 10
10912 + * event port framework and also provides direct access to that framework.
10913 + */
10915 +class SolarisEventPort
10916 + extends Port
10918 + private static final Unsafe unsafe = Unsafe.getUnsafe();
10919 + private static final int addressSize = unsafe.addressSize();
10921 + private static int dependsArch(int value32, int value64) {
10922 + return (addressSize == 4) ? value32 : value64;
10925 + /*
10926 + * typedef struct port_event {
10927 + * int portev_events;
10928 + * ushort_t portev_source;
10929 + * ushort_t portev_pad;
10930 + * uintptr_t portev_object;
10931 + * void *portev_user;
10932 + * } port_event_t;
10933 + */
10934 + static final int SIZEOF_PORT_EVENT = dependsArch(16, 24);
10935 + static final int OFFSETOF_EVENTS = 0;
10936 + static final int OFFSETOF_SOURCE = 4;
10937 + static final int OFFSETOF_OBJECT = 8;
10939 + // port sources
10940 + static final short PORT_SOURCE_USER = 3;
10941 + static final short PORT_SOURCE_FD = 4;
10943 + // events (sys/poll.h)
10944 + static final int POLLIN = 0x0001;
10945 + static final int POLLOUT = 0x0004;
10947 + // file descriptor to event port.
10948 + private final int port;
10950 + // true when port is closed
10951 + private boolean closed;
10953 + SolarisEventPort(AsynchronousChannelProvider provider, ThreadPool pool)
10954 + throws IOException
10956 + super(provider, pool);
10958 + // create event port
10959 + this.port = port_create();
10962 + SolarisEventPort start() {
10963 + startThreads(new EventHandlerTask());
10964 + return this;
10967 + // releass resources
10968 + private void implClose() {
10969 + synchronized (this) {
10970 + if (closed)
10971 + return;
10972 + closed = true;
10974 + port_close(port);
10977 + private void wakeup() {
10978 + try {
10979 + port_send(port, 0);
10980 + } catch (IOException x) {
10981 + throw new AssertionError(x);
10985 + @Override
10986 + void executeOnHandlerTask(Runnable task) {
10987 + synchronized (this) {
10988 + if (closed)
10989 + throw new RejectedExecutionException();
10990 + offerTask(task);
10991 + wakeup();
10995 + @Override
10996 + void shutdownHandlerTasks() {
10997 + /*
10998 + * If no tasks are running then just release resources; otherwise
10999 + * write to the one end of the socketpair to wakeup any polling threads..
11000 + */
11001 + int nThreads = threadCount();
11002 + if (nThreads == 0) {
11003 + implClose();
11004 + } else {
11005 + // send user event to wakeup each thread
11006 + while (nThreads-- > 0) {
11007 + try {
11008 + port_send(port, 0);
11009 + } catch (IOException x) {
11010 + throw new AssertionError(x);
11016 + @Override
11017 + void startPoll(int fd, int events) {
11018 + // (re-)associate file descriptor
11019 + // no need to translate events
11020 + try {
11021 + port_associate(port, PORT_SOURCE_FD, fd, events);
11022 + } catch (IOException x) {
11023 + throw new AssertionError(); // should not happen
11027 + /*
11028 + * Task to read a single event from the port and dispatch it to the
11029 + * channel's onEvent handler.
11030 + */
11031 + private class EventHandlerTask implements Runnable {
11032 + public void run() {
11033 + Invoker.GroupAndInvokeCount myGroupAndInvokeCount =
11034 + Invoker.getGroupAndInvokeCount();
11035 + final boolean isPooledThread = (myGroupAndInvokeCount != null);
11036 + boolean replaceMe = false;
11037 + long address = unsafe.allocateMemory(SIZEOF_PORT_EVENT);
11038 + try {
11039 + for (;;) {
11040 + // reset invoke count
11041 + if (isPooledThread)
11042 + myGroupAndInvokeCount.resetInvokeCount();
11044 + // wait for I/O completion event
11045 + // A error here is fatal (thread will not be replaced)
11046 + replaceMe = false;
11047 + try {
11048 + int n;
11049 + do {
11050 + n = port_get(port, address);
11051 + } while (n == IOStatus.INTERRUPTED);
11052 + } catch (IOException x) {
11053 + x.printStackTrace();
11054 + return;
11057 + // event source
11058 + short source = unsafe.getShort(address + OFFSETOF_SOURCE);
11059 + if (source != PORT_SOURCE_FD) {
11060 + // user event is trigger to invoke task or shutdown
11061 + if (source == PORT_SOURCE_USER) {
11062 + Runnable task = pollTask();
11063 + if (task == null) {
11064 + // shutdown request
11065 + return;
11067 + // run task (may throw error/exception)
11068 + replaceMe = true;
11069 + task.run();
11071 + // ignore
11072 + continue;
11075 + // pe->portev_object is file descriptor
11076 + int fd = (int)unsafe.getAddress(address + OFFSETOF_OBJECT);
11077 + // pe->portev_events
11078 + int events = unsafe.getInt(address + OFFSETOF_EVENTS);
11080 + // lookup channel
11081 + PollableChannel ch;
11082 + fdToChannelLock.readLock().lock();
11083 + try {
11084 + ch = fdToChannel.get(fd);
11085 + } finally {
11086 + fdToChannelLock.readLock().unlock();
11089 + // notify channel
11090 + if (ch != null) {
11091 + replaceMe = true;
11092 + // no need to translate events
11093 + ch.onEvent(events, isPooledThread);
11096 + } finally {
11097 + // free per-thread resources
11098 + unsafe.freeMemory(address);
11099 + // last task to exit when shutdown release resources
11100 + int remaining = threadExit(this, replaceMe);
11101 + if (remaining == 0 && isShutdown())
11102 + implClose();
11107 + /**
11108 + * Creates an event port
11109 + */
11110 + static native int port_create() throws IOException;
11112 + /**
11113 + * Associates specific events of a given object with a port
11114 + */
11115 + static native boolean port_associate(int port, int source, long object, int events)
11116 + throws IOException;
11118 + /**
11119 + * Removes the association of an object with a port.
11120 + */
11121 + static native boolean port_dissociate(int port, int source, long object)
11122 + throws IOException;
11124 + /**
11125 + * Retrieves a single event from a port
11126 + */
11127 + static native int port_get(int port, long address) throws IOException;
11129 + /**
11130 + * Retrieves at most {@code max} events from a port. A time-out of {@code < 0} means
11131 + * never time-out.
11132 + */
11133 + static native int port_getn(int port, long address, int max, long timeout)
11134 + throws IOException;
11136 + /**
11137 + * Sends a user-defined eventto a specified port.
11138 + */
11139 + static native void port_send(int port, int events) throws IOException;
11141 + /**
11142 + * Closes a port.
11143 + */
11144 + static native void port_close(int port);
11147 + static {
11148 + IOUtil.load();
11151 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/classes/sun/nio/fs/DefaultFileSystemProvider.java jdk22u-jdk-22.0.2-ga/src/java.base/solaris/classes/sun/nio/fs/DefaultFileSystemProvider.java
11152 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/classes/sun/nio/fs/DefaultFileSystemProvider.java 1970-01-01 01:00:00.000000000 +0100
11153 +++ jdk22u-jdk-22.0.2-ga/src/java.base/solaris/classes/sun/nio/fs/DefaultFileSystemProvider.java 2024-08-17 19:34:03.909725093 +0200
11154 @@ -0,0 +1,53 @@
11156 + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
11157 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
11159 + * This code is free software; you can redistribute it and/or modify it
11160 + * under the terms of the GNU General Public License version 2 only, as
11161 + * published by the Free Software Foundation. Oracle designates this
11162 + * particular file as subject to the "Classpath" exception as provided
11163 + * by Oracle in the LICENSE file that accompanied this code.
11165 + * This code is distributed in the hope that it will be useful, but WITHOUT
11166 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11167 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11168 + * version 2 for more details (a copy is included in the LICENSE file that
11169 + * accompanied this code).
11171 + * You should have received a copy of the GNU General Public License version
11172 + * 2 along with this work; if not, write to the Free Software Foundation,
11173 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
11175 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
11176 + * or visit www.oracle.com if you need additional information or have any
11177 + * questions.
11178 + */
11180 +package sun.nio.fs;
11182 +import java.nio.file.FileSystem;
11184 +/**
11185 + * Creates this platform's default FileSystemProvider.
11186 + */
11188 +public class DefaultFileSystemProvider {
11189 + private static final SolarisFileSystemProvider INSTANCE
11190 + = new SolarisFileSystemProvider();
11192 + private DefaultFileSystemProvider() { }
11194 + /**
11195 + * Returns the platform's default file system provider.
11196 + */
11197 + public static SolarisFileSystemProvider instance() {
11198 + return INSTANCE;
11201 + /**
11202 + * Returns the platform's default file system.
11203 + */
11204 + public static FileSystem theFileSystem() {
11205 + return INSTANCE.theFileSystem();
11208 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java jdk22u-jdk-22.0.2-ga/src/java.base/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java
11209 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java 1970-01-01 01:00:00.000000000 +0100
11210 +++ jdk22u-jdk-22.0.2-ga/src/java.base/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java 2024-08-17 19:34:03.910205710 +0200
11211 @@ -0,0 +1,414 @@
11213 + * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
11214 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
11216 + * This code is free software; you can redistribute it and/or modify it
11217 + * under the terms of the GNU General Public License version 2 only, as
11218 + * published by the Free Software Foundation. Oracle designates this
11219 + * particular file as subject to the "Classpath" exception as provided
11220 + * by Oracle in the LICENSE file that accompanied this code.
11222 + * This code is distributed in the hope that it will be useful, but WITHOUT
11223 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11224 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11225 + * version 2 for more details (a copy is included in the LICENSE file that
11226 + * accompanied this code).
11228 + * You should have received a copy of the GNU General Public License version
11229 + * 2 along with this work; if not, write to the Free Software Foundation,
11230 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
11232 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
11233 + * or visit www.oracle.com if you need additional information or have any
11234 + * questions.
11235 + */
11237 +package sun.nio.fs;
11239 +import java.nio.file.*;
11240 +import java.nio.file.attribute.*;
11241 +import java.util.*;
11242 +import java.io.IOException;
11243 +import jdk.internal.misc.Unsafe;
11245 +import static sun.nio.fs.UnixConstants.*;
11246 +import static sun.nio.fs.SolarisConstants.*;
11247 +import static sun.nio.fs.SolarisNativeDispatcher.*;
11250 +/**
11251 + * Solaris implementation of AclFileAttributeView with native support for
11252 + * NFSv4 ACLs on ZFS.
11253 + */
11255 +class SolarisAclFileAttributeView
11256 + extends AbstractAclFileAttributeView
11258 + private static final Unsafe unsafe = Unsafe.getUnsafe();
11260 + // Maximum number of entries allowed in an ACL
11261 + private static final int MAX_ACL_ENTRIES = 1024;
11263 + /**
11264 + * typedef struct ace {
11265 + * uid_t a_who;
11266 + * uint32_t a_access_mask;
11267 + * uint16_t a_flags;
11268 + * uint16_t a_type;
11269 + * } ace_t;
11270 + */
11271 + private static final short SIZEOF_ACE_T = 12;
11272 + private static final short OFFSETOF_UID = 0;
11273 + private static final short OFFSETOF_MASK = 4;
11274 + private static final short OFFSETOF_FLAGS = 8;
11275 + private static final short OFFSETOF_TYPE = 10;
11277 + private final UnixPath file;
11278 + private final boolean followLinks;
11280 + SolarisAclFileAttributeView(UnixPath file, boolean followLinks) {
11281 + this.file = file;
11282 + this.followLinks = followLinks;
11285 + /**
11286 + * Permission checks to access file
11287 + */
11288 + private void checkAccess(UnixPath file,
11289 + boolean checkRead,
11290 + boolean checkWrite)
11292 + @SuppressWarnings("removal")
11293 + SecurityManager sm = System.getSecurityManager();
11294 + if (sm != null) {
11295 + if (checkRead)
11296 + file.checkRead();
11297 + if (checkWrite)
11298 + file.checkWrite();
11299 + sm.checkPermission(new RuntimePermission("accessUserInformation"));
11303 + /**
11304 + * Encode the ACL to the given buffer
11305 + */
11306 + private static void encode(List<AclEntry> acl, long address) {
11307 + long offset = address;
11308 + for (AclEntry ace: acl) {
11309 + int flags = 0;
11311 + // map UserPrincipal to uid and flags
11312 + UserPrincipal who = ace.principal();
11313 + if (!(who instanceof UnixUserPrincipals.User))
11314 + throw new ProviderMismatchException();
11315 + UnixUserPrincipals.User user = (UnixUserPrincipals.User)who;
11316 + int uid;
11317 + if (user.isSpecial()) {
11318 + uid = -1;
11319 + if (who == UnixUserPrincipals.SPECIAL_OWNER)
11320 + flags |= ACE_OWNER;
11321 + else if (who == UnixUserPrincipals.SPECIAL_GROUP)
11322 + flags |= (ACE_GROUP | ACE_IDENTIFIER_GROUP);
11323 + else if (who == UnixUserPrincipals.SPECIAL_EVERYONE)
11324 + flags |= ACE_EVERYONE;
11325 + else
11326 + throw new AssertionError("Unable to map special identifier");
11327 + } else {
11328 + if (user instanceof UnixUserPrincipals.Group) {
11329 + uid = user.gid();
11330 + flags |= ACE_IDENTIFIER_GROUP;
11331 + } else {
11332 + uid = user.uid();
11336 + // map ACE type
11337 + int type;
11338 + switch (ace.type()) {
11339 + case ALLOW:
11340 + type = ACE_ACCESS_ALLOWED_ACE_TYPE;
11341 + break;
11342 + case DENY:
11343 + type = ACE_ACCESS_DENIED_ACE_TYPE;
11344 + break;
11345 + case AUDIT:
11346 + type = ACE_SYSTEM_AUDIT_ACE_TYPE;
11347 + break;
11348 + case ALARM:
11349 + type = ACE_SYSTEM_ALARM_ACE_TYPE;
11350 + break;
11351 + default:
11352 + throw new AssertionError("Unable to map ACE type");
11355 + // map permissions
11356 + Set<AclEntryPermission> aceMask = ace.permissions();
11357 + int mask = 0;
11358 + if (aceMask.contains(AclEntryPermission.READ_DATA))
11359 + mask |= ACE_READ_DATA;
11360 + if (aceMask.contains(AclEntryPermission.WRITE_DATA))
11361 + mask |= ACE_WRITE_DATA;
11362 + if (aceMask.contains(AclEntryPermission.APPEND_DATA))
11363 + mask |= ACE_APPEND_DATA;
11364 + if (aceMask.contains(AclEntryPermission.READ_NAMED_ATTRS))
11365 + mask |= ACE_READ_NAMED_ATTRS;
11366 + if (aceMask.contains(AclEntryPermission.WRITE_NAMED_ATTRS))
11367 + mask |= ACE_WRITE_NAMED_ATTRS;
11368 + if (aceMask.contains(AclEntryPermission.EXECUTE))
11369 + mask |= ACE_EXECUTE;
11370 + if (aceMask.contains(AclEntryPermission.DELETE_CHILD))
11371 + mask |= ACE_DELETE_CHILD;
11372 + if (aceMask.contains(AclEntryPermission.READ_ATTRIBUTES))
11373 + mask |= ACE_READ_ATTRIBUTES;
11374 + if (aceMask.contains(AclEntryPermission.WRITE_ATTRIBUTES))
11375 + mask |= ACE_WRITE_ATTRIBUTES;
11376 + if (aceMask.contains(AclEntryPermission.DELETE))
11377 + mask |= ACE_DELETE;
11378 + if (aceMask.contains(AclEntryPermission.READ_ACL))
11379 + mask |= ACE_READ_ACL;
11380 + if (aceMask.contains(AclEntryPermission.WRITE_ACL))
11381 + mask |= ACE_WRITE_ACL;
11382 + if (aceMask.contains(AclEntryPermission.WRITE_OWNER))
11383 + mask |= ACE_WRITE_OWNER;
11384 + if (aceMask.contains(AclEntryPermission.SYNCHRONIZE))
11385 + mask |= ACE_SYNCHRONIZE;
11387 + // FIXME - it would be desirable to know here if the file is a
11388 + // directory or not. Solaris returns EINVAL if an ACE has a directory
11389 + // -only flag and the file is not a directory.
11390 + Set<AclEntryFlag> aceFlags = ace.flags();
11391 + if (aceFlags.contains(AclEntryFlag.FILE_INHERIT))
11392 + flags |= ACE_FILE_INHERIT_ACE;
11393 + if (aceFlags.contains(AclEntryFlag.DIRECTORY_INHERIT))
11394 + flags |= ACE_DIRECTORY_INHERIT_ACE;
11395 + if (aceFlags.contains(AclEntryFlag.NO_PROPAGATE_INHERIT))
11396 + flags |= ACE_NO_PROPAGATE_INHERIT_ACE;
11397 + if (aceFlags.contains(AclEntryFlag.INHERIT_ONLY))
11398 + flags |= ACE_INHERIT_ONLY_ACE;
11400 + unsafe.putInt(offset + OFFSETOF_UID, uid);
11401 + unsafe.putInt(offset + OFFSETOF_MASK, mask);
11402 + unsafe.putShort(offset + OFFSETOF_FLAGS, (short)flags);
11403 + unsafe.putShort(offset + OFFSETOF_TYPE, (short)type);
11405 + offset += SIZEOF_ACE_T;
11409 + /**
11410 + * Decode the buffer, returning an ACL
11411 + */
11412 + private static List<AclEntry> decode(long address, int n) {
11413 + ArrayList<AclEntry> acl = new ArrayList<>(n);
11414 + for (int i=0; i<n; i++) {
11415 + long offset = address + i*SIZEOF_ACE_T;
11417 + int uid = unsafe.getInt(offset + OFFSETOF_UID);
11418 + int mask = unsafe.getInt(offset + OFFSETOF_MASK);
11419 + int flags = (int)unsafe.getShort(offset + OFFSETOF_FLAGS);
11420 + int type = (int)unsafe.getShort(offset + OFFSETOF_TYPE);
11422 + // map uid and flags to UserPrincipal
11423 + UnixUserPrincipals.User who = null;
11424 + if ((flags & ACE_OWNER) > 0) {
11425 + who = UnixUserPrincipals.SPECIAL_OWNER;
11426 + } else if ((flags & ACE_GROUP) > 0) {
11427 + who = UnixUserPrincipals.SPECIAL_GROUP;
11428 + } else if ((flags & ACE_EVERYONE) > 0) {
11429 + who = UnixUserPrincipals.SPECIAL_EVERYONE;
11430 + } else if ((flags & ACE_IDENTIFIER_GROUP) > 0) {
11431 + who = UnixUserPrincipals.fromGid(uid);
11432 + } else {
11433 + who = UnixUserPrincipals.fromUid(uid);
11436 + AclEntryType aceType = null;
11437 + switch (type) {
11438 + case ACE_ACCESS_ALLOWED_ACE_TYPE:
11439 + aceType = AclEntryType.ALLOW;
11440 + break;
11441 + case ACE_ACCESS_DENIED_ACE_TYPE:
11442 + aceType = AclEntryType.DENY;
11443 + break;
11444 + case ACE_SYSTEM_AUDIT_ACE_TYPE:
11445 + aceType = AclEntryType.AUDIT;
11446 + break;
11447 + case ACE_SYSTEM_ALARM_ACE_TYPE:
11448 + aceType = AclEntryType.ALARM;
11449 + break;
11450 + default:
11451 + assert false;
11454 + Set<AclEntryPermission> aceMask = EnumSet.noneOf(AclEntryPermission.class);
11455 + if ((mask & ACE_READ_DATA) > 0)
11456 + aceMask.add(AclEntryPermission.READ_DATA);
11457 + if ((mask & ACE_WRITE_DATA) > 0)
11458 + aceMask.add(AclEntryPermission.WRITE_DATA);
11459 + if ((mask & ACE_APPEND_DATA ) > 0)
11460 + aceMask.add(AclEntryPermission.APPEND_DATA);
11461 + if ((mask & ACE_READ_NAMED_ATTRS) > 0)
11462 + aceMask.add(AclEntryPermission.READ_NAMED_ATTRS);
11463 + if ((mask & ACE_WRITE_NAMED_ATTRS) > 0)
11464 + aceMask.add(AclEntryPermission.WRITE_NAMED_ATTRS);
11465 + if ((mask & ACE_EXECUTE) > 0)
11466 + aceMask.add(AclEntryPermission.EXECUTE);
11467 + if ((mask & ACE_DELETE_CHILD ) > 0)
11468 + aceMask.add(AclEntryPermission.DELETE_CHILD);
11469 + if ((mask & ACE_READ_ATTRIBUTES) > 0)
11470 + aceMask.add(AclEntryPermission.READ_ATTRIBUTES);
11471 + if ((mask & ACE_WRITE_ATTRIBUTES) > 0)
11472 + aceMask.add(AclEntryPermission.WRITE_ATTRIBUTES);
11473 + if ((mask & ACE_DELETE) > 0)
11474 + aceMask.add(AclEntryPermission.DELETE);
11475 + if ((mask & ACE_READ_ACL) > 0)
11476 + aceMask.add(AclEntryPermission.READ_ACL);
11477 + if ((mask & ACE_WRITE_ACL) > 0)
11478 + aceMask.add(AclEntryPermission.WRITE_ACL);
11479 + if ((mask & ACE_WRITE_OWNER) > 0)
11480 + aceMask.add(AclEntryPermission.WRITE_OWNER);
11481 + if ((mask & ACE_SYNCHRONIZE) > 0)
11482 + aceMask.add(AclEntryPermission.SYNCHRONIZE);
11484 + Set<AclEntryFlag> aceFlags = EnumSet.noneOf(AclEntryFlag.class);
11485 + if ((flags & ACE_FILE_INHERIT_ACE) > 0)
11486 + aceFlags.add(AclEntryFlag.FILE_INHERIT);
11487 + if ((flags & ACE_DIRECTORY_INHERIT_ACE) > 0)
11488 + aceFlags.add(AclEntryFlag.DIRECTORY_INHERIT);
11489 + if ((flags & ACE_NO_PROPAGATE_INHERIT_ACE) > 0)
11490 + aceFlags.add(AclEntryFlag.NO_PROPAGATE_INHERIT);
11491 + if ((flags & ACE_INHERIT_ONLY_ACE) > 0)
11492 + aceFlags.add(AclEntryFlag.INHERIT_ONLY);
11494 + // build the ACL entry and add it to the list
11495 + AclEntry ace = AclEntry.newBuilder()
11496 + .setType(aceType)
11497 + .setPrincipal(who)
11498 + .setPermissions(aceMask).setFlags(aceFlags).build();
11499 + acl.add(ace);
11502 + return acl;
11505 + // Returns true if NFSv4 ACLs not enabled on file system
11506 + private static boolean isAclsEnabled(int fd) {
11507 + try {
11508 + long enabled = fpathconf(fd, _PC_ACL_ENABLED);
11509 + if (enabled == _ACL_ACE_ENABLED)
11510 + return true;
11511 + } catch (UnixException x) {
11513 + return false;
11516 + @Override
11517 + public List<AclEntry> getAcl()
11518 + throws IOException
11520 + // permission check
11521 + checkAccess(file, true, false);
11523 + // open file (will fail if file is a link and not following links)
11524 + int fd = -1;
11525 + try {
11526 + fd = file.openForAttributeAccess(followLinks);
11527 + } catch (UnixException x) {
11528 + x.rethrowAsIOException(file);
11530 + try {
11531 + long address = unsafe.allocateMemory(SIZEOF_ACE_T * MAX_ACL_ENTRIES);
11532 + try {
11533 + // read ACL and decode it
11534 + int n = facl(fd, ACE_GETACL, MAX_ACL_ENTRIES, address);
11535 + assert n >= 0;
11536 + return decode(address, n);
11537 + } catch (UnixException x) {
11538 + if ((x.errno() == ENOSYS) || !isAclsEnabled(fd)) {
11539 + throw new FileSystemException(file.getPathForExceptionMessage(),
11540 + null, x.getMessage() + " (file system does not support NFSv4 ACLs)");
11542 + x.rethrowAsIOException(file);
11543 + return null; // keep compiler happy
11544 + } finally {
11545 + unsafe.freeMemory(address);
11547 + } finally {
11548 + close(fd, e -> null);
11552 + @Override
11553 + public void setAcl(List<AclEntry> acl) throws IOException {
11554 + // permission check
11555 + checkAccess(file, false, true);
11557 + // open file (will fail if file is a link and not following links)
11558 + int fd = -1;
11559 + try {
11560 + fd = file.openForAttributeAccess(followLinks);
11561 + } catch (UnixException x) {
11562 + x.rethrowAsIOException(file);
11564 + try {
11565 + // SECURITY: need to copy list as can change during processing
11566 + acl = new ArrayList<AclEntry>(acl);
11567 + int n = acl.size();
11569 + long address = unsafe.allocateMemory(SIZEOF_ACE_T * n);
11570 + try {
11571 + encode(acl, address);
11572 + facl(fd, ACE_SETACL, n, address);
11573 + } catch (UnixException x) {
11574 + if ((x.errno() == ENOSYS) || !isAclsEnabled(fd)) {
11575 + throw new FileSystemException(file.getPathForExceptionMessage(),
11576 + null, x.getMessage() + " (file system does not support NFSv4 ACLs)");
11578 + if (x.errno() == EINVAL && (n < 3))
11579 + throw new IOException("ACL must contain at least 3 entries");
11580 + x.rethrowAsIOException(file);
11581 + } finally {
11582 + unsafe.freeMemory(address);
11584 + } finally {
11585 + close(fd, e -> null);
11589 + @Override
11590 + public UserPrincipal getOwner()
11591 + throws IOException
11593 + checkAccess(file, true, false);
11595 + try {
11596 + UnixFileAttributes attrs =
11597 + UnixFileAttributes.get(file, followLinks);
11598 + return UnixUserPrincipals.fromUid(attrs.uid());
11599 + } catch (UnixException x) {
11600 + x.rethrowAsIOException(file);
11601 + return null; // keep compile happy
11605 + @Override
11606 + public void setOwner(UserPrincipal owner) throws IOException {
11607 + checkAccess(file, true, false);
11609 + if (!(owner instanceof UnixUserPrincipals.User))
11610 + throw new ProviderMismatchException();
11611 + if (owner instanceof UnixUserPrincipals.Group)
11612 + throw new IOException("'owner' parameter is a group");
11613 + int uid = ((UnixUserPrincipals.User)owner).uid();
11615 + try {
11616 + if (followLinks) {
11617 + lchown(file, uid, -1);
11618 + } else {
11619 + chown(file, uid, -1);
11621 + } catch (UnixException x) {
11622 + x.rethrowAsIOException(file);
11626 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisConstants.java.template jdk22u-jdk-22.0.2-ga/src/java.base/solaris/classes/sun/nio/fs/SolarisConstants.java.template
11627 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisConstants.java.template 1970-01-01 01:00:00.000000000 +0100
11628 +++ jdk22u-jdk-22.0.2-ga/src/java.base/solaris/classes/sun/nio/fs/SolarisConstants.java.template 2024-08-17 19:34:03.910509796 +0200
11629 @@ -0,0 +1,89 @@
11631 + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
11633 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
11635 + * This code is free software; you can redistribute it and/or modify it
11636 + * under the terms of the GNU General Public License version 2 only, as
11637 + * published by the Free Software Foundation. Oracle designates this
11638 + * particular file as subject to the "Classpath" exception as provided
11639 + * by Oracle in the LICENSE file that accompanied this code.
11641 + * This code is distributed in the hope that it will be useful, but WITHOUT
11642 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11643 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11644 + * version 2 for more details (a copy is included in the LICENSE file that
11645 + * accompanied this code).
11647 + * You should have received a copy of the GNU General Public License version
11648 + * 2 along with this work; if not, write to the Free Software Foundation,
11649 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
11651 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
11652 + * or visit www.oracle.com if you need additional information or have any
11653 + * questions.
11654 + */
11656 +@@END_COPYRIGHT@@
11658 +#include <stdio.h>
11659 +#include <errno.h>
11660 +#include <unistd.h>
11661 +#include <sys/acl.h>
11662 +#include <fcntl.h>
11663 +#include <sys/stat.h>
11665 +/* On Solaris, "sun" is defined as a macro. Undefine to make package
11666 + declaration valid */
11667 +#undef sun
11669 +/* To be able to name the Java constants the same as the C constants without
11670 + having the preprocessor rewrite those identifiers, add PREFIX_ to all
11671 + identifiers matching a C constant. The PREFIX_ is filtered out in the
11672 + makefile. */
11674 +@@START_HERE@@
11676 +package sun.nio.fs;
11677 +class SolarisConstants {
11679 + private SolarisConstants() { }
11681 + static final int PREFIX_O_XATTR = O_XATTR;
11682 + static final int PREFIX__PC_XATTR_ENABLED = _PC_XATTR_ENABLED;
11683 + static final int PREFIX__PC_ACL_ENABLED = _PC_ACL_ENABLED;
11684 + static final int PREFIX__ACL_ACE_ENABLED = _ACL_ACE_ENABLED;
11685 + static final int PREFIX_ACE_GETACL = ACE_GETACL;
11686 + static final int PREFIX_ACE_SETACL = ACE_SETACL;
11687 + static final int PREFIX_ACE_ACCESS_ALLOWED_ACE_TYPE = ACE_ACCESS_ALLOWED_ACE_TYPE;
11688 + static final int PREFIX_ACE_ACCESS_DENIED_ACE_TYPE = ACE_ACCESS_DENIED_ACE_TYPE;
11689 + static final int PREFIX_ACE_SYSTEM_AUDIT_ACE_TYPE = ACE_SYSTEM_AUDIT_ACE_TYPE;
11690 + static final int PREFIX_ACE_SYSTEM_ALARM_ACE_TYPE = ACE_SYSTEM_ALARM_ACE_TYPE;
11691 + static final int PREFIX_ACE_READ_DATA = ACE_READ_DATA;
11692 + static final int PREFIX_ACE_LIST_DIRECTORY = ACE_LIST_DIRECTORY;
11693 + static final int PREFIX_ACE_WRITE_DATA = ACE_WRITE_DATA;
11694 + static final int PREFIX_ACE_ADD_FILE = ACE_ADD_FILE;
11695 + static final int PREFIX_ACE_APPEND_DATA = ACE_APPEND_DATA;
11696 + static final int PREFIX_ACE_ADD_SUBDIRECTORY = ACE_ADD_SUBDIRECTORY;
11697 + static final int PREFIX_ACE_READ_NAMED_ATTRS = ACE_READ_NAMED_ATTRS;
11698 + static final int PREFIX_ACE_WRITE_NAMED_ATTRS = ACE_WRITE_NAMED_ATTRS;
11699 + static final int PREFIX_ACE_EXECUTE = ACE_EXECUTE;
11700 + static final int PREFIX_ACE_DELETE_CHILD = ACE_DELETE_CHILD;
11701 + static final int PREFIX_ACE_READ_ATTRIBUTES = ACE_READ_ATTRIBUTES;
11702 + static final int PREFIX_ACE_WRITE_ATTRIBUTES = ACE_WRITE_ATTRIBUTES;
11703 + static final int PREFIX_ACE_DELETE = ACE_DELETE;
11704 + static final int PREFIX_ACE_READ_ACL = ACE_READ_ACL;
11705 + static final int PREFIX_ACE_WRITE_ACL = ACE_WRITE_ACL;
11706 + static final int PREFIX_ACE_WRITE_OWNER = ACE_WRITE_OWNER;
11707 + static final int PREFIX_ACE_SYNCHRONIZE = ACE_SYNCHRONIZE;
11708 + static final int PREFIX_ACE_FILE_INHERIT_ACE = ACE_FILE_INHERIT_ACE;
11709 + static final int PREFIX_ACE_DIRECTORY_INHERIT_ACE = ACE_DIRECTORY_INHERIT_ACE;
11710 + static final int PREFIX_ACE_NO_PROPAGATE_INHERIT_ACE = ACE_NO_PROPAGATE_INHERIT_ACE;
11711 + static final int PREFIX_ACE_INHERIT_ONLY_ACE = ACE_INHERIT_ONLY_ACE;
11712 + static final int PREFIX_ACE_SUCCESSFUL_ACCESS_ACE_FLAG = ACE_SUCCESSFUL_ACCESS_ACE_FLAG;
11713 + static final int PREFIX_ACE_FAILED_ACCESS_ACE_FLAG = ACE_FAILED_ACCESS_ACE_FLAG;
11714 + static final int PREFIX_ACE_IDENTIFIER_GROUP = ACE_IDENTIFIER_GROUP;
11715 + static final int PREFIX_ACE_OWNER = ACE_OWNER;
11716 + static final int PREFIX_ACE_GROUP = ACE_GROUP;
11717 + static final int PREFIX_ACE_EVERYONE = ACE_EVERYONE;
11719 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisFileStore.java jdk22u-jdk-22.0.2-ga/src/java.base/solaris/classes/sun/nio/fs/SolarisFileStore.java
11720 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisFileStore.java 1970-01-01 01:00:00.000000000 +0100
11721 +++ jdk22u-jdk-22.0.2-ga/src/java.base/solaris/classes/sun/nio/fs/SolarisFileStore.java 2024-08-17 19:34:03.910813600 +0200
11722 @@ -0,0 +1,111 @@
11724 + * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
11725 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
11727 + * This code is free software; you can redistribute it and/or modify it
11728 + * under the terms of the GNU General Public License version 2 only, as
11729 + * published by the Free Software Foundation. Oracle designates this
11730 + * particular file as subject to the "Classpath" exception as provided
11731 + * by Oracle in the LICENSE file that accompanied this code.
11733 + * This code is distributed in the hope that it will be useful, but WITHOUT
11734 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11735 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11736 + * version 2 for more details (a copy is included in the LICENSE file that
11737 + * accompanied this code).
11739 + * You should have received a copy of the GNU General Public License version
11740 + * 2 along with this work; if not, write to the Free Software Foundation,
11741 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
11743 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
11744 + * or visit www.oracle.com if you need additional information or have any
11745 + * questions.
11746 + */
11748 +package sun.nio.fs;
11750 +import java.nio.file.attribute.*;
11751 +import java.io.IOException;
11753 +import static sun.nio.fs.UnixNativeDispatcher.*;
11754 +import static sun.nio.fs.SolarisConstants.*;
11756 +/**
11757 + * Solaris implementation of FileStore
11758 + */
11760 +class SolarisFileStore
11761 + extends UnixFileStore
11763 + private final boolean xattrEnabled;
11765 + SolarisFileStore(UnixPath file) throws IOException {
11766 + super(file);
11767 + this.xattrEnabled = xattrEnabled();
11770 + SolarisFileStore(UnixFileSystem fs, UnixMountEntry entry) throws IOException {
11771 + super(fs, entry);
11772 + this.xattrEnabled = xattrEnabled();
11775 + // returns true if extended attributes enabled
11776 + private boolean xattrEnabled() {
11777 + long res = 0L;
11778 + try {
11779 + res = pathconf(file(), _PC_XATTR_ENABLED);
11780 + } catch (UnixException x) {
11781 + // ignore
11783 + return (res != 0L);
11786 + @Override
11787 + UnixMountEntry findMountEntry() throws IOException {
11788 + // On Solaris iterate over the entries in the mount table to find device
11789 + for (UnixMountEntry entry: file().getFileSystem().getMountEntries()) {
11790 + if (entry.dev() == dev()) {
11791 + return entry;
11794 + throw new IOException("Device not found in mnttab");
11797 + @Override
11798 + public boolean supportsFileAttributeView(Class<? extends FileAttributeView> type) {
11799 + if (type == AclFileAttributeView.class) {
11800 + // lookup fstypes.properties
11801 + FeatureStatus status = checkIfFeaturePresent("nfsv4acl");
11802 + switch (status) {
11803 + case PRESENT : return true;
11804 + case NOT_PRESENT : return false;
11805 + default :
11806 + // AclFileAttributeView available on ZFS
11807 + return (type().equals("zfs"));
11810 + if (type == UserDefinedFileAttributeView.class) {
11811 + // lookup fstypes.properties
11812 + FeatureStatus status = checkIfFeaturePresent("xattr");
11813 + switch (status) {
11814 + case PRESENT : return true;
11815 + case NOT_PRESENT : return false;
11816 + default :
11817 + // UserDefinedFileAttributeView available if extended
11818 + // attributes supported
11819 + return xattrEnabled;
11822 + return super.supportsFileAttributeView(type);
11825 + @Override
11826 + public boolean supportsFileAttributeView(String name) {
11827 + if (name.equals("acl"))
11828 + return supportsFileAttributeView(AclFileAttributeView.class);
11829 + if (name.equals("user"))
11830 + return supportsFileAttributeView(UserDefinedFileAttributeView.class);
11831 + return super.supportsFileAttributeView(name);
11834 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystem.java jdk22u-jdk-22.0.2-ga/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystem.java
11835 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystem.java 1970-01-01 01:00:00.000000000 +0100
11836 +++ jdk22u-jdk-22.0.2-ga/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystem.java 2024-08-17 19:34:03.911126014 +0200
11837 @@ -0,0 +1,127 @@
11839 + * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
11840 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
11842 + * This code is free software; you can redistribute it and/or modify it
11843 + * under the terms of the GNU General Public License version 2 only, as
11844 + * published by the Free Software Foundation. Oracle designates this
11845 + * particular file as subject to the "Classpath" exception as provided
11846 + * by Oracle in the LICENSE file that accompanied this code.
11848 + * This code is distributed in the hope that it will be useful, but WITHOUT
11849 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11850 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11851 + * version 2 for more details (a copy is included in the LICENSE file that
11852 + * accompanied this code).
11854 + * You should have received a copy of the GNU General Public License version
11855 + * 2 along with this work; if not, write to the Free Software Foundation,
11856 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
11858 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
11859 + * or visit www.oracle.com if you need additional information or have any
11860 + * questions.
11861 + */
11863 +package sun.nio.fs;
11865 +import java.nio.file.*;
11866 +import java.io.IOException;
11867 +import java.util.*;
11868 +import sun.security.action.GetPropertyAction;
11869 +import static sun.nio.fs.SolarisNativeDispatcher.*;
11871 +/**
11872 + * Solaris implementation of FileSystem
11873 + */
11875 +class SolarisFileSystem extends UnixFileSystem {
11876 + private final boolean hasSolaris11Features;
11878 + SolarisFileSystem(UnixFileSystemProvider provider, String dir) {
11879 + super(provider, dir);
11881 + // check os.version
11882 + String osversion = GetPropertyAction.privilegedGetProperty("os.version");
11883 + String[] vers = Util.split(osversion, '.');
11884 + assert vers.length >= 2;
11885 + int majorVersion = Integer.parseInt(vers[0]);
11886 + int minorVersion = Integer.parseInt(vers[1]);
11887 + this.hasSolaris11Features =
11888 + (majorVersion > 5 || (majorVersion == 5 && minorVersion >= 11));
11891 + @Override
11892 + boolean isSolaris() {
11893 + return true;
11896 + @Override
11897 + public WatchService newWatchService()
11898 + throws IOException
11900 + // FEN available since Solaris 11
11901 + if (hasSolaris11Features) {
11902 + return new SolarisWatchService(this);
11903 + } else {
11904 + return new PollingWatchService();
11909 + // lazy initialization of the list of supported attribute views
11910 + private static class SupportedFileFileAttributeViewsHolder {
11911 + static final Set<String> supportedFileAttributeViews =
11912 + supportedFileAttributeViews();
11913 + private static Set<String> supportedFileAttributeViews() {
11914 + Set<String> result = new HashSet<>();
11915 + result.addAll(standardFileAttributeViews());
11916 + // additional Solaris-specific views
11917 + result.add("acl");
11918 + result.add("user");
11919 + return Collections.unmodifiableSet(result);
11923 + @Override
11924 + public Set<String> supportedFileAttributeViews() {
11925 + return SupportedFileFileAttributeViewsHolder.supportedFileAttributeViews;
11928 + @Override
11929 + void copyNonPosixAttributes(int ofd, int nfd) {
11930 + SolarisUserDefinedFileAttributeView.copyExtendedAttributes(ofd, nfd);
11931 + // TDB: copy ACL from source to target
11934 + /**
11935 + * Returns object to iterate over entries in /etc/mnttab
11936 + */
11937 + @Override
11938 + Iterable<UnixMountEntry> getMountEntries() {
11939 + ArrayList<UnixMountEntry> entries = new ArrayList<>();
11940 + try {
11941 + UnixPath mnttab = new UnixPath(this, "/etc/mnttab");
11942 + long fp = fopen(mnttab, "r");
11943 + try {
11944 + for (;;) {
11945 + UnixMountEntry entry = new UnixMountEntry();
11946 + int res = getextmntent(fp, entry);
11947 + if (res < 0)
11948 + break;
11949 + entries.add(entry);
11951 + } finally {
11952 + fclose(fp);
11954 + } catch (UnixException x) {
11955 + // nothing we can do
11957 + return entries;
11960 + @Override
11961 + FileStore getFileStore(UnixMountEntry entry) throws IOException {
11962 + return new SolarisFileStore(this, entry);
11965 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java jdk22u-jdk-22.0.2-ga/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java
11966 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java 1970-01-01 01:00:00.000000000 +0100
11967 +++ jdk22u-jdk-22.0.2-ga/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java 2024-08-17 19:34:03.911424179 +0200
11968 @@ -0,0 +1,94 @@
11970 + * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
11971 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
11973 + * This code is free software; you can redistribute it and/or modify it
11974 + * under the terms of the GNU General Public License version 2 only, as
11975 + * published by the Free Software Foundation. Oracle designates this
11976 + * particular file as subject to the "Classpath" exception as provided
11977 + * by Oracle in the LICENSE file that accompanied this code.
11979 + * This code is distributed in the hope that it will be useful, but WITHOUT
11980 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11981 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11982 + * version 2 for more details (a copy is included in the LICENSE file that
11983 + * accompanied this code).
11985 + * You should have received a copy of the GNU General Public License version
11986 + * 2 along with this work; if not, write to the Free Software Foundation,
11987 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
11989 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
11990 + * or visit www.oracle.com if you need additional information or have any
11991 + * questions.
11992 + */
11994 +package sun.nio.fs;
11996 +import java.nio.file.*;
11997 +import java.nio.file.attribute.*;
11998 +import java.nio.file.spi.FileTypeDetector;
11999 +import java.io.IOException;
12000 +import jdk.internal.util.StaticProperty;
12001 +import sun.security.action.GetPropertyAction;
12003 +/**
12004 + * Solaris implementation of FileSystemProvider
12005 + */
12007 +class SolarisFileSystemProvider extends UnixFileSystemProvider {
12008 + public SolarisFileSystemProvider() {
12009 + super();
12012 + @Override
12013 + SolarisFileSystem newFileSystem(String dir) {
12014 + return new SolarisFileSystem(this, dir);
12017 + @Override
12018 + SolarisFileStore getFileStore(UnixPath path) throws IOException {
12019 + return new SolarisFileStore(path);
12023 + @Override
12024 + @SuppressWarnings("unchecked")
12025 + public <V extends FileAttributeView> V getFileAttributeView(Path obj,
12026 + Class<V> type,
12027 + LinkOption... options)
12029 + if (type == AclFileAttributeView.class) {
12030 + return (V) new SolarisAclFileAttributeView(UnixPath.toUnixPath(obj),
12031 + Util.followLinks(options));
12033 + if (type == UserDefinedFileAttributeView.class) {
12034 + return(V) new SolarisUserDefinedFileAttributeView(UnixPath.toUnixPath(obj),
12035 + Util.followLinks(options));
12037 + return super.getFileAttributeView(obj, type, options);
12040 + @Override
12041 + public DynamicFileAttributeView getFileAttributeView(Path obj,
12042 + String name,
12043 + LinkOption... options)
12045 + if (name.equals("acl"))
12046 + return new SolarisAclFileAttributeView(UnixPath.toUnixPath(obj),
12047 + Util.followLinks(options));
12048 + if (name.equals("user"))
12049 + return new SolarisUserDefinedFileAttributeView(UnixPath.toUnixPath(obj),
12050 + Util.followLinks(options));
12051 + return super.getFileAttributeView(obj, name, options);
12054 + @Override
12055 + FileTypeDetector getFileTypeDetector() {
12056 + Path userMimeTypes = Path.of(StaticProperty.userHome(), ".mime.types");
12057 + Path etcMimeTypes = Path.of("/etc/mime.types");
12059 + return chain(new MimeTypesFileTypeDetector(userMimeTypes),
12060 + new MimeTypesFileTypeDetector(etcMimeTypes));
12063 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisNativeDispatcher.java jdk22u-jdk-22.0.2-ga/src/java.base/solaris/classes/sun/nio/fs/SolarisNativeDispatcher.java
12064 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisNativeDispatcher.java 1970-01-01 01:00:00.000000000 +0100
12065 +++ jdk22u-jdk-22.0.2-ga/src/java.base/solaris/classes/sun/nio/fs/SolarisNativeDispatcher.java 2024-08-17 19:34:03.911705347 +0200
12066 @@ -0,0 +1,55 @@
12068 + * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
12069 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
12071 + * This code is free software; you can redistribute it and/or modify it
12072 + * under the terms of the GNU General Public License version 2 only, as
12073 + * published by the Free Software Foundation. Oracle designates this
12074 + * particular file as subject to the "Classpath" exception as provided
12075 + * by Oracle in the LICENSE file that accompanied this code.
12077 + * This code is distributed in the hope that it will be useful, but WITHOUT
12078 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12079 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12080 + * version 2 for more details (a copy is included in the LICENSE file that
12081 + * accompanied this code).
12083 + * You should have received a copy of the GNU General Public License version
12084 + * 2 along with this work; if not, write to the Free Software Foundation,
12085 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
12087 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
12088 + * or visit www.oracle.com if you need additional information or have any
12089 + * questions.
12090 + */
12092 +package sun.nio.fs;
12094 +/**
12095 + * Solaris specific system calls.
12096 + */
12098 +class SolarisNativeDispatcher extends UnixNativeDispatcher {
12099 + private SolarisNativeDispatcher() { }
12101 + /**
12102 + * int getextmntent(FILE *fp, struct extmnttab *mp, int len);
12103 + */
12104 + static native int getextmntent(long fp, UnixMountEntry entry)
12105 + throws UnixException;
12107 + /**
12108 + * int facl(int filedes, int cmd, int nentries, void aclbufp)
12109 + */
12110 + static native int facl(int fd, int cmd, int nentries, long aclbufp)
12111 + throws UnixException;
12114 + // initialize
12115 + private static native void init();
12117 + static {
12118 + jdk.internal.loader.BootLoader.loadLibrary("nio");
12119 + init();
12122 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisUserDefinedFileAttributeView.java jdk22u-jdk-22.0.2-ga/src/java.base/solaris/classes/sun/nio/fs/SolarisUserDefinedFileAttributeView.java
12123 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisUserDefinedFileAttributeView.java 1970-01-01 01:00:00.000000000 +0100
12124 +++ jdk22u-jdk-22.0.2-ga/src/java.base/solaris/classes/sun/nio/fs/SolarisUserDefinedFileAttributeView.java 2024-08-17 19:34:03.911992735 +0200
12125 @@ -0,0 +1,41 @@
12127 + * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
12128 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
12130 + * This code is free software; you can redistribute it and/or modify it
12131 + * under the terms of the GNU General Public License version 2 only, as
12132 + * published by the Free Software Foundation. Oracle designates this
12133 + * particular file as subject to the "Classpath" exception as provided
12134 + * by Oracle in the LICENSE file that accompanied this code.
12136 + * This code is distributed in the hope that it will be useful, but WITHOUT
12137 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12138 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12139 + * version 2 for more details (a copy is included in the LICENSE file that
12140 + * accompanied this code).
12142 + * You should have received a copy of the GNU General Public License version
12143 + * 2 along with this work; if not, write to the Free Software Foundation,
12144 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
12146 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
12147 + * or visit www.oracle.com if you need additional information or have any
12148 + * questions.
12149 + */
12151 +package sun.nio.fs;
12153 +class SolarisUserDefinedFileAttributeView
12154 + extends UnixUserDefinedFileAttributeView
12157 + SolarisUserDefinedFileAttributeView(UnixPath file, boolean followLinks) {
12158 + super(file, followLinks);
12161 + @Override
12162 + protected int maxNameLength() {
12163 + return 255;
12167 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisWatchService.java jdk22u-jdk-22.0.2-ga/src/java.base/solaris/classes/sun/nio/fs/SolarisWatchService.java
12168 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/classes/sun/nio/fs/SolarisWatchService.java 1970-01-01 01:00:00.000000000 +0100
12169 +++ jdk22u-jdk-22.0.2-ga/src/java.base/solaris/classes/sun/nio/fs/SolarisWatchService.java 2024-08-17 19:34:03.912625797 +0200
12170 @@ -0,0 +1,821 @@
12172 + * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
12173 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
12175 + * This code is free software; you can redistribute it and/or modify it
12176 + * under the terms of the GNU General Public License version 2 only, as
12177 + * published by the Free Software Foundation. Oracle designates this
12178 + * particular file as subject to the "Classpath" exception as provided
12179 + * by Oracle in the LICENSE file that accompanied this code.
12181 + * This code is distributed in the hope that it will be useful, but WITHOUT
12182 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12183 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12184 + * version 2 for more details (a copy is included in the LICENSE file that
12185 + * accompanied this code).
12187 + * You should have received a copy of the GNU General Public License version
12188 + * 2 along with this work; if not, write to the Free Software Foundation,
12189 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
12191 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
12192 + * or visit www.oracle.com if you need additional information or have any
12193 + * questions.
12194 + */
12196 +package sun.nio.fs;
12198 +import java.nio.file.*;
12199 +import java.util.*;
12200 +import java.io.IOException;
12201 +import jdk.internal.misc.Unsafe;
12203 +import static sun.nio.fs.UnixConstants.*;
12205 +/**
12206 + * Solaris implementation of WatchService based on file events notification
12207 + * facility.
12208 + */
12210 +class SolarisWatchService
12211 + extends AbstractWatchService
12213 + private static final Unsafe unsafe = Unsafe.getUnsafe();
12214 + private static int addressSize = unsafe.addressSize();
12216 + private static int dependsArch(int value32, int value64) {
12217 + return (addressSize == 4) ? value32 : value64;
12220 + /*
12221 + * typedef struct port_event {
12222 + * int portev_events;
12223 + * ushort_t portev_source;
12224 + * ushort_t portev_pad;
12225 + * uintptr_t portev_object;
12226 + * void *portev_user;
12227 + * } port_event_t;
12228 + */
12229 + private static final int SIZEOF_PORT_EVENT = dependsArch(16, 24);
12230 + private static final int OFFSETOF_EVENTS = 0;
12231 + private static final int OFFSETOF_SOURCE = 4;
12232 + private static final int OFFSETOF_OBJECT = 8;
12234 + /*
12235 + * typedef struct file_obj {
12236 + * timestruc_t fo_atime;
12237 + * timestruc_t fo_mtime;
12238 + * timestruc_t fo_ctime;
12239 + * uintptr_t fo_pad[3];
12240 + * char *fo_name;
12241 + * } file_obj_t;
12242 + */
12243 + private static final int SIZEOF_FILEOBJ = dependsArch(40, 80);
12244 + private static final int OFFSET_FO_NAME = dependsArch(36, 72);
12246 + // port sources
12247 + private static final short PORT_SOURCE_USER = 3;
12248 + private static final short PORT_SOURCE_FILE = 7;
12250 + // user-watchable events
12251 + private static final int FILE_MODIFIED = 0x00000002;
12252 + private static final int FILE_ATTRIB = 0x00000004;
12253 + private static final int FILE_NOFOLLOW = 0x10000000;
12255 + // exception events
12256 + private static final int FILE_DELETE = 0x00000010;
12257 + private static final int FILE_RENAME_TO = 0x00000020;
12258 + private static final int FILE_RENAME_FROM = 0x00000040;
12259 + private static final int UNMOUNTED = 0x20000000;
12260 + private static final int MOUNTEDOVER = 0x40000000;
12262 + // background thread to read change events
12263 + private final Poller poller;
12265 + SolarisWatchService(UnixFileSystem fs) throws IOException {
12266 + int port = -1;
12267 + try {
12268 + port = portCreate();
12269 + } catch (UnixException x) {
12270 + throw new IOException(x.errorString());
12273 + this.poller = new Poller(fs, this, port);
12274 + this.poller.start();
12277 + @Override
12278 + WatchKey register(Path dir,
12279 + WatchEvent.Kind<?>[] events,
12280 + WatchEvent.Modifier... modifiers)
12281 + throws IOException
12283 + // delegate to poller
12284 + return poller.register(dir, events, modifiers);
12287 + @Override
12288 + void implClose() throws IOException {
12289 + // delegate to poller
12290 + poller.close();
12293 + /**
12294 + * WatchKey implementation
12295 + */
12296 + private class SolarisWatchKey extends AbstractWatchKey
12297 + implements DirectoryNode
12299 + private final UnixFileKey fileKey;
12301 + // pointer to native file_obj object
12302 + private final long object;
12304 + // events (may be changed). set to null when watch key is invalid
12305 + private volatile Set<? extends WatchEvent.Kind<?>> events;
12307 + // map of entries in directory; created lazily; accessed only by
12308 + // poller thread.
12309 + private Map<Path,EntryNode> children = new HashMap<>();
12311 + SolarisWatchKey(SolarisWatchService watcher,
12312 + UnixPath dir,
12313 + UnixFileKey fileKey,
12314 + long object,
12315 + Set<? extends WatchEvent.Kind<?>> events)
12317 + super(dir, watcher);
12318 + this.fileKey = fileKey;
12319 + this.object = object;
12320 + this.events = events;
12323 + UnixPath getDirectory() {
12324 + return (UnixPath)watchable();
12327 + UnixFileKey getFileKey() {
12328 + return fileKey;
12331 + @Override
12332 + public long object() {
12333 + return object;
12336 + void invalidate() {
12337 + events = null;
12340 + Set<? extends WatchEvent.Kind<?>> events() {
12341 + return events;
12344 + void setEvents(Set<? extends WatchEvent.Kind<?>> events) {
12345 + this.events = events;
12348 + Map<Path,EntryNode> children() {
12349 + return children;
12352 + @Override
12353 + public boolean isValid() {
12354 + return events != null;
12357 + @Override
12358 + public void cancel() {
12359 + if (isValid()) {
12360 + // delegate to poller
12361 + poller.cancel(this);
12365 + @Override
12366 + public void addChild(Path name, EntryNode node) {
12367 + children.put(name, node);
12370 + @Override
12371 + public void removeChild(Path name) {
12372 + children.remove(name);
12375 + @Override
12376 + public EntryNode getChild(Path name) {
12377 + return children.get(name);
12381 + /**
12382 + * Background thread to read from port
12383 + */
12384 + private class Poller extends AbstractPoller {
12386 + // maximum number of events to read per call to port_getn
12387 + private static final int MAX_EVENT_COUNT = 128;
12389 + // events that map to ENTRY_DELETE
12390 + private static final int FILE_REMOVED =
12391 + (FILE_DELETE|FILE_RENAME_TO|FILE_RENAME_FROM);
12393 + // events that tell us not to re-associate the object
12394 + private static final int FILE_EXCEPTION =
12395 + (FILE_REMOVED|UNMOUNTED|MOUNTEDOVER);
12397 + // address of event buffers (used to receive events with port_getn)
12398 + private final long bufferAddress;
12400 + private final SolarisWatchService watcher;
12402 + // the I/O port
12403 + private final int port;
12405 + // maps file key (dev/inode) to WatchKey
12406 + private final Map<UnixFileKey,SolarisWatchKey> fileKey2WatchKey;
12408 + // maps file_obj object to Node
12409 + private final Map<Long,Node> object2Node;
12411 + /**
12412 + * Create a new instance
12413 + */
12414 + Poller(UnixFileSystem fs, SolarisWatchService watcher, int port) {
12415 + this.watcher = watcher;
12416 + this.port = port;
12417 + this.bufferAddress =
12418 + unsafe.allocateMemory(SIZEOF_PORT_EVENT * MAX_EVENT_COUNT);
12419 + this.fileKey2WatchKey = new HashMap<UnixFileKey,SolarisWatchKey>();
12420 + this.object2Node = new HashMap<Long,Node>();
12423 + @Override
12424 + void wakeup() throws IOException {
12425 + // write to port to wakeup polling thread
12426 + try {
12427 + portSend(port, 0);
12428 + } catch (UnixException x) {
12429 + throw new IOException(x.errorString());
12433 + @Override
12434 + Object implRegister(Path obj,
12435 + Set<? extends WatchEvent.Kind<?>> events,
12436 + WatchEvent.Modifier... modifiers)
12438 + // no modifiers supported at this time
12439 + if (modifiers.length > 0) {
12440 + for (WatchEvent.Modifier modifier: modifiers) {
12441 + if (modifier == null)
12442 + return new NullPointerException();
12443 + if (!ExtendedOptions.SENSITIVITY_HIGH.matches(modifier) &&
12444 + !ExtendedOptions.SENSITIVITY_MEDIUM.matches(modifier) &&
12445 + !ExtendedOptions.SENSITIVITY_LOW.matches(modifier)) {
12446 + return new UnsupportedOperationException("Modifier not supported");
12451 + UnixPath dir = (UnixPath)obj;
12453 + // check file is directory
12454 + UnixFileAttributes attrs = null;
12455 + try {
12456 + attrs = UnixFileAttributes.get(dir, true);
12457 + } catch (UnixException x) {
12458 + return x.asIOException(dir);
12460 + if (!attrs.isDirectory()) {
12461 + return new NotDirectoryException(dir.getPathForExceptionMessage());
12464 + // if already registered then update the events and return existing key
12465 + UnixFileKey fileKey = attrs.fileKey();
12466 + SolarisWatchKey watchKey = fileKey2WatchKey.get(fileKey);
12467 + if (watchKey != null) {
12468 + try {
12469 + updateEvents(watchKey, events);
12470 + } catch (UnixException x) {
12471 + return x.asIOException(dir);
12473 + return watchKey;
12476 + // register directory
12477 + long object = 0L;
12478 + try {
12479 + object = registerImpl(dir, (FILE_MODIFIED | FILE_ATTRIB));
12480 + } catch (UnixException x) {
12481 + return x.asIOException(dir);
12484 + // create watch key and insert it into maps
12485 + watchKey = new SolarisWatchKey(watcher, dir, fileKey, object, events);
12486 + object2Node.put(object, watchKey);
12487 + fileKey2WatchKey.put(fileKey, watchKey);
12489 + // register all entries in directory
12490 + registerChildren(dir, watchKey, false, false);
12492 + return watchKey;
12495 + // release resources for single entry
12496 + void releaseChild(EntryNode node) {
12497 + long object = node.object();
12498 + if (object != 0L) {
12499 + object2Node.remove(object);
12500 + releaseObject(object, true);
12501 + node.setObject(0L);
12505 + // release resources for entries in directory
12506 + void releaseChildren(SolarisWatchKey key) {
12507 + for (EntryNode node: key.children().values()) {
12508 + releaseChild(node);
12512 + // cancel single key
12513 + @Override
12514 + void implCancelKey(WatchKey obj) {
12515 + SolarisWatchKey key = (SolarisWatchKey)obj;
12516 + if (key.isValid()) {
12517 + fileKey2WatchKey.remove(key.getFileKey());
12519 + // release resources for entries
12520 + releaseChildren(key);
12522 + // release resources for directory
12523 + long object = key.object();
12524 + object2Node.remove(object);
12525 + releaseObject(object, true);
12527 + // and finally invalidate the key
12528 + key.invalidate();
12532 + // close watch service
12533 + @Override
12534 + void implCloseAll() {
12535 + // release all native resources
12536 + for (Long object: object2Node.keySet()) {
12537 + releaseObject(object, true);
12540 + // invalidate all keys
12541 + for (Map.Entry<UnixFileKey,SolarisWatchKey> entry: fileKey2WatchKey.entrySet()) {
12542 + entry.getValue().invalidate();
12545 + // clean-up
12546 + object2Node.clear();
12547 + fileKey2WatchKey.clear();
12549 + // free global resources
12550 + unsafe.freeMemory(bufferAddress);
12551 + UnixNativeDispatcher.close(port, e -> null);
12554 + /**
12555 + * Poller main loop. Blocks on port_getn waiting for events and then
12556 + * processes them.
12557 + */
12558 + @Override
12559 + public void run() {
12560 + try {
12561 + for (;;) {
12562 + int n = portGetn(port, bufferAddress, MAX_EVENT_COUNT);
12563 + assert n > 0;
12565 + long address = bufferAddress;
12566 + for (int i=0; i<n; i++) {
12567 + boolean shutdown = processEvent(address);
12568 + if (shutdown)
12569 + return;
12570 + address += SIZEOF_PORT_EVENT;
12573 + } catch (UnixException x) {
12574 + x.printStackTrace();
12578 + /**
12579 + * Process a single port_event
12581 + * Returns true if poller thread is requested to shutdown.
12582 + */
12583 + boolean processEvent(long address) {
12584 + // pe->portev_source
12585 + short source = unsafe.getShort(address + OFFSETOF_SOURCE);
12586 + // pe->portev_object
12587 + long object = unsafe.getAddress(address + OFFSETOF_OBJECT);
12588 + // pe->portev_events
12589 + int events = unsafe.getInt(address + OFFSETOF_EVENTS);
12591 + // user event is trigger to process pending requests
12592 + if (source != PORT_SOURCE_FILE) {
12593 + if (source == PORT_SOURCE_USER) {
12594 + // process any pending requests
12595 + boolean shutdown = processRequests();
12596 + if (shutdown)
12597 + return true;
12599 + return false;
12602 + // lookup object to get Node
12603 + Node node = object2Node.get(object);
12604 + if (node == null) {
12605 + // should not happen
12606 + return false;
12609 + // As a workaround for 6642290 and 6636438/6636412 we don't use
12610 + // FILE_EXCEPTION events to tell use not to register the file.
12611 + // boolean reregister = (events & FILE_EXCEPTION) == 0;
12612 + boolean reregister = true;
12614 + // If node is EntryNode then event relates to entry in directory
12615 + // If node is a SolarisWatchKey (DirectoryNode) then event relates
12616 + // to a watched directory.
12617 + boolean isDirectory = (node instanceof SolarisWatchKey);
12618 + if (isDirectory) {
12619 + processDirectoryEvents((SolarisWatchKey)node, events);
12620 + } else {
12621 + boolean ignore = processEntryEvents((EntryNode)node, events);
12622 + if (ignore)
12623 + reregister = false;
12626 + // need to re-associate to get further events
12627 + if (reregister) {
12628 + try {
12629 + events = FILE_MODIFIED | FILE_ATTRIB;
12630 + if (!isDirectory) events |= FILE_NOFOLLOW;
12631 + portAssociate(port,
12632 + PORT_SOURCE_FILE,
12633 + object,
12634 + events);
12635 + } catch (UnixException x) {
12636 + // unable to re-register
12637 + reregister = false;
12641 + // object is not re-registered so release resources. If
12642 + // object is a watched directory then signal key
12643 + if (!reregister) {
12644 + // release resources
12645 + object2Node.remove(object);
12646 + releaseObject(object, false);
12648 + // if watch key then signal it
12649 + if (isDirectory) {
12650 + SolarisWatchKey key = (SolarisWatchKey)node;
12651 + fileKey2WatchKey.remove( key.getFileKey() );
12652 + key.invalidate();
12653 + key.signal();
12654 + } else {
12655 + // if entry then remove it from parent
12656 + EntryNode entry = (EntryNode)node;
12657 + SolarisWatchKey key = (SolarisWatchKey)entry.parent();
12658 + key.removeChild(entry.name());
12662 + return false;
12665 + /**
12666 + * Process directory events. If directory is modified then re-scan
12667 + * directory to register any new entries
12668 + */
12669 + void processDirectoryEvents(SolarisWatchKey key, int mask) {
12670 + if ((mask & (FILE_MODIFIED | FILE_ATTRIB)) != 0) {
12671 + registerChildren(key.getDirectory(), key,
12672 + key.events().contains(StandardWatchEventKinds.ENTRY_CREATE),
12673 + key.events().contains(StandardWatchEventKinds.ENTRY_DELETE));
12677 + /**
12678 + * Process events for entries in registered directories. Returns {@code
12679 + * true} if events are ignored because the watch key has been cancelled.
12680 + */
12681 + boolean processEntryEvents(EntryNode node, int mask) {
12682 + SolarisWatchKey key = (SolarisWatchKey)node.parent();
12683 + Set<? extends WatchEvent.Kind<?>> events = key.events();
12684 + if (events == null) {
12685 + // key has been cancelled so ignore event
12686 + return true;
12689 + // entry modified
12690 + if (((mask & (FILE_MODIFIED | FILE_ATTRIB)) != 0) &&
12691 + events.contains(StandardWatchEventKinds.ENTRY_MODIFY))
12693 + key.signalEvent(StandardWatchEventKinds.ENTRY_MODIFY, node.name());
12697 + return false;
12700 + /**
12701 + * Registers all entries in the given directory
12703 + * The {@code sendCreateEvents} and {@code sendDeleteEvents} parameters
12704 + * indicates if ENTRY_CREATE and ENTRY_DELETE events should be queued
12705 + * when new entries are found. When initially registering a directory
12706 + * they will always be false. When re-scanning a directory then it
12707 + * depends on if the events are enabled or not.
12708 + */
12709 + void registerChildren(UnixPath dir,
12710 + SolarisWatchKey parent,
12711 + boolean sendCreateEvents,
12712 + boolean sendDeleteEvents)
12714 + boolean isModifyEnabled =
12715 + parent.events().contains(StandardWatchEventKinds.ENTRY_MODIFY) ;
12717 + // reset visited flag on entries so that we can detect file deletes
12718 + for (EntryNode node: parent.children().values()) {
12719 + node.setVisited(false);
12722 + try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
12723 + for (Path entry: stream) {
12724 + Path name = entry.getFileName();
12726 + // skip entry if already registered
12727 + EntryNode node = parent.getChild(name);
12728 + if (node != null) {
12729 + node.setVisited(true);
12730 + continue;
12733 + // new entry found
12735 + long object = 0L;
12736 + int errno = 0;
12737 + boolean addNode = false;
12739 + // if ENTRY_MODIFY enabled then we register the entry for events
12740 + if (isModifyEnabled) {
12741 + try {
12742 + UnixPath path = (UnixPath)entry;
12743 + int events = (FILE_NOFOLLOW | FILE_MODIFIED | FILE_ATTRIB);
12744 + object = registerImpl(path, events);
12745 + addNode = true;
12746 + } catch (UnixException x) {
12747 + errno = x.errno();
12749 + } else {
12750 + addNode = true;
12753 + if (addNode) {
12754 + // create node
12755 + node = new EntryNode(object, (UnixPath)entry.getFileName(), parent);
12756 + node.setVisited(true);
12757 + // tell the parent about it
12758 + parent.addChild(entry.getFileName(), node);
12759 + if (object != 0L)
12760 + object2Node.put(object, node);
12763 + // send ENTRY_CREATE event for the new file
12764 + // send ENTRY_DELETE event for files that were deleted immediately
12765 + boolean deleted = (errno == ENOENT);
12766 + if (sendCreateEvents && (addNode || deleted))
12767 + parent.signalEvent(StandardWatchEventKinds.ENTRY_CREATE, name);
12768 + if (sendDeleteEvents && deleted)
12769 + parent.signalEvent(StandardWatchEventKinds.ENTRY_DELETE, name);
12772 + } catch (DirectoryIteratorException | IOException x) {
12773 + // queue OVERFLOW event so that user knows to re-scan directory
12774 + parent.signalEvent(StandardWatchEventKinds.OVERFLOW, null);
12775 + return;
12778 + // clean-up and send ENTRY_DELETE events for any entries that were
12779 + // not found
12780 + Iterator<Map.Entry<Path,EntryNode>> iterator =
12781 + parent.children().entrySet().iterator();
12782 + while (iterator.hasNext()) {
12783 + Map.Entry<Path,EntryNode> entry = iterator.next();
12784 + EntryNode node = entry.getValue();
12785 + if (!node.isVisited()) {
12786 + long object = node.object();
12787 + if (object != 0L) {
12788 + object2Node.remove(object);
12789 + releaseObject(object, true);
12791 + if (sendDeleteEvents)
12792 + parent.signalEvent(StandardWatchEventKinds.ENTRY_DELETE, node.name());
12793 + iterator.remove();
12798 + /**
12799 + * Update watch key's events. If ENTRY_MODIFY changes to be enabled
12800 + * then register each file in the directory; If ENTRY_MODIFY changed to
12801 + * be disabled then unregister each file.
12802 + */
12803 + void updateEvents(SolarisWatchKey key, Set<? extends WatchEvent.Kind<?>> events)
12804 + throws UnixException
12807 + // update events, remembering if ENTRY_MODIFY was previously
12808 + // enabled or disabled.
12809 + boolean oldModifyEnabled = key.events()
12810 + .contains(StandardWatchEventKinds.ENTRY_MODIFY);
12811 + key.setEvents(events);
12813 + // check if ENTRY_MODIFY has changed
12814 + boolean newModifyEnabled = events
12815 + .contains(StandardWatchEventKinds.ENTRY_MODIFY);
12816 + if (newModifyEnabled != oldModifyEnabled) {
12817 + UnixException ex = null;
12818 + for (EntryNode node: key.children().values()) {
12819 + if (newModifyEnabled) {
12820 + // register
12821 + UnixPath path = key.getDirectory().resolve(node.name());
12822 + int ev = (FILE_NOFOLLOW | FILE_MODIFIED | FILE_ATTRIB);
12823 + try {
12824 + long object = registerImpl(path, ev);
12825 + object2Node.put(object, node);
12826 + node.setObject(object);
12827 + } catch (UnixException x) {
12828 + // if file has been deleted then it will be detected
12829 + // as a FILE_MODIFIED event on the directory
12830 + if (x.errno() != ENOENT) {
12831 + ex = x;
12832 + break;
12835 + } else {
12836 + // unregister
12837 + releaseChild(node);
12841 + // an error occurred
12842 + if (ex != null) {
12843 + releaseChildren(key);
12844 + throw ex;
12849 + /**
12850 + * Calls port_associate to register the given path.
12851 + * Returns pointer to fileobj structure that is allocated for
12852 + * the registration.
12853 + */
12854 + long registerImpl(UnixPath dir, int events)
12855 + throws UnixException
12857 + // allocate memory for the path (file_obj->fo_name field)
12858 + byte[] path = dir.getByteArrayForSysCalls();
12859 + int len = path.length;
12860 + long name = unsafe.allocateMemory(len+1);
12861 + unsafe.copyMemory(path, Unsafe.ARRAY_BYTE_BASE_OFFSET, null,
12862 + name, (long)len);
12863 + unsafe.putByte(name + len, (byte)0);
12865 + // allocate memory for filedatanode structure - this is the object
12866 + // to port_associate
12867 + long object = unsafe.allocateMemory(SIZEOF_FILEOBJ);
12868 + unsafe.setMemory(null, object, SIZEOF_FILEOBJ, (byte)0);
12869 + unsafe.putAddress(object + OFFSET_FO_NAME, name);
12871 + // associate the object with the port
12872 + try {
12873 + portAssociate(port,
12874 + PORT_SOURCE_FILE,
12875 + object,
12876 + events);
12877 + } catch (UnixException x) {
12878 + // debugging
12879 + if (x.errno() == EAGAIN) {
12880 + System.err.println("The maximum number of objects associated "+
12881 + "with the port has been reached");
12884 + unsafe.freeMemory(name);
12885 + unsafe.freeMemory(object);
12886 + throw x;
12888 + return object;
12891 + /**
12892 + * Frees all resources for an file_obj object; optionally remove
12893 + * association from port
12894 + */
12895 + void releaseObject(long object, boolean dissociate) {
12896 + // remove association
12897 + if (dissociate) {
12898 + try {
12899 + portDissociate(port, PORT_SOURCE_FILE, object);
12900 + } catch (UnixException x) {
12901 + // ignore
12905 + // free native memory
12906 + long name = unsafe.getAddress(object + OFFSET_FO_NAME);
12907 + unsafe.freeMemory(name);
12908 + unsafe.freeMemory(object);
12912 + /**
12913 + * A node with native (file_obj) resources
12914 + */
12915 + private static interface Node {
12916 + long object();
12919 + /**
12920 + * A directory node with a map of the entries in the directory
12921 + */
12922 + private static interface DirectoryNode extends Node {
12923 + void addChild(Path name, EntryNode node);
12924 + void removeChild(Path name);
12925 + EntryNode getChild(Path name);
12928 + /**
12929 + * An implementation of a node that is an entry in a directory.
12930 + */
12931 + private static class EntryNode implements Node {
12932 + private long object;
12933 + private final UnixPath name;
12934 + private final DirectoryNode parent;
12935 + private boolean visited;
12937 + EntryNode(long object, UnixPath name, DirectoryNode parent) {
12938 + this.object = object;
12939 + this.name = name;
12940 + this.parent = parent;
12943 + @Override
12944 + public long object() {
12945 + return object;
12948 + void setObject(long ptr) {
12949 + this.object = ptr;
12952 + UnixPath name() {
12953 + return name;
12956 + DirectoryNode parent() {
12957 + return parent;
12960 + boolean isVisited() {
12961 + return visited;
12964 + void setVisited(boolean v) {
12965 + this.visited = v;
12969 + // -- native methods --
12971 + private static native void init();
12973 + private static native int portCreate() throws UnixException;
12975 + private static native void portAssociate(int port, int source, long object, int events)
12976 + throws UnixException;
12978 + private static native void portDissociate(int port, int source, long object)
12979 + throws UnixException;
12981 + private static native void portSend(int port, int events)
12982 + throws UnixException;
12984 + private static native int portGetn(int port, long address, int max)
12985 + throws UnixException;
12987 + static {
12988 + jdk.internal.loader.BootLoader.loadLibrary("nio");
12989 + init();
12992 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/native/libjava/ProcessHandleImpl_solaris.c jdk22u-jdk-22.0.2-ga/src/java.base/solaris/native/libjava/ProcessHandleImpl_solaris.c
12993 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/native/libjava/ProcessHandleImpl_solaris.c 1970-01-01 01:00:00.000000000 +0100
12994 +++ jdk22u-jdk-22.0.2-ga/src/java.base/solaris/native/libjava/ProcessHandleImpl_solaris.c 2024-08-17 19:34:03.913003482 +0200
12995 @@ -0,0 +1,51 @@
12997 + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
12998 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
13000 + * This code is free software; you can redistribute it and/or modify it
13001 + * under the terms of the GNU General Public License version 2 only, as
13002 + * published by the Free Software Foundation. Oracle designates this
13003 + * particular file as subject to the "Classpath" exception as provided
13004 + * by Oracle in the LICENSE file that accompanied this code.
13006 + * This code is distributed in the hope that it will be useful, but WITHOUT
13007 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13008 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13009 + * version 2 for more details (a copy is included in the LICENSE file that
13010 + * accompanied this code).
13012 + * You should have received a copy of the GNU General Public License version
13013 + * 2 along with this work; if not, write to the Free Software Foundation,
13014 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
13016 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
13017 + * or visit www.oracle.com if you need additional information or have any
13018 + * questions.
13019 + */
13021 +#include "jni.h"
13023 +#include "ProcessHandleImpl_unix.h"
13025 +#include <procfs.h>
13028 + * Implementation of native ProcessHandleImpl functions for Solaris.
13029 + * See ProcessHandleImpl_unix.c for more details.
13030 + */
13032 +void os_initNative(JNIEnv *env, jclass clazz) {}
13034 +jint os_getChildren(JNIEnv *env, jlong jpid, jlongArray jarray,
13035 + jlongArray jparentArray, jlongArray jstimesArray) {
13036 + return unix_getChildren(env, jpid, jarray, jparentArray, jstimesArray);
13039 +pid_t os_getParentPidAndTimings(JNIEnv *env, pid_t pid, jlong *total, jlong *start) {
13040 + return unix_getParentPidAndTimings(env, pid, total, start);
13043 +void os_getCmdlineAndUserInfo(JNIEnv *env, jobject jinfo, pid_t pid) {
13044 + unix_getCmdlineAndUserInfo(env, jinfo, pid);
13047 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/native/libjvm_db/libjvm_db.c jdk22u-jdk-22.0.2-ga/src/java.base/solaris/native/libjvm_db/libjvm_db.c
13048 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/native/libjvm_db/libjvm_db.c 1970-01-01 01:00:00.000000000 +0100
13049 +++ jdk22u-jdk-22.0.2-ga/src/java.base/solaris/native/libjvm_db/libjvm_db.c 2024-08-17 19:34:03.914038278 +0200
13050 @@ -0,0 +1,1552 @@
13052 + * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
13053 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
13055 + * This code is free software; you can redistribute it and/or modify it
13056 + * under the terms of the GNU General Public License version 2 only, as
13057 + * published by the Free Software Foundation.
13059 + * This code is distributed in the hope that it will be useful, but WITHOUT
13060 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13061 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13062 + * version 2 for more details (a copy is included in the LICENSE file that
13063 + * accompanied this code).
13065 + * You should have received a copy of the GNU General Public License version
13066 + * 2 along with this work; if not, write to the Free Software Foundation,
13067 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
13069 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
13070 + * or visit www.oracle.com if you need additional information or have any
13071 + * questions.
13073 + */
13075 +#include <stdio.h>
13076 +#include <stdlib.h>
13077 +#include <string.h>
13078 +#include <errno.h>
13079 +#include <gelf.h>
13081 +#include "libjvm_db.h"
13082 +#include "JvmOffsets.h"
13084 +#define LIBJVM_SO "libjvm.so"
13086 +#if defined(i386) || defined(__i386) || defined(__amd64)
13087 +#ifdef COMPILER2
13088 +#define X86_COMPILER2
13089 +#endif /* COMPILER2 */
13090 +#endif /* i386 */
13092 +typedef struct {
13093 + short vf_cnt; /* number of recognized java vframes */
13094 + short bci; /* current frame method byte code index */
13095 + int line; /* current frame method source line */
13096 + uint64_t new_fp; /* fp for the next frame */
13097 + uint64_t new_pc; /* pc for the next frame */
13098 + uint64_t new_sp; /* "raw" sp for the next frame (includes extension by interpreter/adapter */
13099 + char locinf; /* indicates there is valid location info */
13100 +} Jframe_t;
13102 +int Jlookup_by_regs(jvm_agent_t* J, const prgregset_t regs, char *name,
13103 + size_t size, Jframe_t *jframe);
13105 +int main(int arg) { return arg; }
13107 +static int debug = 0;
13109 +static void failed(int err, const char * file, int line) {
13110 + if (debug) {
13111 + fprintf(stderr, "failed %d at %s:%d\n", err, file, line);
13115 +static void warn(const char * file, int line, const char * msg) {
13116 + if (debug) {
13117 + fprintf(stderr, "warning: %s at %s:%d\n", msg, file, line);
13121 +static void warn1(const char * file, int line, const char * msg, intptr_t arg1) {
13122 + if (debug) {
13123 + fprintf(stderr, "warning: ");
13124 + fprintf(stderr, msg, arg1);
13125 + fprintf(stderr, " at %s:%d\n", file, line);
13129 +#define CHECK_FAIL(err) \
13130 + if (err != PS_OK) { failed(err, __FILE__, __LINE__); goto fail; }
13131 +#define WARN(msg) warn(__FILE__, __LINE__, msg)
13132 +#define WARN1(msg, arg1) warn1(__FILE__, __LINE__, msg, arg1)
13134 +typedef struct VMStructEntry {
13135 + const char * typeName; /* The type name containing the given field (example: "Klass") */
13136 + const char * fieldName; /* The field name within the type (example: "_name") */
13137 + uint64_t address; /* Address of field; only used for static fields */
13138 + /* ("offset" can not be reused because of apparent solstudio compiler bug */
13139 + /* in generation of initializer data) */
13140 +} VMStructEntry;
13142 +/* Prototyping inlined methods */
13144 +int sprintf(char *s, const char *format, ...);
13146 +#define SZ16 sizeof(int16_t)
13147 +#define SZ32 sizeof(int32_t)
13149 +#define COMP_METHOD_SIGN '*'
13151 +#define MAX_VFRAMES_CNT 256
13153 +typedef struct vframe {
13154 + uint64_t method;
13155 + int32_t sender_decode_offset;
13156 + int32_t methodIdx;
13157 + int32_t bci;
13158 + int32_t line;
13159 +} Vframe_t;
13161 +typedef struct frame {
13162 + uintptr_t fp;
13163 + uintptr_t pc;
13164 + uintptr_t sp;
13165 + uintptr_t sender_sp; // The unextended sp of the caller
13166 +} Frame_t;
13168 +typedef struct Nmethod_t {
13169 + struct jvm_agent* J;
13170 + Jframe_t *jframe;
13172 + uint64_t nm; /* _nmethod */
13173 + uint64_t pc;
13174 + uint64_t pc_desc;
13176 + int32_t orig_pc_offset; /* _orig_pc_offset */
13177 + uint64_t instrs_beg; /* _code_offset */
13178 + uint64_t instrs_end;
13179 + uint64_t deopt_beg; /* _deoptimize_offset */
13180 + uint64_t scopes_data_beg; /* _scopes_data_begin */
13181 + int32_t scopes_data_end;
13182 + int32_t metadata_beg; /* _metadata_offset */
13183 + int32_t metadata_end;
13184 + int32_t scopes_pcs_beg; /* _scopes_pcs_offset */
13185 + int32_t scopes_pcs_end;
13187 + int vf_cnt;
13188 + Vframe_t vframes[MAX_VFRAMES_CNT];
13189 +} Nmethod_t;
13191 +struct jvm_agent {
13192 + struct ps_prochandle* P;
13194 + uint64_t nmethod_vtbl;
13195 + uint64_t CodeBlob_vtbl;
13196 + uint64_t BufferBlob_vtbl;
13197 + uint64_t RuntimeStub_vtbl;
13198 + uint64_t Method_vtbl;
13200 + uint64_t Use_Compressed_Oops_address;
13201 + uint64_t Universe_narrow_oop_base_address;
13202 + uint64_t Universe_narrow_oop_shift_address;
13203 + uint64_t CodeCache_heaps_address;
13205 + /* Volatiles */
13206 + uint8_t Use_Compressed_Oops;
13207 + uint64_t Universe_narrow_oop_base;
13208 + uint32_t Universe_narrow_oop_shift;
13209 + // Code cache heaps
13210 + int32_t Number_of_heaps;
13211 + uint64_t* Heap_low;
13212 + uint64_t* Heap_high;
13213 + uint64_t* Heap_segmap_low;
13214 + uint64_t* Heap_segmap_high;
13216 + int32_t SIZE_CodeCache_log2_segment;
13218 + uint64_t methodPtr;
13219 + uint64_t bcp;
13221 + Nmethod_t *N; /*Inlined methods support */
13222 + Frame_t prev_fr;
13223 + Frame_t curr_fr;
13226 +static int
13227 +read_string(struct ps_prochandle *P,
13228 + char *buf, /* caller's buffer */
13229 + size_t size, /* upper limit on bytes to read */
13230 + uintptr_t addr) /* address in process */
13232 + int err = PS_OK;
13233 + while (size-- > 1 && err == PS_OK) {
13234 + err = ps_pread(P, addr, buf, 1);
13235 + if (*buf == '\0') {
13236 + return PS_OK;
13238 + addr += 1;
13239 + buf += 1;
13241 + return -1;
13244 +static int read_compressed_pointer(jvm_agent_t* J, uint64_t base, uint32_t *ptr) {
13245 + int err = -1;
13246 + uint32_t ptr32;
13247 + err = ps_pread(J->P, base, &ptr32, sizeof(uint32_t));
13248 + *ptr = ptr32;
13249 + return err;
13252 +static int read_pointer(jvm_agent_t* J, uint64_t base, uint64_t* ptr) {
13253 + int err = -1;
13254 + uint32_t ptr32;
13256 + switch (DATA_MODEL) {
13257 + case PR_MODEL_LP64:
13258 + err = ps_pread(J->P, base, ptr, sizeof(uint64_t));
13259 + break;
13260 + case PR_MODEL_ILP32:
13261 + err = ps_pread(J->P, base, &ptr32, sizeof(uint32_t));
13262 + *ptr = ptr32;
13263 + break;
13266 + return err;
13269 +static int read_string_pointer(jvm_agent_t* J, uint64_t base, const char ** stringp) {
13270 + uint64_t ptr;
13271 + int err;
13272 + char buffer[1024];
13274 + *stringp = NULL;
13275 + err = read_pointer(J, base, &ptr);
13276 + CHECK_FAIL(err);
13277 + if (ptr != 0) {
13278 + err = read_string(J->P, buffer, sizeof(buffer), ptr);
13279 + CHECK_FAIL(err);
13280 + *stringp = strdup(buffer);
13282 + return PS_OK;
13284 + fail:
13285 + return err;
13288 +static int parse_vmstruct_entry(jvm_agent_t* J, uint64_t base, VMStructEntry* vmp) {
13289 + uint64_t ptr;
13290 + int err;
13292 + err = read_string_pointer(J, base + OFFSET_VMStructEntrytypeName, &vmp->typeName);
13293 + CHECK_FAIL(err);
13294 + err = read_string_pointer(J, base + OFFSET_VMStructEntryfieldName, &vmp->fieldName);
13295 + CHECK_FAIL(err);
13296 + err = read_pointer(J, base + OFFSET_VMStructEntryaddress, &vmp->address);
13297 + CHECK_FAIL(err);
13299 + return PS_OK;
13301 + fail:
13302 + if (vmp->typeName != NULL) free((void*)vmp->typeName);
13303 + if (vmp->fieldName != NULL) free((void*)vmp->fieldName);
13304 + return err;
13307 +static int parse_vmstructs(jvm_agent_t* J) {
13308 + VMStructEntry vmVar;
13309 + VMStructEntry* vmp = &vmVar;
13310 + uint64_t gHotSpotVMStructs;
13311 + psaddr_t sym_addr;
13312 + uint64_t base;
13313 + int err;
13315 + /* Clear *vmp now in case we jump to fail: */
13316 + memset(vmp, 0, sizeof(VMStructEntry));
13318 + err = ps_pglobal_lookup(J->P, LIBJVM_SO, "gHotSpotVMStructs", &sym_addr);
13319 + CHECK_FAIL(err);
13320 + err = read_pointer(J, sym_addr, &gHotSpotVMStructs);
13321 + CHECK_FAIL(err);
13322 + base = gHotSpotVMStructs;
13324 + err = PS_OK;
13325 + while (err == PS_OK) {
13326 + memset(vmp, 0, sizeof(VMStructEntry));
13327 + err = parse_vmstruct_entry(J, base, vmp);
13328 + if (err != PS_OK || vmp->typeName == NULL) {
13329 + break;
13332 + if (vmp->typeName[0] == 'C' && strcmp("CodeCache", vmp->typeName) == 0) {
13333 + /* Read _heaps field of type GrowableArray<CodeHeaps*>* */
13334 + if (strcmp("_heaps", vmp->fieldName) == 0) {
13335 + err = read_pointer(J, vmp->address, &J->CodeCache_heaps_address);
13337 + } else if (vmp->typeName[0] == 'U' && strcmp("Universe", vmp->typeName) == 0) {
13338 + if (strcmp("_narrow_oop._base", vmp->fieldName) == 0) {
13339 + J->Universe_narrow_oop_base_address = vmp->address;
13341 + if (strcmp("_narrow_oop._shift", vmp->fieldName) == 0) {
13342 + J->Universe_narrow_oop_shift_address = vmp->address;
13345 + CHECK_FAIL(err);
13347 + base += SIZE_VMStructEntry;
13348 + if (vmp->typeName != NULL) free((void*)vmp->typeName);
13349 + if (vmp->fieldName != NULL) free((void*)vmp->fieldName);
13352 + return PS_OK;
13354 + fail:
13355 + if (vmp->typeName != NULL) free((void*)vmp->typeName);
13356 + if (vmp->fieldName != NULL) free((void*)vmp->fieldName);
13357 + return -1;
13360 +static int find_symbol(jvm_agent_t* J, const char *name, uint64_t* valuep) {
13361 + psaddr_t sym_addr;
13362 + int err;
13364 + err = ps_pglobal_lookup(J->P, LIBJVM_SO, name, &sym_addr);
13365 + if (err != PS_OK) goto fail;
13366 + *valuep = sym_addr;
13367 + return PS_OK;
13369 + fail:
13370 + return err;
13373 +static int read_volatiles(jvm_agent_t* J) {
13374 + int i;
13375 + uint64_t array_data;
13376 + uint64_t code_heap_address;
13377 + int err;
13379 + err = find_symbol(J, "UseCompressedOops", &J->Use_Compressed_Oops_address);
13380 + if (err == PS_OK) {
13381 + err = ps_pread(J->P, J->Use_Compressed_Oops_address, &J->Use_Compressed_Oops, sizeof(uint8_t));
13382 + CHECK_FAIL(err);
13383 + } else {
13384 + J->Use_Compressed_Oops = 0;
13387 + err = read_pointer(J, J->Universe_narrow_oop_base_address, &J->Universe_narrow_oop_base);
13388 + CHECK_FAIL(err);
13389 + err = ps_pread(J->P, J->Universe_narrow_oop_shift_address, &J->Universe_narrow_oop_shift, sizeof(uint32_t));
13390 + CHECK_FAIL(err);
13392 + /* CodeCache_heaps_address points to GrowableArray<CodeHeaps*>, read _data field
13393 + pointing to the first entry of type CodeCache* in the array */
13394 + err = read_pointer(J, J->CodeCache_heaps_address + OFFSET_GrowableArray_CodeHeap_data, &array_data);
13395 + /* Read _len field containing the number of code heaps */
13396 + err = ps_pread(J->P, J->CodeCache_heaps_address + OFFSET_GrowableArray_CodeHeap_len,
13397 + &J->Number_of_heaps, sizeof(J->Number_of_heaps));
13399 + /* Allocate memory for heap configurations */
13400 + J->Heap_low = (uint64_t*)calloc(J->Number_of_heaps, sizeof(uint64_t));
13401 + J->Heap_high = (uint64_t*)calloc(J->Number_of_heaps, sizeof(uint64_t));
13402 + J->Heap_segmap_low = (uint64_t*)calloc(J->Number_of_heaps, sizeof(uint64_t));
13403 + J->Heap_segmap_high = (uint64_t*)calloc(J->Number_of_heaps, sizeof(uint64_t));
13405 + /* Read code heap configurations */
13406 + for (i = 0; i < J->Number_of_heaps; ++i) {
13407 + /* Read address of heap */
13408 + err = read_pointer(J, array_data, &code_heap_address);
13409 + CHECK_FAIL(err);
13411 + err = read_pointer(J, code_heap_address + OFFSET_CodeHeap_memory +
13412 + OFFSET_VirtualSpace_low, &J->Heap_low[i]);
13413 + CHECK_FAIL(err);
13414 + err = read_pointer(J, code_heap_address + OFFSET_CodeHeap_memory +
13415 + OFFSET_VirtualSpace_high, &J->Heap_high[i]);
13416 + CHECK_FAIL(err);
13417 + err = read_pointer(J, code_heap_address + OFFSET_CodeHeap_segmap +
13418 + OFFSET_VirtualSpace_low, &J->Heap_segmap_low[i]);
13419 + CHECK_FAIL(err);
13420 + err = read_pointer(J, code_heap_address + OFFSET_CodeHeap_segmap +
13421 + OFFSET_VirtualSpace_high, &J->Heap_segmap_high[i]);
13422 + CHECK_FAIL(err);
13424 + /* Increment pointer to next entry */
13425 + array_data = array_data + POINTER_SIZE;
13428 + err = ps_pread(J->P, code_heap_address + OFFSET_CodeHeap_log2_segment_size,
13429 + &J->SIZE_CodeCache_log2_segment, sizeof(J->SIZE_CodeCache_log2_segment));
13430 + CHECK_FAIL(err);
13432 + return PS_OK;
13434 + fail:
13435 + return err;
13438 +static int codeheap_contains(int heap_num, jvm_agent_t* J, uint64_t ptr) {
13439 + return (J->Heap_low[heap_num] <= ptr && ptr < J->Heap_high[heap_num]);
13442 +static int codecache_contains(jvm_agent_t* J, uint64_t ptr) {
13443 + int i;
13444 + for (i = 0; i < J->Number_of_heaps; ++i) {
13445 + if (codeheap_contains(i, J, ptr)) {
13446 + return 1;
13449 + return 0;
13452 +static uint64_t segment_for(int heap_num, jvm_agent_t* J, uint64_t p) {
13453 + return (p - J->Heap_low[heap_num]) >> J->SIZE_CodeCache_log2_segment;
13456 +static uint64_t block_at(int heap_num, jvm_agent_t* J, int i) {
13457 + return J->Heap_low[heap_num] + (i << J->SIZE_CodeCache_log2_segment);
13460 +static int find_start(jvm_agent_t* J, uint64_t ptr, uint64_t *startp) {
13461 + int err;
13462 + int i;
13464 + for (i = 0; i < J->Number_of_heaps; ++i) {
13465 + *startp = 0;
13466 + if (codeheap_contains(i, J, ptr)) {
13467 + int32_t used;
13468 + uint64_t segment = segment_for(i, J, ptr);
13469 + uint64_t block = J->Heap_segmap_low[i];
13470 + uint8_t tag;
13471 + err = ps_pread(J->P, block + segment, &tag, sizeof(tag));
13472 + CHECK_FAIL(err);
13473 + if (tag == 0xff)
13474 + return PS_OK;
13475 + while (tag > 0) {
13476 + err = ps_pread(J->P, block + segment, &tag, sizeof(tag));
13477 + CHECK_FAIL(err);
13478 + segment -= tag;
13480 + block = block_at(i, J, segment);
13481 + err = ps_pread(J->P, block + OFFSET_HeapBlockHeader_used, &used, sizeof(used));
13482 + CHECK_FAIL(err);
13483 + if (used) {
13484 + *startp = block + SIZE_HeapBlockHeader;
13487 + return PS_OK;
13490 + fail:
13491 + return -1;
13494 +static int find_jlong_constant(jvm_agent_t* J, const char *name, uint64_t* valuep) {
13495 + psaddr_t sym_addr;
13496 + int err = ps_pglobal_lookup(J->P, LIBJVM_SO, name, &sym_addr);
13497 + if (err == PS_OK) {
13498 + err = ps_pread(J->P, sym_addr, valuep, sizeof(uint64_t));
13499 + return err;
13501 + *valuep = -1;
13502 + return -1;
13505 +jvm_agent_t *Jagent_create(struct ps_prochandle *P, int vers) {
13506 + jvm_agent_t* J;
13507 + int err;
13509 + if (vers != JVM_DB_VERSION) {
13510 + errno = ENOTSUP;
13511 + return NULL;
13514 + J = (jvm_agent_t*)calloc(sizeof(struct jvm_agent), 1);
13516 + debug = getenv("LIBJVMDB_DEBUG") != NULL;
13517 + if (debug) debug = 3;
13519 + if (debug) {
13520 + fprintf(stderr, "Jagent_create: debug=%d\n", debug);
13521 +#ifdef X86_COMPILER2
13522 + fprintf(stderr, "Jagent_create: R_SP=%d, R_FP=%d, POINTER_SIZE=%d\n", R_SP, R_FP, POINTER_SIZE);
13523 +#endif /* X86_COMPILER2 */
13526 + J->P = P;
13528 + // Initialize the initial previous frame
13530 + J->prev_fr.fp = 0;
13531 + J->prev_fr.pc = 0;
13532 + J->prev_fr.sp = 0;
13533 + J->prev_fr.sender_sp = 0;
13535 + err = find_symbol(J, "__1cHnmethodG__vtbl_", &J->nmethod_vtbl);
13536 + CHECK_FAIL(err);
13537 + err = find_symbol(J, "__1cKBufferBlobG__vtbl_", &J->BufferBlob_vtbl);
13538 + if (err != PS_OK) J->BufferBlob_vtbl = 0;
13539 + err = find_symbol(J, "__1cICodeBlobG__vtbl_", &J->CodeBlob_vtbl);
13540 + CHECK_FAIL(err);
13541 + err = find_symbol(J, "__1cLRuntimeStubG__vtbl_", &J->RuntimeStub_vtbl);
13542 + CHECK_FAIL(err);
13543 + err = find_symbol(J, "__1cGMethodG__vtbl_", &J->Method_vtbl);
13544 + CHECK_FAIL(err);
13546 + err = parse_vmstructs(J);
13547 + CHECK_FAIL(err);
13548 + err = read_volatiles(J);
13549 + CHECK_FAIL(err);
13551 + return J;
13553 + fail:
13554 + Jagent_destroy(J);
13555 + return NULL;
13558 +void Jagent_destroy(jvm_agent_t *J) {
13559 + if (J != NULL) {
13560 + free(J);
13564 +static int is_method(jvm_agent_t* J, uint64_t methodPtr) {
13565 + uint64_t klass;
13566 + int err = read_pointer(J, methodPtr, &klass);
13567 + if (err != PS_OK) goto fail;
13568 + return klass == J->Method_vtbl;
13570 + fail:
13571 + return 0;
13574 +static int
13575 +name_for_methodPtr(jvm_agent_t* J, uint64_t methodPtr, char * result, size_t size)
13577 + short nameIndex;
13578 + short signatureIndex;
13579 + uint64_t constantPool;
13580 + uint64_t constMethod;
13581 + uint64_t nameSymbol;
13582 + uint64_t signatureSymbol;
13583 + uint64_t klassPtr;
13584 + uint64_t klassSymbol;
13585 + short klassSymbolLength;
13586 + short nameSymbolLength;
13587 + short signatureSymbolLength;
13588 + char * nameString = NULL;
13589 + char * klassString = NULL;
13590 + char * signatureString = NULL;
13591 + int err;
13593 + err = read_pointer(J, methodPtr + OFFSET_Method_constMethod, &constMethod);
13594 + CHECK_FAIL(err);
13595 + err = read_pointer(J, constMethod + OFFSET_ConstMethod_constants, &constantPool);
13596 + CHECK_FAIL(err);
13598 + /* To get name string */
13599 + err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_name_index, &nameIndex, 2);
13600 + CHECK_FAIL(err);
13601 + err = read_pointer(J, constantPool + nameIndex * POINTER_SIZE + SIZE_ConstantPool, &nameSymbol);
13602 + CHECK_FAIL(err);
13603 + // The symbol is a CPSlot and has lower bit set to indicate metadata
13604 + nameSymbol &= (~1); // remove metadata lsb
13605 + err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_length, &nameSymbolLength, 2);
13606 + CHECK_FAIL(err);
13607 + nameString = (char*)calloc(nameSymbolLength + 1, 1);
13608 + err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_body, nameString, nameSymbolLength);
13609 + CHECK_FAIL(err);
13611 + /* To get signature string */
13612 + err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_signature_index, &signatureIndex, 2);
13613 + CHECK_FAIL(err);
13614 + err = read_pointer(J, constantPool + signatureIndex * POINTER_SIZE + SIZE_ConstantPool, &signatureSymbol);
13615 + CHECK_FAIL(err);
13616 + signatureSymbol &= (~1); // remove metadata lsb
13617 + err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_length, &signatureSymbolLength, 2);
13618 + CHECK_FAIL(err);
13619 + signatureString = (char*)calloc(signatureSymbolLength + 1, 1);
13620 + err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_body, signatureString, signatureSymbolLength);
13621 + CHECK_FAIL(err);
13623 + /* To get klass string */
13624 + err = read_pointer(J, constantPool + OFFSET_ConstantPool_pool_holder, &klassPtr);
13625 + CHECK_FAIL(err);
13626 + err = read_pointer(J, klassPtr + OFFSET_Klass_name, &klassSymbol);
13627 + CHECK_FAIL(err);
13628 + err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_length, &klassSymbolLength, 2);
13629 + CHECK_FAIL(err);
13630 + klassString = (char*)calloc(klassSymbolLength + 1, 1);
13631 + err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_body, klassString, klassSymbolLength);
13632 + CHECK_FAIL(err);
13634 + result[0] = '\0';
13635 + if (snprintf(result, size,
13636 + "%s.%s%s",
13637 + klassString,
13638 + nameString,
13639 + signatureString) >= size) {
13640 + // truncation
13641 + goto fail;
13644 + if (nameString != NULL) free(nameString);
13645 + if (klassString != NULL) free(klassString);
13646 + if (signatureString != NULL) free(signatureString);
13648 + return PS_OK;
13650 + fail:
13651 + if (debug) {
13652 + fprintf(stderr, "name_for_methodPtr: FAIL \n\n");
13654 + if (nameString != NULL) free(nameString);
13655 + if (klassString != NULL) free(klassString);
13656 + if (signatureString != NULL) free(signatureString);
13657 + return -1;
13660 +static int nmethod_info(Nmethod_t *N)
13662 + jvm_agent_t *J = N->J;
13663 + uint64_t nm = N->nm;
13664 + int32_t err;
13666 + if (debug > 2 )
13667 + fprintf(stderr, "\t nmethod_info: BEGIN \n");
13669 + /* Instructions */
13670 + err = read_pointer(J, nm + OFFSET_CodeBlob_code_begin, &N->instrs_beg);
13671 + CHECK_FAIL(err);
13672 + err = read_pointer(J, nm + OFFSET_CodeBlob_code_end, &N->instrs_end);
13673 + CHECK_FAIL(err);
13674 + err = read_pointer(J, nm + OFFSET_nmethod_deopt_handler_begin, &N->deopt_beg);
13675 + CHECK_FAIL(err);
13676 + err = ps_pread(J->P, nm + OFFSET_nmethod_orig_pc_offset, &N->orig_pc_offset, SZ32);
13677 + CHECK_FAIL(err);
13679 + /* Metadata */
13680 + err = ps_pread(J->P, nm + OFFSET_nmethod_metadata_offset, &N->metadata_beg, SZ32);
13681 + CHECK_FAIL(err);
13682 + err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_data_begin, &N->metadata_end, SZ32);
13683 + CHECK_FAIL(err);
13685 + /* scopes_pcs */
13686 + err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_pcs_offset, &N->scopes_pcs_beg, SZ32);
13687 + CHECK_FAIL(err);
13688 + err = ps_pread(J->P, nm + OFFSET_nmethod_dependencies_offset, &N->scopes_pcs_end, SZ32);
13689 + CHECK_FAIL(err);
13691 + /* scopes_data */
13692 + err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_data_begin, &N->scopes_data_beg, POINTER_SIZE);
13693 + CHECK_FAIL(err);
13695 + if (debug > 2 ) {
13696 + N->scopes_data_end = N->scopes_pcs_beg;
13698 + fprintf(stderr, "\t nmethod_info: instrs_beg: %#x, instrs_end: %#x\n",
13699 + N->instrs_beg, N->instrs_end);
13701 + fprintf(stderr, "\t nmethod_info: deopt_beg: %#x \n",
13702 + N->deopt_beg);
13704 + fprintf(stderr, "\t nmethod_info: orig_pc_offset: %#x \n",
13705 + N->orig_pc_offset);
13707 + fprintf(stderr, "\t nmethod_info: metadata_beg: %#x, metadata_end: %#x\n",
13708 + N->metadata_beg, N->metadata_end);
13710 + fprintf(stderr, "\t nmethod_info: scopes_data_beg: %#x, scopes_data_end: %#x\n",
13711 + N->scopes_data_beg, N->scopes_data_end);
13713 + fprintf(stderr, "\t nmethod_info: scopes_pcs_beg: %#x, scopes_pcs_end: %#x\n",
13714 + N->scopes_pcs_beg, N->scopes_pcs_end);
13716 + fprintf(stderr, "\t nmethod_info: END \n\n");
13718 + return PS_OK;
13720 + fail:
13721 + return err;
13724 +static int
13725 +raw_read_int(jvm_agent_t* J, uint64_t *buffer, int32_t *val)
13727 + int shift = 0;
13728 + int value = 0;
13729 + uint8_t ch = 0;
13730 + int32_t err;
13731 + int32_t sum;
13732 + // Constants for UNSIGNED5 coding of Pack200
13733 + // see compressedStream.hpp
13734 + enum {
13735 + lg_H = 6,
13736 + H = 1<<lg_H,
13737 + BitsPerByte = 8,
13738 + L = (1<<BitsPerByte)-H,
13739 + };
13740 + int i;
13742 + err = ps_pread(J->P, (*buffer)++, &ch, sizeof(uint8_t));
13743 + CHECK_FAIL(err);
13744 + if (debug > 2)
13745 + fprintf(stderr, "\t\t\t raw_read_int: *buffer: %#llx, ch: %#x\n", *buffer, ch);
13747 + sum = ch;
13748 + if ( sum >= L ) {
13749 + int32_t lg_H_i = lg_H;
13750 + // Read maximum of 5 total bytes (we've already read 1).
13751 + // See CompressedReadStream::read_int_mb
13752 + for ( i = 0; i < 4; i++) {
13753 + err = ps_pread(J->P, (*buffer)++, &ch, sizeof(uint8_t));
13754 + CHECK_FAIL(err);
13755 + sum += ch << lg_H_i;
13756 + if (ch < L ) {
13757 + *val = sum;
13758 + return PS_OK;
13760 + lg_H_i += lg_H;
13763 + *val = sum;
13764 + return PS_OK;
13766 + fail:
13767 + return err;
13770 +static int
13771 +read_pair(jvm_agent_t* J, uint64_t *buffer, int32_t *bci, int32_t *line)
13773 + uint8_t next = 0;
13774 + int32_t bci_delta;
13775 + int32_t line_delta;
13776 + int32_t err;
13778 + if (debug > 2)
13779 + fprintf(stderr, "\t\t read_pair: BEGIN\n");
13781 + err = ps_pread(J->P, (*buffer)++, &next, sizeof(uint8_t));
13782 + CHECK_FAIL(err);
13784 + if (next == 0) {
13785 + if (debug > 2)
13786 + fprintf(stderr, "\t\t read_pair: END: next == 0\n");
13787 + return 1; /* stream terminated */
13789 + if (next == 0xFF) {
13790 + if (debug > 2)
13791 + fprintf(stderr, "\t\t read_pair: END: next == 0xFF\n");
13793 + /* Escape character, regular compression used */
13795 + err = raw_read_int(J, buffer, &bci_delta);
13796 + CHECK_FAIL(err);
13798 + err = raw_read_int(J, buffer, &line_delta);
13799 + CHECK_FAIL(err);
13801 + *bci += bci_delta;
13802 + *line += line_delta;
13804 + if (debug > 2) {
13805 + fprintf(stderr, "\t\t read_pair: delta = (line %d: %d)\n",
13806 + line_delta, bci_delta);
13807 + fprintf(stderr, "\t\t read_pair: unpack= (line %d: %d)\n",
13808 + *line, *bci);
13810 + } else {
13811 + /* Single byte compression used */
13812 + *bci += next >> 3;
13813 + *line += next & 0x7;
13814 + if (debug > 2) {
13815 + fprintf(stderr, "\t\t read_pair: delta = (line %d: %d)\n",
13816 + next & 0x7, next >> 3);
13817 + fprintf(stderr, "\t\t read_pair: unpack= (line %d: %d)\n",
13818 + *line, *bci);
13821 + if (debug > 2)
13822 + fprintf(stderr, "\t\t read_pair: END\n");
13823 + return PS_OK;
13825 + fail:
13826 + if (debug)
13827 + fprintf(stderr, "\t\t read_pair: FAIL\n");
13828 + return err;
13831 +static int
13832 +line_number_from_bci(jvm_agent_t* J, Vframe_t *vf)
13834 + uint64_t buffer;
13835 + uint16_t code_size;
13836 + uint64_t code_end_delta;
13837 + uint64_t constMethod;
13838 + int8_t access_flags;
13839 + int32_t best_bci = 0;
13840 + int32_t stream_bci = 0;
13841 + int32_t stream_line = 0;
13842 + int32_t err;
13844 + if (debug > 2) {
13845 + char name[256];
13846 + err = name_for_methodPtr(J, vf->method, name, 256);
13847 + CHECK_FAIL(err);
13848 + fprintf(stderr, "\t line_number_from_bci: BEGIN, method name: %s, targ bci: %d\n",
13849 + name, vf->bci);
13852 + err = read_pointer(J, vf->method + OFFSET_Method_constMethod, &constMethod);
13853 + CHECK_FAIL(err);
13855 + vf->line = 0;
13856 + err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_flags, &access_flags, sizeof(int8_t));
13857 + CHECK_FAIL(err);
13859 + if (!(access_flags & ConstMethod_has_linenumber_table)) {
13860 + if (debug > 2)
13861 + fprintf(stderr, "\t line_number_from_bci: END: !HAS_LINE_NUMBER_TABLE \n\n");
13862 + return PS_OK;
13865 + /* The line numbers are a short array of 2-tuples [start_pc, line_number].
13866 + * Not necessarily sorted and not necessarily one-to-one.
13867 + */
13869 + err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_code_size, &code_size, SZ16);
13870 + CHECK_FAIL(err);
13872 + /* inlined_table_start() */
13873 + code_end_delta = (uint64_t) (access_flags & AccessFlags_NATIVE) ? 2*POINTER_SIZE : 0;
13874 + buffer = constMethod + (uint64_t) SIZE_ConstMethod + (uint64_t) code_size + code_end_delta;
13876 + if (debug > 2) {
13877 + fprintf(stderr, "\t\t line_number_from_bci: method: %#llx, native: %d\n",
13878 + vf->method, (access_flags & AccessFlags_NATIVE));
13879 + fprintf(stderr, "\t\t line_number_from_bci: buffer: %#llx, code_size: %d\n",
13880 + buffer, (int) code_size);
13883 + while (read_pair(J, &buffer, &stream_bci, &stream_line) == 0) {
13884 + if (stream_bci == vf->bci) {
13885 + /* perfect match */
13886 + if (debug > 2)
13887 + fprintf(stderr, "\t line_number_from_bci: END: exact line: %d \n\n", vf->line);
13888 + vf->line = stream_line;
13889 + return PS_OK;
13890 + } else {
13891 + /* update best_bci/line */
13892 + if (stream_bci < vf->bci && stream_bci >= best_bci) {
13893 + best_bci = stream_bci;
13894 + vf->line = stream_line;
13895 + if (debug > 2) {
13896 + fprintf(stderr, "\t line_number_from_bci: best_bci: %d, best_line: %d\n",
13897 + best_bci, vf->line);
13902 + if (debug > 2)
13903 + fprintf(stderr, "\t line_number_from_bci: END: line: %d \n\n", vf->line);
13904 + return PS_OK;
13906 + fail:
13907 + if (debug)
13908 + fprintf(stderr, "\t line_number_from_bci: FAIL\n");
13909 + return err;
13912 +static int
13913 +get_real_pc(Nmethod_t *N, uint64_t pc_desc, uint64_t *real_pc)
13915 + int32_t pc_offset;
13916 + int32_t err;
13918 + err = ps_pread(N->J->P, pc_desc + OFFSET_PcDesc_pc_offset, &pc_offset, SZ32);
13919 + CHECK_FAIL(err);
13921 + *real_pc = N->instrs_beg + pc_offset;
13922 + if (debug > 2) {
13923 + fprintf(stderr, "\t\t get_real_pc: pc_offset: %lx, real_pc: %llx\n",
13924 + pc_offset, *real_pc);
13926 + return PS_OK;
13928 + fail:
13929 + return err;
13932 +/* Finds a PcDesc with real-pc equal to N->pc */
13933 +static int pc_desc_at(Nmethod_t *N)
13935 + uint64_t pc_diff = 999;
13936 + int32_t offs;
13937 + int32_t err;
13939 + if (debug > 2)
13940 + fprintf(stderr, "\t pc_desc_at: BEGIN\n");
13942 + N->vf_cnt = 0;
13943 + N->pc_desc = 0;
13945 + for (offs = N->scopes_pcs_beg; offs < N->scopes_pcs_end; offs += SIZE_PcDesc) {
13946 + uint64_t pd;
13947 + uint64_t best_pc_diff = 16; /* some approximation */
13948 + uint64_t real_pc = 0;
13950 + pd = N->nm + offs;
13951 + err = get_real_pc(N, pd, &real_pc);
13952 + CHECK_FAIL(err);
13954 + pc_diff = real_pc - N->pc;
13956 + /* In general, this fragment should work */
13957 + if (pc_diff == 0) {
13958 + N->pc_desc = pd;
13959 + if (debug) {
13960 + fprintf(stderr, "\t pc_desc_at: END: pc_desc: FOUND: %#lx \n\n", pd);
13962 + return PS_OK;
13964 + /* This fragment is to be able to find out an appropriate
13965 + * pc_desc entry even if pc_desc info is inaccurate.
13966 + */
13967 + if (best_pc_diff > pc_diff && pc_diff > 0) {
13968 + best_pc_diff = pc_diff;
13969 + N->pc_desc = pd;
13972 + if (debug) {
13973 + fprintf(stderr, "\t pc_desc_at: END: pc_desc NOT FOUND");
13974 + if (pc_diff < 20)
13975 + fprintf(stderr, ", best pc_diff: %d\n\n", pc_diff);
13976 + else
13977 + fprintf(stderr, "\n\n");
13979 + return PS_OK;
13981 + fail:
13982 + return err;
13985 +static int
13986 +scope_desc_at(Nmethod_t *N, int32_t decode_offset, Vframe_t *vf)
13988 + uint64_t buffer;
13989 + int32_t err;
13991 + if (debug > 2) {
13992 + fprintf(stderr, "\t\t scope_desc_at: BEGIN \n");
13995 + buffer = N->scopes_data_beg + decode_offset;
13997 + err = raw_read_int(N->J, &buffer, &vf->sender_decode_offset);
13998 + CHECK_FAIL(err);
14000 + err = raw_read_int(N->J, &buffer, &vf->methodIdx);
14001 + CHECK_FAIL(err);
14003 + err = raw_read_int(N->J, &buffer, &vf->bci);
14004 + CHECK_FAIL(err);
14006 + if (debug > 2) {
14007 + fprintf(stderr, "\t\t scope_desc_at: sender_decode_offset: %#x\n",
14008 + vf->sender_decode_offset);
14009 + fprintf(stderr, "\t\t scope_desc_at: methodIdx: %d\n", vf->methodIdx);
14010 + fprintf(stderr, "\t\t scope_desc_at: bci: %d\n", vf->bci);
14012 + fprintf(stderr, "\t\t scope_desc_at: END \n\n");
14014 + return PS_OK;
14016 + fail:
14017 + return err;
14020 +static int scopeDesc_chain(Nmethod_t *N) {
14021 + int32_t decode_offset = 0;
14022 + int32_t err;
14024 + if (debug > 2) {
14025 + fprintf(stderr, "\t scopeDesc_chain: BEGIN\n");
14028 + err = ps_pread(N->J->P, N->pc_desc + OFFSET_PcDesc_scope_decode_offset,
14029 + &decode_offset, SZ32);
14030 + CHECK_FAIL(err);
14032 + while (decode_offset > 0) {
14033 + Vframe_t *vf = &N->vframes[N->vf_cnt];
14035 + if (debug > 2) {
14036 + fprintf(stderr, "\t scopeDesc_chain: decode_offset: %#x\n", decode_offset);
14039 + err = scope_desc_at(N, decode_offset, vf);
14040 + CHECK_FAIL(err);
14042 + if (vf->methodIdx > ((N->metadata_end - N->metadata_beg) / POINTER_SIZE)) {
14043 + fprintf(stderr, "\t scopeDesc_chain: (methodIdx > metadata length) !\n");
14044 + return -1;
14046 + err = read_pointer(N->J, N->nm + N->metadata_beg + (vf->methodIdx-1)*POINTER_SIZE,
14047 + &vf->method);
14048 + CHECK_FAIL(err);
14050 + if (vf->method) {
14051 + N->vf_cnt++;
14052 + err = line_number_from_bci(N->J, vf);
14053 + CHECK_FAIL(err);
14054 + if (debug > 2) {
14055 + fprintf(stderr, "\t scopeDesc_chain: method: %#8llx, line: %d\n",
14056 + vf->method, vf->line);
14059 + decode_offset = vf->sender_decode_offset;
14061 + if (debug > 2) {
14062 + fprintf(stderr, "\t scopeDesc_chain: END \n\n");
14064 + return PS_OK;
14066 + fail:
14067 + if (debug) {
14068 + fprintf(stderr, "\t scopeDesc_chain: FAIL \n\n");
14070 + return err;
14074 +static int
14075 +name_for_nmethod(jvm_agent_t* J,
14076 + uint64_t nm,
14077 + uint64_t pc,
14078 + uint64_t method,
14079 + char *result,
14080 + size_t size,
14081 + Jframe_t *jframe
14082 +) {
14083 + Nmethod_t *N;
14084 + Vframe_t *vf;
14085 + int32_t err;
14086 + int deoptimized = 0;
14088 + if (debug) {
14089 + fprintf(stderr, "name_for_nmethod: BEGIN: nmethod: %#llx, pc: %#llx\n", nm, pc);
14091 + if (J->N == NULL) {
14092 + J->N = (Nmethod_t *) malloc(sizeof(Nmethod_t));
14094 + memset(J->N, 0, sizeof(Nmethod_t)); /* Initial stat: all values are zeros */
14095 + N = J->N;
14096 + N->J = J;
14097 + N->nm = nm;
14098 + N->pc = pc;
14099 + N->jframe = jframe;
14101 + err = nmethod_info(N);
14102 + CHECK_FAIL(err);
14103 + if (debug) {
14104 + fprintf(stderr, "name_for_nmethod: pc: %#llx, deopt_pc: %#llx\n",
14105 + pc, N->deopt_beg);
14108 + /* check for a deoptimized frame */
14109 + if ( pc == N->deopt_beg) {
14110 + uint64_t base;
14111 + if (debug) {
14112 + fprintf(stderr, "name_for_nmethod: found deoptimized frame\n");
14114 + if (J->prev_fr.sender_sp != 0) {
14115 + base = J->prev_fr.sender_sp + N->orig_pc_offset;
14116 + } else {
14117 + base = J->curr_fr.sp + N->orig_pc_offset;
14119 + err = read_pointer(J, base, &N->pc);
14120 + CHECK_FAIL(err);
14121 + if (debug) {
14122 + fprintf(stderr, "name_for_nmethod: found deoptimized frame converting pc from %#8llx to %#8llx\n",
14123 + pc, N->pc);
14125 + deoptimized = 1;
14128 + err = pc_desc_at(N);
14129 + CHECK_FAIL(err);
14131 + if (N->pc_desc > 0) {
14132 + jframe->locinf = 1;
14133 + err = scopeDesc_chain(N);
14134 + CHECK_FAIL(err);
14136 + result[0] = COMP_METHOD_SIGN;
14137 + vf = &N->vframes[0];
14138 + if (N->vf_cnt > 0) {
14139 + jframe->vf_cnt = N->vf_cnt;
14140 + jframe->bci = vf->bci;
14141 + jframe->line = vf->line;
14142 + err = name_for_methodPtr(J, N->vframes[0].method, result+1, size-1);
14143 + CHECK_FAIL(err);
14144 + } else {
14145 + err = name_for_methodPtr(J, method, result+1, size-1);
14146 + CHECK_FAIL(err);
14148 + if (deoptimized) {
14149 + strncat(result, " [deoptimized frame]; ", size - strlen(result) - 1);
14150 + } else {
14151 + strncat(result, " [compiled] ", size - strlen(result) - 1);
14153 + if (debug)
14154 + fprintf(stderr, "name_for_nmethod: END: method name: %s, vf_cnt: %d\n\n",
14155 + result, N->vf_cnt);
14156 + return PS_OK;
14158 + fail:
14159 + if (debug)
14160 + fprintf(stderr, "name_for_nmethod: FAIL \n\n");
14161 + return err;
14164 +static int
14165 +name_for_imethod(jvm_agent_t* J,
14166 + uint64_t bcp,
14167 + uint64_t method,
14168 + char *result,
14169 + size_t size,
14170 + Jframe_t *jframe
14171 +) {
14172 + uint64_t bci;
14173 + uint64_t constMethod;
14174 + Vframe_t vframe = {0};
14175 + Vframe_t *vf = &vframe;
14176 + int32_t err;
14178 + err = read_pointer(J, method + OFFSET_Method_constMethod, &constMethod);
14179 + CHECK_FAIL(err);
14181 + bci = bcp - (constMethod + (uint64_t) SIZE_ConstMethod);
14183 + if (debug)
14184 + fprintf(stderr, "\t name_for_imethod: BEGIN: method: %#llx\n", method);
14186 + err = name_for_methodPtr(J, method, result, size);
14187 + CHECK_FAIL(err);
14188 + if (debug)
14189 + fprintf(stderr, "\t name_for_imethod: method name: %s\n", result);
14191 + if (bci > 0) {
14192 + vf->method = method;
14193 + vf->bci = bci;
14194 + err = line_number_from_bci(J, vf);
14195 + CHECK_FAIL(err);
14197 + jframe->bci = vf->bci;
14198 + jframe->line = vf->line;
14199 + jframe->locinf = 1;
14201 + if (debug) {
14202 + fprintf(stderr, "\t name_for_imethod: END: bci: %d, line: %d\n\n",
14203 + vf->bci, vf->line);
14205 + return PS_OK;
14207 + fail:
14208 + if (debug)
14209 + fprintf(stderr, "\t name_for_imethod: FAIL\n");
14210 + return err;
14213 +static int
14214 +name_for_codecache(jvm_agent_t* J, uint64_t fp, uint64_t pc, char * result,
14215 + size_t size, Jframe_t *jframe, int* is_interpreted)
14217 + uint64_t start;
14218 + uint64_t vtbl;
14219 + int32_t err;
14220 + *is_interpreted = 0;
14222 + result[0] = '\0';
14224 + err = find_start(J, pc, &start);
14225 + CHECK_FAIL(err);
14227 + err = read_pointer(J, start, &vtbl);
14228 + CHECK_FAIL(err);
14230 + if (vtbl == J->nmethod_vtbl) {
14231 + uint64_t method;
14233 + err = read_pointer(J, start + OFFSET_nmethod_method, &method);
14234 + CHECK_FAIL(err);
14236 + if (debug) {
14237 + fprintf(stderr, "name_for_codecache: start: %#8llx, pc: %#8llx, method: %#8llx \n",
14238 + start, pc, method);
14240 + err = name_for_nmethod(J, start, pc, method, result, size, jframe);
14241 + CHECK_FAIL(err);
14242 + } else if (vtbl == J->BufferBlob_vtbl) {
14243 + const char * name;
14245 + err = read_string_pointer(J, start + OFFSET_CodeBlob_name, &name);
14247 + /*
14248 + * Temporary usage of string "Interpreter".
14249 + * We need some other way to distinguish "StubRoutines"
14250 + * and regular interpreted frames.
14251 + */
14252 + if (err == PS_OK && strncmp(name, "Interpreter", 11) == 0) {
14253 + *is_interpreted = 1;
14254 + if (is_method(J, J->methodPtr)) {
14255 + return name_for_imethod(J, J->bcp, J->methodPtr, result, size, jframe);
14259 + if (err == PS_OK) {
14260 + strncpy(result, name, size);
14261 + free((void*)name);
14262 + } else {
14263 + strncpy(result, "<unknown BufferBlob>", size);
14265 + /* return PS_OK; */
14266 + } else {
14267 + const char * name;
14269 + err = read_string_pointer(J, start + OFFSET_CodeBlob_name, &name);
14270 + if (err == PS_OK) {
14271 + strncpy(result, name, size);
14272 + free((void*)name);
14273 + } else {
14274 + strncpy(result, "<unknown CodeBlob>", size);
14275 + WARN1("unknown CodeBlob: vtbl = 0x%x", vtbl);
14278 + result[size-1] = '\0';
14280 +#ifdef X86_COMPILER2
14281 + if (vtbl != J->RuntimeStub_vtbl) {
14282 + uint64_t trial_pc;
14283 + int frame_size;
14284 + err = ps_pread(J->P, start + OFFSET_CodeBlob_frame_size,
14285 + &frame_size, SZ32);
14286 + CHECK_FAIL(err);
14288 + // frame_size is in words, we want bytes.
14289 + frame_size *= POINTER_SIZE; /* word => byte conversion */
14291 + /*
14292 + Because c2 doesn't use FP as a framepointer the value of sp/fp we receive
14293 + in the initial entry to a set of stack frames containing server frames
14294 + will pretty much be nonsense. We can detect that nonsense by looking to
14295 + see if the PC we received is correct if we look at the expected storage
14296 + location in relation to the FP (ie. POINTER_SIZE(FP) )
14297 + */
14299 + err = read_pointer(J, fp + POINTER_SIZE , &trial_pc);
14300 + if ( (err != PS_OK || trial_pc != pc) && frame_size > 0 ) {
14301 + // Either we couldn't even read at the "fp" or the pc didn't match
14302 + // both are sure clues that the fp is bogus. We no search the stack
14303 + // for a reasonable number of words trying to find the bogus fp
14304 + // and the current pc in adjacent words. The we will be able to
14305 + // deduce an approximation of the frame pointer and actually get
14306 + // the correct stack pointer. Which we can then unwind for the
14307 + // next frame.
14308 + int i;
14309 + uint64_t check;
14310 + uint64_t base = J->curr_fr.sp;
14311 + uint64_t prev_fp = 0;
14312 + for ( i = 0; i < frame_size * 5 ; i++, base += POINTER_SIZE ) {
14313 + err = read_pointer(J, base , &check);
14314 + CHECK_FAIL(err);
14315 + if (check == fp) {
14316 + base += POINTER_SIZE;
14317 + err = read_pointer(J, base , &check);
14318 + CHECK_FAIL(err);
14319 + if (check == pc) {
14320 + if (debug) {
14321 + fprintf(stderr, "name_for_codecache: found matching fp/pc combo at 0x%llx\n", base - POINTER_SIZE);
14323 + prev_fp = base - 2 * POINTER_SIZE;
14324 + break;
14328 + if ( prev_fp != 0 ) {
14329 + // real_sp is the sp we should have received for this frame
14330 + uint64_t real_sp = prev_fp + 2 * POINTER_SIZE;
14331 + // +POINTER_SIZE because callee owns the return address so caller's sp is +1 word
14332 + jframe->new_sp = real_sp + frame_size + POINTER_SIZE;
14333 + err = read_pointer(J, jframe->new_sp - POINTER_SIZE , &jframe->new_pc);
14334 + CHECK_FAIL(err);
14335 + err = read_pointer(J, jframe->new_sp - 2*POINTER_SIZE, &jframe->new_fp);
14336 + CHECK_FAIL(err);
14337 + return PS_OK;
14341 + /* A prototype to workaround FP absence */
14342 + /*
14343 + * frame_size can be 0 for StubRoutines (1) frame.
14344 + * In this case it should work with fp as usual.
14345 + */
14346 + if (frame_size > 0) {
14347 + jframe->new_fp = J->prev_fr.fp + frame_size;
14348 + jframe->new_sp = jframe->new_fp + 2 * POINTER_SIZE;
14349 + } else {
14350 + memset(&J->curr_fr, 0, sizeof(Frame_t));
14351 + err = read_pointer(J, fp, &jframe->new_fp);
14352 + CHECK_FAIL(err);
14354 + err = read_pointer(J, jframe->new_fp + POINTER_SIZE, &jframe->new_pc);
14355 + CHECK_FAIL(err);
14357 + if (debug) {
14358 + fprintf(stderr, "name_for_codecache: %s, frame_size=%#lx\n",
14359 + result, frame_size);
14360 + fprintf(stderr, "name_for_codecache: prev_fr.fp=%#lx, fp=%#lx\n",
14361 + J->prev_fr.fp, jframe->new_fp);
14364 +#endif /* X86_COMPILER2 */
14366 + return PS_OK;
14368 + fail:
14369 + return err;
14372 +int Jget_vframe(jvm_agent_t* J, int vframe_no,
14373 + char *name, size_t size, Jframe_t *jframe)
14375 + Nmethod_t *N = J->N;
14376 + Vframe_t *vf;
14377 + int32_t err;
14379 + if (vframe_no >= N->vf_cnt) {
14380 + (void) sprintf(name, "Wrong inlinedMethod%1d()", vframe_no);
14381 + return -1;
14383 + vf = N->vframes + vframe_no;
14384 + name[0] = COMP_METHOD_SIGN;
14385 + err = name_for_methodPtr(J, vf->method, name + 1, size);
14386 + CHECK_FAIL(err);
14388 + jframe->bci = vf->bci;
14389 + jframe->line = vf->line;
14390 + if (debug) {
14391 + fprintf(stderr, "\t Jget_vframe: method name: %s, line: %d\n",
14392 + name, vf->line);
14394 + return PS_OK;
14396 + fail:
14397 + if (debug) {
14398 + fprintf(stderr, "\t Jget_vframe: FAIL\n");
14400 + return err;
14403 +#define MAX_SYM_SIZE 256
14405 +int Jlookup_by_regs(jvm_agent_t* J, const prgregset_t regs, char *name,
14406 + size_t size, Jframe_t *jframe) {
14407 + uintptr_t fp;
14408 + uintptr_t pc;
14409 + /* arguments given to read_pointer need to be worst case sized */
14410 + uint64_t methodPtr = 0;
14411 + uint64_t sender_sp;
14412 + uint64_t bcp = 0;
14413 + int is_interpreted = 0;
14414 + int result = PS_OK;
14415 + int err = PS_OK;
14417 + if (J == NULL) {
14418 + return -1;
14421 + jframe->vf_cnt = 1;
14422 + jframe->new_fp = 0;
14423 + jframe->new_pc = 0;
14424 + jframe->line = 0;
14425 + jframe->bci = 0;
14426 + jframe->locinf = 0;
14428 + read_volatiles(J);
14429 + pc = (uintptr_t) regs[R_PC];
14430 + J->curr_fr.pc = pc;
14431 + J->curr_fr.fp = regs[R_FP];
14432 + J->curr_fr.sp = regs[R_SP];
14434 + if (debug)
14435 + fprintf(stderr, "Jlookup_by_regs: BEGINs: fp=%#lx, pc=%#lx\n", regs[R_FP], pc);
14437 +#if defined(i386) || defined(__i386) || defined(__amd64)
14439 + fp = (uintptr_t) regs[R_FP];
14440 + if (J->prev_fr.fp == 0) {
14441 +#ifdef X86_COMPILER2
14442 + /* A workaround for top java frames */
14443 + J->prev_fr.fp = (uintptr_t)(regs[R_SP] - 2 * POINTER_SIZE);
14444 +#else
14445 + J->prev_fr.fp = (uintptr_t)(regs[R_SP] - POINTER_SIZE);
14446 +#endif /* COMPILER2 */
14448 + if (debug > 2) {
14449 + printf("Jlookup_by_regs: J->prev_fr.fp = %#lx\n", J->prev_fr.fp);
14452 + if (read_pointer(J, fp + OFFSET_interpreter_frame_method, &methodPtr) != PS_OK) {
14453 + methodPtr = 0;
14455 + if (read_pointer(J, fp + OFFSET_interpreter_frame_sender_sp, &sender_sp) != PS_OK) {
14456 + sender_sp = 0;
14458 + if (read_pointer(J, fp + OFFSET_interpreter_frame_bcp_offset, &bcp) != PS_OK) {
14459 + bcp = 0;
14461 +#endif /* i386 */
14463 + J->methodPtr = methodPtr;
14464 + J->bcp = bcp;
14466 + /* On x86 with C2 JVM: native frame may have wrong regs[R_FP]
14467 + * For example: JVM_SuspendThread frame poins to the top interpreted frame.
14468 + * If we call is_method(J, methodPtr) before codecache_contains(J, pc)
14469 + * then we go over and omit both: nmethod and I2CAdapter frames.
14470 + * Note, that regs[R_PC] is always correct if frame defined correctly.
14471 + * So it is better to call codecache_contains(J, pc) from the beginning.
14472 + */
14473 +#ifndef X86_COMPILER2
14474 + if (is_method(J, J->methodPtr)) {
14475 + result = name_for_imethod(J, bcp, J->methodPtr, name, size, jframe);
14476 + /* If the methodPtr is a method then this is highly likely to be
14477 + an interpreter frame */
14478 + if (result >= 0) {
14479 + is_interpreted = 1;
14481 + } else
14482 +#endif /* ! X86_COMPILER2 */
14484 + if (codecache_contains(J, pc)) {
14485 + result = name_for_codecache(J, fp, pc, name, size, jframe, &is_interpreted);
14487 +#ifdef X86_COMPILER2
14488 + else if (is_method(J, J->methodPtr)) {
14489 + result = name_for_imethod(J, bcp, J->methodPtr, name, size, jframe);
14490 + /* If the methodPtr is a method then this is highly likely to be
14491 + an interpreter frame */
14492 + if (result >= 0) {
14493 + is_interpreted = 1;
14496 +#endif /* X86_COMPILER2 */
14497 + else {
14498 + if (debug) {
14499 + fprintf(stderr, "Jlookup_by_regs: END with -1\n\n");
14501 + result = -1;
14503 + if (!is_interpreted) {
14504 + sender_sp = 0;
14506 + J->curr_fr.sender_sp = sender_sp;
14508 +#ifdef X86_COMPILER2
14509 + if (!J->curr_fr.fp) {
14510 + J->curr_fr.fp = (jframe->new_fp) ? jframe->new_fp : (uintptr_t)regs[R_FP];
14512 + if (!jframe->new_pc && jframe->new_fp) {
14513 + // This seems dubious
14514 + read_pointer(J, jframe->new_fp + POINTER_SIZE, &jframe->new_pc);
14515 + CHECK_FAIL(err);
14516 + if (debug > 2) {
14517 + printf("Jlookup_by_regs: (update pc) jframe->new_fp: %#llx, jframe->new_pc: %#llx\n",
14518 + jframe->new_fp, jframe->new_pc);
14522 +#endif /* X86_COMPILER2 */
14523 + J->prev_fr = J->curr_fr;
14525 + if (debug)
14526 + fprintf(stderr, "Jlookup_by_regs: END\n\n");
14528 + return result;
14530 + fail:
14531 + return err;
14534 +void update_gregs(prgregset_t gregs, Jframe_t jframe) {
14535 +#ifdef X86_COMPILER2
14536 + if (debug > 0) {
14537 + 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]);
14539 + /*
14540 + * A workaround for java C2 frames with unconventional FP.
14541 + * may have to modify regset with new values for FP/PC/SP when needed.
14542 + */
14543 + if (jframe.new_sp) {
14544 + *((uintptr_t *) &gregs[R_SP]) = (uintptr_t) jframe.new_sp;
14545 + } else {
14546 + // *((uintptr_t *) &gregs[R_SP]) = (uintptr_t) gregs[R_FP] + 2 * POINTER_SIZE;
14549 + if (jframe.new_fp) {
14550 + *((uintptr_t *) &gregs[R_FP]) = (uintptr_t) jframe.new_fp;
14552 + if (jframe.new_pc) {
14553 + *((uintptr_t *) &gregs[R_PC]) = (uintptr_t) jframe.new_pc;
14555 + if (debug > 0) {
14556 + 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]);
14558 +#endif /* X86_COMPILER2 */
14562 + * Iterates over java frames at current location given by 'gregs'.
14564 + * Returns -1 if no java frames are present or if an error is encountered.
14565 + * Returns the result of calling 'func' if the return value is non-zero.
14566 + * Returns 0 otherwise.
14567 + */
14568 +int Jframe_iter(jvm_agent_t *J, prgregset_t gregs, java_stack_f *func, void* cld) {
14569 + char buf[MAX_SYM_SIZE + 1];
14570 + Jframe_t jframe;
14571 + int i = 0, res;
14572 +#ifdef X86_COMPILER2
14573 + if (debug > 0) {
14574 + fprintf(stderr, "Jframe_iter: Entry sp = 0x%llx, fp = 0x%llx, pc = 0x%llx\n", gregs[R_SP], gregs[R_FP], gregs[R_PC]);
14576 +#endif /* X86_COMPILER2 */
14578 + memset(&jframe, 0, sizeof(Jframe_t));
14579 + memset(buf, 0, sizeof(buf));
14580 + res = Jlookup_by_regs(J, gregs, buf, sizeof(buf), &jframe);
14581 + if (res != PS_OK)
14582 + return (-1);
14585 + res = func(cld, gregs, buf, (jframe.locinf)? jframe.bci : -1,
14586 + jframe.line, NULL);
14587 + if (res != 0) {
14588 + update_gregs(gregs, jframe);
14589 + return (res);
14591 + for (i = 1; i < jframe.vf_cnt; i++) {
14592 + Jget_vframe(J, i, buf, sizeof(buf), &jframe);
14593 + res = func(cld, gregs, buf, (jframe.locinf)? jframe.bci : -1,
14594 + jframe.line, NULL);
14595 + if (res != 0) {
14596 + update_gregs(gregs, jframe);
14597 + return (res);
14600 + update_gregs(gregs, jframe);
14601 + return (0);
14603 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/native/libjvm_db/libjvm_db.h jdk22u-jdk-22.0.2-ga/src/java.base/solaris/native/libjvm_db/libjvm_db.h
14604 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/native/libjvm_db/libjvm_db.h 1970-01-01 01:00:00.000000000 +0100
14605 +++ jdk22u-jdk-22.0.2-ga/src/java.base/solaris/native/libjvm_db/libjvm_db.h 2024-08-17 19:34:03.914317411 +0200
14606 @@ -0,0 +1,69 @@
14608 + * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
14609 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
14611 + * This code is free software; you can redistribute it and/or modify it
14612 + * under the terms of the GNU General Public License version 2 only, as
14613 + * published by the Free Software Foundation.
14615 + * This code is distributed in the hope that it will be useful, but WITHOUT
14616 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14617 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14618 + * version 2 for more details (a copy is included in the LICENSE file that
14619 + * accompanied this code).
14621 + * You should have received a copy of the GNU General Public License version
14622 + * 2 along with this work; if not, write to the Free Software Foundation,
14623 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
14625 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
14626 + * or visit www.oracle.com if you need additional information or have any
14627 + * questions.
14629 + */
14631 +#ifndef OS_SOLARIS_DTRACE_LIBJVM_DB_H
14632 +#define OS_SOLARIS_DTRACE_LIBJVM_DB_H
14634 +#include <proc_service.h>
14635 +#include "jni.h"
14637 +#ifdef __cplusplus
14638 +extern "C" {
14639 +#endif
14641 +typedef struct jvm_agent jvm_agent_t;
14643 +#define JVM_DB_VERSION 1
14645 +JNIEXPORT jvm_agent_t *Jagent_create(struct ps_prochandle *P, int vers);
14648 + * Called from Jframe_iter() for each java frame. If it returns 0, then
14649 + * Jframe_iter() proceeds to the next frame. Otherwise, the return value is
14650 + * immediately returned to the caller of Jframe_iter().
14652 + * Parameters:
14653 + * 'cld' is client supplied data (to maintain iterator state, if any).
14654 + * 'name' is java method name.
14655 + * 'bci' is byte code index. it will be -1 if not available.
14656 + * 'line' is java source line number. it will be 0 if not available.
14657 + * 'handle' is an abstract client handle, reserved for future expansions
14658 + */
14660 +typedef int java_stack_f(void *cld, const prgregset_t regs, const char* name, int bci, int line, void *handle);
14663 + * Iterates over the java frames at the current location. Returns -1 if no java
14664 + * frames were found, or if there was some unrecoverable error. Otherwise,
14665 + * returns the last value returned from 'func'.
14666 + */
14667 +JNIEXPORT int Jframe_iter(jvm_agent_t *agent, prgregset_t gregs, java_stack_f *func, void* cld);
14669 +JNIEXPORT void Jagent_destroy(jvm_agent_t *J);
14671 +#ifdef __cplusplus
14672 +} /* extern "C" */
14673 +#endif /* __cplusplus */
14675 +#endif // OS_SOLARIS_DTRACE_LIBJVM_DB_H
14676 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/native/libjvm_dtrace/jvm_dtrace.c jdk22u-jdk-22.0.2-ga/src/java.base/solaris/native/libjvm_dtrace/jvm_dtrace.c
14677 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/native/libjvm_dtrace/jvm_dtrace.c 1970-01-01 01:00:00.000000000 +0100
14678 +++ jdk22u-jdk-22.0.2-ga/src/java.base/solaris/native/libjvm_dtrace/jvm_dtrace.c 2024-08-17 19:34:03.914862990 +0200
14679 @@ -0,0 +1,562 @@
14681 + * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
14682 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
14684 + * This code is free software; you can redistribute it and/or modify it
14685 + * under the terms of the GNU General Public License version 2 only, as
14686 + * published by the Free Software Foundation.
14688 + * This code is distributed in the hope that it will be useful, but WITHOUT
14689 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14690 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14691 + * version 2 for more details (a copy is included in the LICENSE file that
14692 + * accompanied this code).
14694 + * You should have received a copy of the GNU General Public License version
14695 + * 2 along with this work; if not, write to the Free Software Foundation,
14696 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
14698 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
14699 + * or visit www.oracle.com if you need additional information or have any
14700 + * questions.
14702 + */
14704 +#include <door.h>
14705 +#include <errno.h>
14706 +#include <fcntl.h>
14707 +#include <limits.h>
14708 +#include <poll.h>
14709 +#include <signal.h>
14710 +#include <stdarg.h>
14711 +#include <stdio.h>
14712 +#include <stdlib.h>
14713 +#include <string.h>
14714 +#include <sys/types.h>
14715 +#include <sys/stat.h>
14716 +#include <thread.h>
14717 +#include <unistd.h>
14718 +#include "jvm_dtrace.h"
14720 +// NOTE: These constants are used in JVM code as well.
14721 +// KEEP JVM CODE IN SYNC if you are going to change these...
14723 +#define DTRACE_ALLOC_PROBES 0x1
14724 +#define DTRACE_METHOD_PROBES 0x2
14725 +#define DTRACE_MONITOR_PROBES 0x4
14726 +#define DTRACE_ALL_PROBES -1
14728 +// generic error messages
14729 +#define JVM_ERR_OUT_OF_MEMORY "out of memory (native heap)"
14730 +#define JVM_ERR_INVALID_PARAM "invalid input parameter(s)"
14731 +#define JVM_ERR_NULL_PARAM "input paramater is NULL"
14733 +// error messages for attach
14734 +#define JVM_ERR_CANT_OPEN_DOOR "cannot open door file"
14735 +#define JVM_ERR_CANT_CREATE_ATTACH_FILE "cannot create attach file"
14736 +#define JVM_ERR_DOOR_FILE_PERMISSION "door file is not secure"
14737 +#define JVM_ERR_CANT_SIGNAL "cannot send SIGQUIT to target"
14739 +// error messages for enable probe
14740 +#define JVM_ERR_DOOR_CMD_SEND "door command send failed"
14741 +#define JVM_ERR_DOOR_CANT_READ_STATUS "cannot read door command status"
14742 +#define JVM_ERR_DOOR_CMD_STATUS "door command error status"
14744 +// error message for detach
14745 +#define JVM_ERR_CANT_CLOSE_DOOR "cannot close door file"
14747 +#define RESTARTABLE(_cmd, _result) do { \
14748 + do { \
14749 + _result = _cmd; \
14750 + } while((_result == -1) && (errno == EINTR)); \
14751 +} while(0)
14753 +struct _jvm_t {
14754 + pid_t pid;
14755 + int door_fd;
14758 +static int libjvm_dtrace_debug;
14759 +static void print_debug(const char* fmt,...) {
14760 + if (libjvm_dtrace_debug) {
14761 + va_list alist;
14762 + va_start(alist, fmt);
14763 + fputs("libjvm_dtrace DEBUG: ", stderr);
14764 + vfprintf(stderr, fmt, alist);
14765 + va_end(alist);
14769 +/* Key for thread local error message */
14770 +static thread_key_t jvm_error_key;
14772 +/* init function for this library */
14773 +static void init_jvm_dtrace() {
14774 + /* check for env. var for debug mode */
14775 + libjvm_dtrace_debug = getenv("LIBJVM_DTRACE_DEBUG") != NULL;
14776 + /* create key for thread local error message */
14777 + if (thr_keycreate(&jvm_error_key, NULL) != 0) {
14778 + print_debug("can't create thread_key_t for jvm error key\n");
14779 + // exit(1); ?
14783 +#pragma init(init_jvm_dtrace)
14785 +/* set thread local error message */
14786 +static void set_jvm_error(const char* msg) {
14787 + thr_setspecific(jvm_error_key, (void*)msg);
14790 +/* clear thread local error message */
14791 +static void clear_jvm_error() {
14792 + thr_setspecific(jvm_error_key, NULL);
14795 +/* file handling functions that can handle interrupt */
14797 +static int file_open(const char* path, int flag) {
14798 + int ret;
14799 + RESTARTABLE(open(path, flag), ret);
14800 + return ret;
14803 +static int file_close(int fd) {
14804 + return close(fd);
14807 +static int file_read(int fd, char* buf, int len) {
14808 + int ret;
14809 + RESTARTABLE(read(fd, buf, len), ret);
14810 + return ret;
14813 +/* send SIGQUIT signal to given process */
14814 +static int send_sigquit(pid_t pid) {
14815 + int ret;
14816 + RESTARTABLE(kill(pid, SIGQUIT), ret);
14817 + return ret;
14820 +/* called to check permissions on attach file */
14821 +static int check_permission(const char* path) {
14822 + struct stat64 sb;
14823 + uid_t uid, gid;
14824 + int res;
14826 + /*
14827 + * Check that the path is owned by the effective uid/gid of this
14828 + * process. Also check that group/other access is not allowed.
14829 + */
14830 + uid = geteuid();
14831 + gid = getegid();
14833 + res = stat64(path, &sb);
14834 + if (res != 0) {
14835 + print_debug("stat failed for %s\n", path);
14836 + return -1;
14839 + if ((sb.st_uid != uid) || (sb.st_gid != gid) ||
14840 + ((sb.st_mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) != 0)) {
14841 + print_debug("well-known file %s is not secure\n", path);
14842 + return -1;
14844 + return 0;
14847 +#define ATTACH_FILE_PATTERN "/tmp/.attach_pid%d"
14849 +/* fill-in the name of attach file name in given buffer */
14850 +static void fill_attach_file_name(char* path, int len, pid_t pid) {
14851 + memset(path, 0, len);
14852 + sprintf(path, ATTACH_FILE_PATTERN, pid);
14855 +#define DOOR_FILE_PATTERN "/tmp/.java_pid%d"
14857 +/* open door file for the given JVM */
14858 +static int open_door(pid_t pid) {
14859 + char path[PATH_MAX + 1];
14860 + int fd;
14862 + sprintf(path, DOOR_FILE_PATTERN, pid);
14863 + fd = file_open(path, O_RDONLY);
14864 + if (fd < 0) {
14865 + set_jvm_error(JVM_ERR_CANT_OPEN_DOOR);
14866 + print_debug("cannot open door file %s\n", path);
14867 + return -1;
14869 + print_debug("opened door file %s\n", path);
14870 + if (check_permission(path) != 0) {
14871 + set_jvm_error(JVM_ERR_DOOR_FILE_PERMISSION);
14872 + print_debug("check permission failed for %s\n", path);
14873 + file_close(fd);
14874 + fd = -1;
14876 + return fd;
14879 +/* create attach file for given process */
14880 +static int create_attach_file(pid_t pid) {
14881 + char path[PATH_MAX + 1];
14882 + int fd;
14883 + fill_attach_file_name(path, sizeof(path), pid);
14884 + fd = file_open(path, O_CREAT | O_RDWR);
14885 + if (fd < 0) {
14886 + set_jvm_error(JVM_ERR_CANT_CREATE_ATTACH_FILE);
14887 + print_debug("cannot create file %s\n", path);
14888 + } else {
14889 + print_debug("created attach file %s\n", path);
14891 + return fd;
14894 +/* delete attach file for given process */
14895 +static void delete_attach_file(pid_t pid) {
14896 + char path[PATH_MAX + 1];
14897 + fill_attach_file_name(path, sizeof(path), pid);
14898 + int res = unlink(path);
14899 + if (res) {
14900 + print_debug("cannot delete attach file %s\n", path);
14901 + } else {
14902 + print_debug("deleted attach file %s\n", path);
14906 +/* attach to given JVM */
14907 +jvm_t* jvm_attach(pid_t pid) {
14908 + jvm_t* jvm;
14909 + int door_fd, attach_fd, i = 0;
14911 + jvm = (jvm_t*) calloc(1, sizeof(jvm_t));
14912 + if (jvm == NULL) {
14913 + set_jvm_error(JVM_ERR_OUT_OF_MEMORY);
14914 + print_debug("calloc failed in %s at %d\n", __FILE__, __LINE__);
14915 + return NULL;
14917 + jvm->pid = pid;
14918 + attach_fd = -1;
14920 + door_fd = open_door(pid);
14921 + if (door_fd < 0) {
14922 + print_debug("trying to create attach file\n");
14923 + if ((attach_fd = create_attach_file(pid)) < 0) {
14924 + goto quit;
14927 + /* send QUIT signal to the target so that it will
14928 + * check for the attach file.
14929 + */
14930 + if (send_sigquit(pid) != 0) {
14931 + set_jvm_error(JVM_ERR_CANT_SIGNAL);
14932 + print_debug("sending SIGQUIT failed\n");
14933 + goto quit;
14936 + /* give the target VM time to start the attach mechanism */
14937 + do {
14938 + int res;
14939 + RESTARTABLE(poll(0, 0, 200), res);
14940 + door_fd = open_door(pid);
14941 + i++;
14942 + } while (i <= 50 && door_fd == -1);
14943 + if (door_fd < 0) {
14944 + print_debug("Unable to open door to process %d\n", pid);
14945 + goto quit;
14949 +quit:
14950 + if (attach_fd >= 0) {
14951 + file_close(attach_fd);
14952 + delete_attach_file(jvm->pid);
14954 + if (door_fd >= 0) {
14955 + jvm->door_fd = door_fd;
14956 + clear_jvm_error();
14957 + } else {
14958 + free(jvm);
14959 + jvm = NULL;
14961 + return jvm;
14964 +/* return the last thread local error message */
14965 +const char* jvm_get_last_error() {
14966 + const char* res = NULL;
14967 + thr_getspecific(jvm_error_key, (void**)&res);
14968 + return res;
14971 +/* detach the givenb JVM */
14972 +int jvm_detach(jvm_t* jvm) {
14973 + if (jvm) {
14974 + int res = 0;
14975 + if (jvm->door_fd != -1) {
14976 + if (file_close(jvm->door_fd) != 0) {
14977 + set_jvm_error(JVM_ERR_CANT_CLOSE_DOOR);
14978 + res = -1;
14979 + } else {
14980 + clear_jvm_error();
14983 + free(jvm);
14984 + return res;
14985 + } else {
14986 + set_jvm_error(JVM_ERR_NULL_PARAM);
14987 + print_debug("jvm_t* is NULL\n");
14988 + return -1;
14993 + * A simple table to translate some known errors into reasonable
14994 + * error messages
14995 + */
14996 +static struct {
14997 + int err;
14998 + const char* msg;
14999 +} const error_messages[] = {
15000 + { 100, "Bad request" },
15001 + { 101, "Protocol mismatch" },
15002 + { 102, "Resource failure" },
15003 + { 103, "Internal error" },
15004 + { 104, "Permission denied" },
15008 + * Lookup the given error code and return the appropriate
15009 + * message. If not found return NULL.
15010 + */
15011 +static const char* translate_error(int err) {
15012 + int table_size = sizeof(error_messages) / sizeof(error_messages[0]);
15013 + int i;
15015 + for (i=0; i<table_size; i++) {
15016 + if (err == error_messages[i].err) {
15017 + return error_messages[i].msg;
15020 + return NULL;
15024 + * Current protocol version
15025 + */
15026 +static const char* PROTOCOL_VERSION = "1";
15028 +#define RES_BUF_SIZE 128
15031 + * Enqueue attach-on-demand command to the given JVM
15032 + */
15033 +static
15034 +int enqueue_command(jvm_t* jvm, const char* cstr, int arg_count, const char** args) {
15035 + size_t size;
15036 + door_arg_t door_args;
15037 + char res_buffer[RES_BUF_SIZE];
15038 + int rc, i;
15039 + char* buf = NULL;
15040 + int result = -1;
15042 + /*
15043 + * First we get the command string and create the start of the
15044 + * argument string to send to the target VM:
15045 + * <ver>\0<cmd>\0
15046 + */
15047 + if (cstr == NULL) {
15048 + print_debug("command name is NULL\n");
15049 + goto quit;
15051 + size = strlen(PROTOCOL_VERSION) + strlen(cstr) + 2;
15052 + buf = (char*)malloc(size);
15053 + if (buf != NULL) {
15054 + char* pos = buf;
15055 + strcpy(buf, PROTOCOL_VERSION);
15056 + pos += strlen(PROTOCOL_VERSION)+1;
15057 + strcpy(pos, cstr);
15058 + } else {
15059 + set_jvm_error(JVM_ERR_OUT_OF_MEMORY);
15060 + print_debug("malloc failed at %d in %s\n", __LINE__, __FILE__);
15061 + goto quit;
15064 + /*
15065 + * Next we iterate over the arguments and extend the buffer
15066 + * to include them.
15067 + */
15068 + for (i=0; i<arg_count; i++) {
15069 + cstr = args[i];
15070 + if (cstr != NULL) {
15071 + size_t len = strlen(cstr);
15072 + char* newbuf = (char*)realloc(buf, size+len+1);
15073 + if (newbuf == NULL) {
15074 + set_jvm_error(JVM_ERR_OUT_OF_MEMORY);
15075 + print_debug("realloc failed in %s at %d\n", __FILE__, __LINE__);
15076 + goto quit;
15078 + buf = newbuf;
15079 + strcpy(buf+size, cstr);
15080 + size += len+1;
15084 + /*
15085 + * The arguments to the door function are in 'buf' so we now
15086 + * do the door call
15087 + */
15088 + door_args.data_ptr = buf;
15089 + door_args.data_size = size;
15090 + door_args.desc_ptr = NULL;
15091 + door_args.desc_num = 0;
15092 + door_args.rbuf = (char*)&res_buffer;
15093 + door_args.rsize = sizeof(res_buffer);
15095 + RESTARTABLE(door_call(jvm->door_fd, &door_args), rc);
15097 + /*
15098 + * door_call failed
15099 + */
15100 + if (rc == -1) {
15101 + print_debug("door_call failed\n");
15102 + } else {
15103 + /*
15104 + * door_call succeeded but the call didn't return the expected jint.
15105 + */
15106 + if (door_args.data_size < sizeof(int)) {
15107 + print_debug("Enqueue error - reason unknown as result is truncated!");
15108 + } else {
15109 + int* res = (int*)(door_args.data_ptr);
15110 + if (*res != 0) {
15111 + const char* msg = translate_error(*res);
15112 + if (msg == NULL) {
15113 + print_debug("Unable to enqueue command to target VM: %d\n", *res);
15114 + } else {
15115 + print_debug("Unable to enqueue command to target VM: %s\n", msg);
15117 + } else {
15118 + /*
15119 + * The door call should return a file descriptor to one end of
15120 + * a socket pair
15121 + */
15122 + if ((door_args.desc_ptr != NULL) &&
15123 + (door_args.desc_num == 1) &&
15124 + (door_args.desc_ptr->d_attributes & DOOR_DESCRIPTOR)) {
15125 + result = door_args.desc_ptr->d_data.d_desc.d_descriptor;
15126 + } else {
15127 + print_debug("Reply from enqueue missing descriptor!\n");
15133 +quit:
15134 + if (buf) free(buf);
15135 + return result;
15138 +/* read status code for a door command */
15139 +static int read_status(int fd) {
15140 + char ch, buf[16];
15141 + int index = 0;
15143 + while (1) {
15144 + if (file_read(fd, &ch, sizeof(ch)) != sizeof(ch)) {
15145 + set_jvm_error(JVM_ERR_DOOR_CANT_READ_STATUS);
15146 + print_debug("door cmd status: read status failed\n");
15147 + return -1;
15149 + buf[index++] = ch;
15150 + if (ch == '\n') {
15151 + buf[index - 1] = '\0';
15152 + return atoi(buf);
15154 + if (index == sizeof(buf)) {
15155 + set_jvm_error(JVM_ERR_DOOR_CANT_READ_STATUS);
15156 + print_debug("door cmd status: read status overflow\n");
15157 + return -1;
15162 +static const char* ENABLE_DPROBES_CMD = "enabledprobes";
15164 +/* enable one or more DTrace probes for a given JVM */
15165 +int jvm_enable_dtprobes(jvm_t* jvm, int num_probe_types, const char** probe_types) {
15166 + int fd, status = 0;
15167 + char ch;
15168 + const char* args[1];
15169 + char buf[16];
15170 + int probe_type = 0, index;
15171 + int count = 0;
15173 + if (jvm == NULL) {
15174 + set_jvm_error(JVM_ERR_NULL_PARAM);
15175 + print_debug("jvm_t* is NULL\n");
15176 + return -1;
15179 + if (num_probe_types == 0 || probe_types == NULL ||
15180 + probe_types[0] == NULL) {
15181 + set_jvm_error(JVM_ERR_INVALID_PARAM);
15182 + print_debug("invalid probe type argument(s)\n");
15183 + return -1;
15186 + for (index = 0; index < num_probe_types; index++) {
15187 + const char* p = probe_types[index];
15188 + if (strcmp(p, JVM_DTPROBE_OBJECT_ALLOC) == 0) {
15189 + probe_type |= DTRACE_ALLOC_PROBES;
15190 + count++;
15191 + } else if (strcmp(p, JVM_DTPROBE_METHOD_ENTRY) == 0 ||
15192 + strcmp(p, JVM_DTPROBE_METHOD_RETURN) == 0) {
15193 + probe_type |= DTRACE_METHOD_PROBES;
15194 + count++;
15195 + } else if (strcmp(p, JVM_DTPROBE_MONITOR_ENTER) == 0 ||
15196 + strcmp(p, JVM_DTPROBE_MONITOR_ENTERED) == 0 ||
15197 + strcmp(p, JVM_DTPROBE_MONITOR_EXIT) == 0 ||
15198 + strcmp(p, JVM_DTPROBE_MONITOR_WAIT) == 0 ||
15199 + strcmp(p, JVM_DTPROBE_MONITOR_WAITED) == 0 ||
15200 + strcmp(p, JVM_DTPROBE_MONITOR_NOTIFY) == 0 ||
15201 + strcmp(p, JVM_DTPROBE_MONITOR_NOTIFYALL) == 0) {
15202 + probe_type |= DTRACE_MONITOR_PROBES;
15203 + count++;
15204 + } else if (strcmp(p, JVM_DTPROBE_ALL) == 0) {
15205 + probe_type |= DTRACE_ALL_PROBES;
15206 + count++;
15210 + if (count == 0) {
15211 + return count;
15213 + sprintf(buf, "%d", probe_type);
15214 + args[0] = buf;
15216 + fd = enqueue_command(jvm, ENABLE_DPROBES_CMD, 1, args);
15217 + if (fd < 0) {
15218 + set_jvm_error(JVM_ERR_DOOR_CMD_SEND);
15219 + return -1;
15222 + status = read_status(fd);
15223 + // non-zero status is error
15224 + if (status) {
15225 + set_jvm_error(JVM_ERR_DOOR_CMD_STATUS);
15226 + print_debug("%s command failed (status: %d) in target JVM\n",
15227 + ENABLE_DPROBES_CMD, status);
15228 + file_close(fd);
15229 + return -1;
15231 + // read from stream until EOF
15232 + while (file_read(fd, &ch, sizeof(ch)) == sizeof(ch)) {
15233 + if (libjvm_dtrace_debug) {
15234 + printf("%c", ch);
15238 + file_close(fd);
15239 + clear_jvm_error();
15240 + return count;
15242 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/native/libjvm_dtrace/jvm_dtrace.h jdk22u-jdk-22.0.2-ga/src/java.base/solaris/native/libjvm_dtrace/jvm_dtrace.h
15243 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/native/libjvm_dtrace/jvm_dtrace.h 1970-01-01 01:00:00.000000000 +0100
15244 +++ jdk22u-jdk-22.0.2-ga/src/java.base/solaris/native/libjvm_dtrace/jvm_dtrace.h 2024-08-17 19:34:03.915152237 +0200
15245 @@ -0,0 +1,86 @@
15247 + * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
15248 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
15250 + * This code is free software; you can redistribute it and/or modify it
15251 + * under the terms of the GNU General Public License version 2 only, as
15252 + * published by the Free Software Foundation.
15254 + * This code is distributed in the hope that it will be useful, but WITHOUT
15255 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15256 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15257 + * version 2 for more details (a copy is included in the LICENSE file that
15258 + * accompanied this code).
15260 + * You should have received a copy of the GNU General Public License version
15261 + * 2 along with this work; if not, write to the Free Software Foundation,
15262 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
15264 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
15265 + * or visit www.oracle.com if you need additional information or have any
15266 + * questions.
15268 + */
15270 +#ifndef _JVM_DTRACE_H_
15271 +#define _JVM_DTRACE_H_
15274 + * Interface to dynamically turn on probes in Hotspot JVM. Currently,
15275 + * this interface can be used to dynamically enable certain DTrace
15276 + * probe points that are costly to have "always on".
15277 + */
15279 +#ifdef __cplusplus
15280 +extern "C" {
15281 +#endif
15283 +#include <sys/types.h>
15284 +#include "jni.h"
15286 +struct _jvm_t;
15287 +typedef struct _jvm_t jvm_t;
15290 +/* Attach to the given JVM process. Returns NULL on failure.
15291 + jvm_get_last_error() returns last error message. */
15292 +JNIEXPORT jvm_t* jvm_attach(pid_t pid);
15294 +/* Returns the last error message from this library or NULL if none. */
15295 +JNIEXPORT const char* jvm_get_last_error();
15297 +/* few well-known probe type constants for 'probe_types' param below */
15299 +#define JVM_DTPROBE_METHOD_ENTRY "method-entry"
15300 +#define JVM_DTPROBE_METHOD_RETURN "method-return"
15301 +#define JVM_DTPROBE_MONITOR_ENTER "monitor-contended-enter"
15302 +#define JVM_DTPROBE_MONITOR_ENTERED "monitor-contended-entered"
15303 +#define JVM_DTPROBE_MONITOR_EXIT "monitor-contended-exit"
15304 +#define JVM_DTPROBE_MONITOR_WAIT "monitor-wait"
15305 +#define JVM_DTPROBE_MONITOR_WAITED "monitor-waited"
15306 +#define JVM_DTPROBE_MONITOR_NOTIFY "monitor-notify"
15307 +#define JVM_DTPROBE_MONITOR_NOTIFYALL "monitor-notifyall"
15308 +#define JVM_DTPROBE_OBJECT_ALLOC "object-alloc"
15309 +#define JVM_DTPROBE_ALL "*"
15311 +/* Enable the specified DTrace probes of given probe types on
15312 + * the specified JVM. Returns >= 0 on success, -1 on failure.
15313 + * On success, this returns number of probe_types enabled.
15314 + * On failure, jvm_get_last_error() returns the last error message.
15315 + */
15316 +JNIEXPORT int jvm_enable_dtprobes(jvm_t* jvm, int num_probe_types, const char** probe_types);
15318 +/* Note: There is no jvm_disable_dtprobes function. Probes are automatically
15319 + * disabled when there are no more clients requiring those probes.
15320 + */
15322 +/* Detach the given JVM. Returns 0 on success, -1 on failure.
15323 + * jvm_get_last_error() returns the last error message.
15324 + */
15325 +JNIEXPORT int jvm_detach(jvm_t* jvm);
15327 +#ifdef __cplusplus
15329 +#endif
15331 +#endif /* _JVM_DTRACE_H_ */
15332 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/native/libnet/solaris_close.c jdk22u-jdk-22.0.2-ga/src/java.base/solaris/native/libnet/solaris_close.c
15333 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/native/libnet/solaris_close.c 1970-01-01 01:00:00.000000000 +0100
15334 +++ jdk22u-jdk-22.0.2-ga/src/java.base/solaris/native/libnet/solaris_close.c 2024-08-17 19:34:03.915507014 +0200
15335 @@ -0,0 +1,107 @@
15337 + * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
15338 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
15340 + * This code is free software; you can redistribute it and/or modify it
15341 + * under the terms of the GNU General Public License version 2 only, as
15342 + * published by the Free Software Foundation. Oracle designates this
15343 + * particular file as subject to the "Classpath" exception as provided
15344 + * by Oracle in the LICENSE file that accompanied this code.
15346 + * This code is distributed in the hope that it will be useful, but WITHOUT
15347 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15348 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15349 + * version 2 for more details (a copy is included in the LICENSE file that
15350 + * accompanied this code).
15352 + * You should have received a copy of the GNU General Public License version
15353 + * 2 along with this work; if not, write to the Free Software Foundation,
15354 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
15356 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
15357 + * or visit www.oracle.com if you need additional information or have any
15358 + * questions.
15359 + */
15361 +#include <errno.h>
15362 +#include <sys/socket.h>
15363 +#include <stropts.h>
15364 +#include <unistd.h>
15365 +#include "jvm.h"
15366 +#include "net_util.h"
15368 +/* Support for restartable system calls on Solaris. */
15370 +#define RESTARTABLE_RETURN_INT(_cmd) do { \
15371 + int _result; \
15372 + if (1) { \
15373 + do { \
15374 + _result = _cmd; \
15375 + } while((_result == -1) && (errno == EINTR)); \
15376 + return _result; \
15377 + } \
15378 +} while(0)
15380 +int NET_Read(int s, void* buf, size_t len) {
15381 + RESTARTABLE_RETURN_INT(recv(s, buf, len, 0));
15384 +int NET_NonBlockingRead(int s, void* buf, size_t len) {
15385 + RESTARTABLE_RETURN_INT(recv(s, buf, len, MSG_DONTWAIT));
15388 +int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
15389 + struct sockaddr *from, socklen_t *fromlen) {
15390 + RESTARTABLE_RETURN_INT(recvfrom(s, buf, len, flags, from, fromlen));
15393 +int NET_Send(int s, void *msg, int len, unsigned int flags) {
15394 + RESTARTABLE_RETURN_INT(send(s, msg, len, flags));
15397 +int NET_SendTo(int s, const void *msg, int len, unsigned int flags,
15398 + const struct sockaddr *to, int tolen) {
15399 + RESTARTABLE_RETURN_INT(sendto(s, msg, len, flags, to, tolen));
15402 +int NET_Connect(int s, struct sockaddr *addr, int addrlen) {
15403 + RESTARTABLE_RETURN_INT(connect(s, addr, addrlen));
15406 +int NET_Accept(int s, struct sockaddr *addr, socklen_t *addrlen) {
15407 + RESTARTABLE_RETURN_INT(accept(s, addr, addrlen));
15410 +int NET_SocketClose(int fd) {
15411 + return close(fd);
15414 +int NET_Dup2(int fd, int fd2) {
15415 + return dup2(fd, fd2);
15418 +int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
15419 + RESTARTABLE_RETURN_INT(poll(ufds, nfds, timeout));
15422 +int NET_Timeout(JNIEnv *env, int s, long timeout, jlong nanoTimeStamp) {
15423 + int result;
15424 + jlong prevNanoTime = nanoTimeStamp;
15425 + jlong nanoTimeout = (jlong) timeout * NET_NSEC_PER_MSEC;
15426 + struct pollfd pfd;
15427 + pfd.fd = s;
15428 + pfd.events = POLLIN;
15430 + for(;;) {
15431 + result = poll(&pfd, 1, nanoTimeout / NET_NSEC_PER_MSEC);
15432 + if (result < 0 && errno == EINTR) {
15433 + jlong newNanoTime = JVM_NanoTime(env, 0);
15434 + nanoTimeout -= newNanoTime - prevNanoTime;
15435 + if (nanoTimeout < NET_NSEC_PER_MSEC)
15436 + return 0;
15437 + prevNanoTime = newNanoTime;
15438 + } else {
15439 + return result;
15443 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/native/libnio/ch/DevPollArrayWrapper.c jdk22u-jdk-22.0.2-ga/src/java.base/solaris/native/libnio/ch/DevPollArrayWrapper.c
15444 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/native/libnio/ch/DevPollArrayWrapper.c 1970-01-01 01:00:00.000000000 +0100
15445 +++ jdk22u-jdk-22.0.2-ga/src/java.base/solaris/native/libnio/ch/DevPollArrayWrapper.c 2024-08-17 19:34:03.915913914 +0200
15446 @@ -0,0 +1,112 @@
15448 + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
15449 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
15451 + * This code is free software; you can redistribute it and/or modify it
15452 + * under the terms of the GNU General Public License version 2 only, as
15453 + * published by the Free Software Foundation. Oracle designates this
15454 + * particular file as subject to the "Classpath" exception as provided
15455 + * by Oracle in the LICENSE file that accompanied this code.
15457 + * This code is distributed in the hope that it will be useful, but WITHOUT
15458 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15459 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15460 + * version 2 for more details (a copy is included in the LICENSE file that
15461 + * accompanied this code).
15463 + * You should have received a copy of the GNU General Public License version
15464 + * 2 along with this work; if not, write to the Free Software Foundation,
15465 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
15467 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
15468 + * or visit www.oracle.com if you need additional information or have any
15469 + * questions.
15470 + */
15472 +#include <sys/types.h>
15473 +#include <sys/stat.h>
15474 +#include <devpoll.h>
15475 +#include <fcntl.h>
15476 +#include <poll.h>
15478 +#include "jni.h"
15479 +#include "jni_util.h"
15480 +#include "jvm.h"
15481 +#include "jlong.h"
15482 +#include "nio.h"
15483 +#include "nio_util.h"
15485 +#include "sun_nio_ch_DevPollArrayWrapper.h"
15487 +JNIEXPORT jint JNICALL
15488 +Java_sun_nio_ch_DevPollArrayWrapper_init(JNIEnv *env, jobject this)
15490 + int wfd = open("/dev/poll", O_RDWR);
15491 + if (wfd < 0) {
15492 + JNU_ThrowIOExceptionWithLastError(env, "Error opening driver");
15493 + return -1;
15495 + return wfd;
15498 +JNIEXPORT void JNICALL
15499 +Java_sun_nio_ch_DevPollArrayWrapper_register(JNIEnv *env, jobject this,
15500 + jint wfd, jint fd, jint mask)
15502 + struct pollfd a[1];
15503 + int n;
15505 + a[0].fd = fd;
15506 + a[0].events = mask;
15507 + a[0].revents = 0;
15509 + n = write(wfd, &a[0], sizeof(a));
15510 + if (n != sizeof(a)) {
15511 + if (n < 0) {
15512 + JNU_ThrowIOExceptionWithLastError(env, "Error writing pollfds");
15513 + } else {
15514 + JNU_ThrowIOException(env, "Unexpected number of bytes written");
15519 +JNIEXPORT void JNICALL
15520 +Java_sun_nio_ch_DevPollArrayWrapper_registerMultiple(JNIEnv *env, jobject this,
15521 + jint wfd, jlong address,
15522 + jint len)
15524 + unsigned char *pollBytes = (unsigned char *)jlong_to_ptr(address);
15525 + unsigned char *pollEnd = pollBytes + sizeof(struct pollfd) * len;
15526 + while (pollBytes < pollEnd) {
15527 + int bytesWritten = write(wfd, pollBytes, (int)(pollEnd - pollBytes));
15528 + if (bytesWritten < 0) {
15529 + JNU_ThrowIOExceptionWithLastError(env, "Error writing pollfds");
15530 + return;
15532 + pollBytes += bytesWritten;
15536 +JNIEXPORT jint JNICALL
15537 +Java_sun_nio_ch_DevPollArrayWrapper_poll0(JNIEnv *env, jobject this,
15538 + jlong address, jint numfds,
15539 + jlong timeout, jint wfd)
15541 + struct dvpoll a;
15542 + void *pfd = (void *) jlong_to_ptr(address);
15543 + int result;
15545 + a.dp_fds = pfd;
15546 + a.dp_nfds = numfds;
15547 + a.dp_timeout = (int)timeout;
15548 + result = ioctl(wfd, DP_POLL, &a);
15549 + if (result < 0) {
15550 + if (errno == EINTR) {
15551 + return IOS_INTERRUPTED;
15552 + } else {
15553 + JNU_ThrowIOExceptionWithLastError(env, "Error reading driver");
15554 + return IOS_THROWN;
15557 + return result;
15559 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/native/libnio/ch/SolarisEventPort.c jdk22u-jdk-22.0.2-ga/src/java.base/solaris/native/libnio/ch/SolarisEventPort.c
15560 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/native/libnio/ch/SolarisEventPort.c 1970-01-01 01:00:00.000000000 +0100
15561 +++ jdk22u-jdk-22.0.2-ga/src/java.base/solaris/native/libnio/ch/SolarisEventPort.c 2024-08-17 19:34:03.916236934 +0200
15562 @@ -0,0 +1,147 @@
15564 + * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
15565 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
15567 + * This code is free software; you can redistribute it and/or modify it
15568 + * under the terms of the GNU General Public License version 2 only, as
15569 + * published by the Free Software Foundation. Oracle designates this
15570 + * particular file as subject to the "Classpath" exception as provided
15571 + * by Oracle in the LICENSE file that accompanied this code.
15573 + * This code is distributed in the hope that it will be useful, but WITHOUT
15574 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15575 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15576 + * version 2 for more details (a copy is included in the LICENSE file that
15577 + * accompanied this code).
15579 + * You should have received a copy of the GNU General Public License version
15580 + * 2 along with this work; if not, write to the Free Software Foundation,
15581 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
15583 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
15584 + * or visit www.oracle.com if you need additional information or have any
15585 + * questions.
15586 + */
15588 +#include <stdlib.h>
15589 +#include <dlfcn.h>
15590 +#include <sys/types.h>
15591 +#include <port.h>
15593 +#include "jni.h"
15594 +#include "jni_util.h"
15595 +#include "jvm.h"
15596 +#include "jlong.h"
15597 +#include "nio.h"
15598 +#include "nio_util.h"
15600 +#include "sun_nio_ch_SolarisEventPort.h"
15602 +JNIEXPORT jint JNICALL
15603 +Java_sun_nio_ch_SolarisEventPort_port_1create
15604 + (JNIEnv* env, jclass clazz)
15606 + int port = port_create();
15607 + if (port == -1) {
15608 + JNU_ThrowIOExceptionWithLastError(env, "port_create");
15610 + return (jint)port;
15613 +JNIEXPORT void JNICALL
15614 +Java_sun_nio_ch_SolarisEventPort_port_1close
15615 + (JNIEnv* env, jclass clazz, jint port)
15617 + int res = close(port);
15618 + if (res < 0 && res != EINTR) {
15619 + JNU_ThrowIOExceptionWithLastError(env, "close failed");
15623 +JNIEXPORT jboolean JNICALL
15624 +Java_sun_nio_ch_SolarisEventPort_port_1associate
15625 + (JNIEnv* env, jclass clazz, jint port, jint source, jlong objectAddress, jint events)
15627 + uintptr_t object = (uintptr_t)jlong_to_ptr(objectAddress);
15628 + if (port_associate((int)port, (int)source, object, (int)events, NULL) == 0) {
15629 + return JNI_TRUE;
15630 + } else {
15631 + if (errno != EBADFD)
15632 + JNU_ThrowIOExceptionWithLastError(env, "port_associate");
15633 + return JNI_FALSE;
15637 +JNIEXPORT jboolean JNICALL
15638 +Java_sun_nio_ch_SolarisEventPort_port_1dissociate
15639 + (JNIEnv* env, jclass clazz, jint port, jint source, jlong objectAddress)
15641 + uintptr_t object = (uintptr_t)jlong_to_ptr(objectAddress);
15643 + if (port_dissociate((int)port, (int)source, object) == 0) {
15644 + return JNI_TRUE;
15645 + } else {
15646 + if (errno != ENOENT)
15647 + JNU_ThrowIOExceptionWithLastError(env, "port_dissociate");
15648 + return JNI_FALSE;
15652 +JNIEXPORT void JNICALL
15653 +Java_sun_nio_ch_SolarisEventPort_port_1send(JNIEnv* env, jclass clazz,
15654 + jint port, jint events)
15656 + if (port_send((int)port, (int)events, NULL) == -1) {
15657 + JNU_ThrowIOExceptionWithLastError(env, "port_send");
15661 +JNIEXPORT jint JNICALL
15662 +Java_sun_nio_ch_SolarisEventPort_port_1get(JNIEnv* env, jclass clazz,
15663 + jint port, jlong eventAddress)
15665 + int res;
15666 + port_event_t* ev = (port_event_t*)jlong_to_ptr(eventAddress);
15668 + res = port_get((int)port, ev, NULL);
15669 + if (res == -1) {
15670 + if (errno == EINTR) {
15671 + return IOS_INTERRUPTED;
15672 + } else {
15673 + JNU_ThrowIOExceptionWithLastError(env, "port_get failed");
15674 + return IOS_THROWN;
15677 + return res;
15680 +JNIEXPORT jint JNICALL
15681 +Java_sun_nio_ch_SolarisEventPort_port_1getn(JNIEnv* env, jclass clazz,
15682 + jint port, jlong arrayAddress, jint max, jlong timeout)
15684 + int res;
15685 + uint_t n = 1;
15686 + port_event_t* list = (port_event_t*)jlong_to_ptr(arrayAddress);
15687 + timespec_t ts;
15688 + timespec_t* tsp;
15690 + if (timeout >= 0L) {
15691 + ts.tv_sec = timeout / 1000;
15692 + ts.tv_nsec = 1000000 * (timeout % 1000);
15693 + tsp = &ts;
15694 + } else {
15695 + tsp = NULL;
15698 + res = port_getn((int)port, list, (uint_t)max, &n, tsp);
15699 + if (res == -1 && errno != ETIME) {
15700 + if (errno == EINTR) {
15701 + return IOS_INTERRUPTED;
15702 + } else {
15703 + JNU_ThrowIOExceptionWithLastError(env, "port_getn failed");
15704 + return IOS_THROWN;
15708 + return (jint)n;
15710 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/native/libnio/fs/SolarisNativeDispatcher.c jdk22u-jdk-22.0.2-ga/src/java.base/solaris/native/libnio/fs/SolarisNativeDispatcher.c
15711 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/native/libnio/fs/SolarisNativeDispatcher.c 1970-01-01 01:00:00.000000000 +0100
15712 +++ jdk22u-jdk-22.0.2-ga/src/java.base/solaris/native/libnio/fs/SolarisNativeDispatcher.c 2024-08-17 19:34:03.916611185 +0200
15713 @@ -0,0 +1,143 @@
15715 + * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
15716 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
15718 + * This code is free software; you can redistribute it and/or modify it
15719 + * under the terms of the GNU General Public License version 2 only, as
15720 + * published by the Free Software Foundation. Oracle designates this
15721 + * particular file as subject to the "Classpath" exception as provided
15722 + * by Oracle in the LICENSE file that accompanied this code.
15724 + * This code is distributed in the hope that it will be useful, but WITHOUT
15725 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15726 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15727 + * version 2 for more details (a copy is included in the LICENSE file that
15728 + * accompanied this code).
15730 + * You should have received a copy of the GNU General Public License version
15731 + * 2 along with this work; if not, write to the Free Software Foundation,
15732 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
15734 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
15735 + * or visit www.oracle.com if you need additional information or have any
15736 + * questions.
15737 + */
15739 +#include "jni.h"
15740 +#include "jni_util.h"
15741 +#include "jvm.h"
15742 +#include "jlong.h"
15744 +#include <strings.h>
15745 +#include <errno.h>
15746 +#include <sys/acl.h>
15747 +#include <sys/mnttab.h>
15748 +#include <sys/mkdev.h>
15750 +#include "jni.h"
15752 +#include "sun_nio_fs_SolarisNativeDispatcher.h"
15754 +static jfieldID entry_name;
15755 +static jfieldID entry_dir;
15756 +static jfieldID entry_fstype;
15757 +static jfieldID entry_options;
15758 +static jfieldID entry_dev;
15760 +static void throwUnixException(JNIEnv* env, int errnum) {
15761 + jobject x = JNU_NewObjectByName(env, "sun/nio/fs/UnixException",
15762 + "(I)V", errnum);
15763 + if (x != NULL) {
15764 + (*env)->Throw(env, x);
15768 +JNIEXPORT void JNICALL
15769 +Java_sun_nio_fs_SolarisNativeDispatcher_init(JNIEnv *env, jclass clazz) {
15770 + clazz = (*env)->FindClass(env, "sun/nio/fs/UnixMountEntry");
15771 + CHECK_NULL(clazz);
15772 + entry_name = (*env)->GetFieldID(env, clazz, "name", "[B");
15773 + CHECK_NULL(entry_name);
15774 + entry_dir = (*env)->GetFieldID(env, clazz, "dir", "[B");
15775 + CHECK_NULL(entry_dir);
15776 + entry_fstype = (*env)->GetFieldID(env, clazz, "fstype", "[B");
15777 + CHECK_NULL(entry_fstype);
15778 + entry_options = (*env)->GetFieldID(env, clazz, "opts", "[B");
15779 + CHECK_NULL(entry_options);
15780 + entry_dev = (*env)->GetFieldID(env, clazz, "dev", "J");
15781 + CHECK_NULL(entry_dev);
15784 +JNIEXPORT jint JNICALL
15785 +Java_sun_nio_fs_SolarisNativeDispatcher_facl(JNIEnv* env, jclass this, jint fd,
15786 + jint cmd, jint nentries, jlong address)
15788 + void* aclbufp = jlong_to_ptr(address);
15789 + int n = -1;
15791 + n = facl((int)fd, (int)cmd, (int)nentries, aclbufp);
15792 + if (n == -1) {
15793 + throwUnixException(env, errno);
15795 + return (jint)n;
15798 +JNIEXPORT jint JNICALL
15799 +Java_sun_nio_fs_SolarisNativeDispatcher_getextmntent(JNIEnv* env, jclass this,
15800 + jlong value, jobject entry)
15802 + struct extmnttab ent;
15803 + FILE* fp = jlong_to_ptr(value);
15804 + jsize len;
15805 + jbyteArray bytes;
15806 + char* name;
15807 + char* dir;
15808 + char* fstype;
15809 + char* options;
15810 + dev_t dev;
15812 + if (getextmntent(fp, &ent, 0))
15813 + return -1;
15814 + name = ent.mnt_special;
15815 + dir = ent.mnt_mountp;
15816 + fstype = ent.mnt_fstype;
15817 + options = ent.mnt_mntopts;
15818 + dev = makedev(ent.mnt_major, ent.mnt_minor);
15819 + if (dev == NODEV) {
15820 + throwUnixException(env, errno);
15821 + return -1;
15824 + len = strlen(name);
15825 + bytes = (*env)->NewByteArray(env, len);
15826 + if (bytes == NULL)
15827 + return -1;
15828 + (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)name);
15829 + (*env)->SetObjectField(env, entry, entry_name, bytes);
15831 + len = strlen(dir);
15832 + bytes = (*env)->NewByteArray(env, len);
15833 + if (bytes == NULL)
15834 + return -1;
15835 + (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)dir);
15836 + (*env)->SetObjectField(env, entry, entry_dir, bytes);
15838 + len = strlen(fstype);
15839 + bytes = (*env)->NewByteArray(env, len);
15840 + if (bytes == NULL)
15841 + return -1;
15842 + (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)fstype);
15843 + (*env)->SetObjectField(env, entry, entry_fstype, bytes);
15845 + len = strlen(options);
15846 + bytes = (*env)->NewByteArray(env, len);
15847 + if (bytes == NULL)
15848 + return -1;
15849 + (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)options);
15850 + (*env)->SetObjectField(env, entry, entry_options, bytes);
15852 + if (dev != 0)
15853 + (*env)->SetLongField(env, entry, entry_dev, (jlong)dev);
15855 + return 0;
15857 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/native/libnio/fs/SolarisWatchService.c jdk22u-jdk-22.0.2-ga/src/java.base/solaris/native/libnio/fs/SolarisWatchService.c
15858 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/solaris/native/libnio/fs/SolarisWatchService.c 1970-01-01 01:00:00.000000000 +0100
15859 +++ jdk22u-jdk-22.0.2-ga/src/java.base/solaris/native/libnio/fs/SolarisWatchService.c 2024-08-17 19:34:03.916906548 +0200
15860 @@ -0,0 +1,104 @@
15862 + * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
15863 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
15865 + * This code is free software; you can redistribute it and/or modify it
15866 + * under the terms of the GNU General Public License version 2 only, as
15867 + * published by the Free Software Foundation. Oracle designates this
15868 + * particular file as subject to the "Classpath" exception as provided
15869 + * by Oracle in the LICENSE file that accompanied this code.
15871 + * This code is distributed in the hope that it will be useful, but WITHOUT
15872 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15873 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15874 + * version 2 for more details (a copy is included in the LICENSE file that
15875 + * accompanied this code).
15877 + * You should have received a copy of the GNU General Public License version
15878 + * 2 along with this work; if not, write to the Free Software Foundation,
15879 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
15881 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
15882 + * or visit www.oracle.com if you need additional information or have any
15883 + * questions.
15884 + */
15886 +#include "jni.h"
15887 +#include "jni_util.h"
15888 +#include "jvm.h"
15889 +#include "jlong.h"
15891 +#include <stdlib.h>
15892 +#include <dlfcn.h>
15893 +#include <sys/types.h>
15894 +#include <port.h> // Solaris 10
15896 +#include "sun_nio_fs_SolarisWatchService.h"
15898 +static void throwUnixException(JNIEnv* env, int errnum) {
15899 + jobject x = JNU_NewObjectByName(env, "sun/nio/fs/UnixException",
15900 + "(I)V", errnum);
15901 + if (x != NULL) {
15902 + (*env)->Throw(env, x);
15906 +JNIEXPORT void JNICALL
15907 +Java_sun_nio_fs_SolarisWatchService_init(JNIEnv *env, jclass clazz)
15911 +JNIEXPORT jint JNICALL
15912 +Java_sun_nio_fs_SolarisWatchService_portCreate
15913 + (JNIEnv* env, jclass clazz)
15915 + int port = port_create();
15916 + if (port == -1) {
15917 + throwUnixException(env, errno);
15919 + return (jint)port;
15922 +JNIEXPORT void JNICALL
15923 +Java_sun_nio_fs_SolarisWatchService_portAssociate
15924 + (JNIEnv* env, jclass clazz, jint port, jint source, jlong objectAddress, jint events)
15926 + uintptr_t object = (uintptr_t)jlong_to_ptr(objectAddress);
15928 + if (port_associate((int)port, (int)source, object, (int)events, NULL) == -1) {
15929 + throwUnixException(env, errno);
15933 +JNIEXPORT void JNICALL
15934 +Java_sun_nio_fs_SolarisWatchService_portDissociate
15935 + (JNIEnv* env, jclass clazz, jint port, jint source, jlong objectAddress)
15937 + uintptr_t object = (uintptr_t)jlong_to_ptr(objectAddress);
15939 + if (port_dissociate((int)port, (int)source, object) == -1) {
15940 + throwUnixException(env, errno);
15944 +JNIEXPORT void JNICALL
15945 +Java_sun_nio_fs_SolarisWatchService_portSend(JNIEnv* env, jclass clazz,
15946 + jint port, jint events)
15948 + if (port_send((int)port, (int)events, NULL) == -1) {
15949 + throwUnixException(env, errno);
15953 +JNIEXPORT jint JNICALL
15954 +Java_sun_nio_fs_SolarisWatchService_portGetn(JNIEnv* env, jclass clazz,
15955 + jint port, jlong arrayAddress, jint max)
15957 + uint_t n = 1;
15958 + port_event_t* list = (port_event_t*)jlong_to_ptr(arrayAddress);
15960 + if (port_getn((int)port, list, (uint_t)max, &n, NULL) == -1) {
15961 + throwUnixException(env, errno);
15963 + return (jint)n;
15965 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/classes/java/lang/ProcessImpl.java jdk22u-jdk-22.0.2-ga/src/java.base/unix/classes/java/lang/ProcessImpl.java
15966 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/classes/java/lang/ProcessImpl.java 2024-06-04 18:47:50.000000000 +0200
15967 +++ jdk22u-jdk-22.0.2-ga/src/java.base/unix/classes/java/lang/ProcessImpl.java 2024-08-17 19:34:03.859413698 +0200
15968 @@ -83,6 +83,9 @@
15969 private /* final */ InputStream stdout;
15970 private /* final */ InputStream stderr;
15972 + // only used on Solaris
15973 + private /* final */ DeferredCloseInputStream stdout_inner_stream;
15975 private static enum LaunchMechanism {
15976 // order IS important!
15977 FORK,
15978 @@ -108,6 +111,7 @@
15979 return lm; // All options are valid for Linux
15980 case AIX:
15981 case MACOS:
15982 + case SOLARIS:
15983 if (lm != LaunchMechanism.VFORK) {
15984 return lm; // All but VFORK are valid
15986 @@ -364,6 +368,44 @@
15988 break;
15990 + case SOLARIS:
15991 + stdin = (fds[0] == -1) ?
15992 + ProcessBuilder.NullOutputStream.INSTANCE :
15993 + new BufferedOutputStream(
15994 + new FileOutputStream(newFileDescriptor(fds[0])));
15996 + stdout = (fds[1] == -1 || forceNullOutputStream) ?
15997 + ProcessBuilder.NullInputStream.INSTANCE :
15998 + new BufferedInputStream(
15999 + stdout_inner_stream =
16000 + new DeferredCloseInputStream(
16001 + newFileDescriptor(fds[1])));
16003 + stderr = (fds[2] == -1) ?
16004 + ProcessBuilder.NullInputStream.INSTANCE :
16005 + new DeferredCloseInputStream(newFileDescriptor(fds[2]));
16007 + /*
16008 + * For each subprocess forked a corresponding reaper task
16009 + * is submitted. That task is the only thread which waits
16010 + * for the subprocess to terminate and it doesn't hold any
16011 + * locks while doing so. This design allows waitFor() and
16012 + * exitStatus() to be safely executed in parallel (and they
16013 + * need no native code).
16014 + */
16015 + ProcessHandleImpl.completion(pid, true).handle((exitcode, throwable) -> {
16016 + lock.lock();
16017 + try {
16018 + this.exitcode = (exitcode == null) ? -1 : exitcode.intValue();
16019 + this.hasExited = true;
16020 + condition.signalAll();
16021 + } finally {
16022 + lock.unlock();
16024 + return null;
16025 + });
16026 + break;
16028 case AIX:
16029 stdin = (fds[0] == -1) ?
16030 ProcessBuilder.NullOutputStream.INSTANCE :
16031 @@ -480,6 +522,32 @@
16032 try { stderr.close(); } catch (IOException ignored) {}
16033 break;
16035 + case SOLARIS:
16036 + // There is a risk that pid will be recycled, causing us to
16037 + // kill the wrong process! So we only terminate processes
16038 + // that appear to still be running. Even with this check,
16039 + // there is an unavoidable race condition here, but the window
16040 + // is very small, and OSes try hard to not recycle pids too
16041 + // soon, so this is quite safe.
16042 + lock.lock();
16043 + try {
16044 + if (!hasExited)
16045 + processHandle.destroyProcess(force);
16046 + } finally {
16047 + lock.unlock();
16049 + try {
16050 + stdin.close();
16051 + if (stdout_inner_stream != null)
16052 + stdout_inner_stream.closeDeferred(stdout);
16053 + if (stderr instanceof DeferredCloseInputStream)
16054 + ((DeferredCloseInputStream) stderr)
16055 + .closeDeferred(stderr);
16056 + } catch (IOException e) {
16057 + // ignore
16059 + break;
16061 default: throw new AssertionError("Unsupported platform: " + OperatingSystem.current());
16064 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/classes/sun/net/PortConfig.java jdk22u-jdk-22.0.2-ga/src/java.base/unix/classes/sun/net/PortConfig.java
16065 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/classes/sun/net/PortConfig.java 2024-06-04 18:47:50.000000000 +0200
16066 +++ jdk22u-jdk-22.0.2-ga/src/java.base/unix/classes/sun/net/PortConfig.java 2024-08-17 19:34:03.859822604 +0200
16067 @@ -48,6 +48,10 @@
16068 defaultLower = 32768;
16069 defaultUpper = 61000;
16070 break;
16071 + case SOLARIS:
16072 + defaultLower = 32768;
16073 + defaultUpper = 65535;
16074 + break;
16075 case MACOS:
16076 defaultLower = 49152;
16077 defaultUpper = 65535;
16078 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/classes/sun/nio/fs/UnixConstants.java.template jdk22u-jdk-22.0.2-ga/src/java.base/unix/classes/sun/nio/fs/UnixConstants.java.template
16079 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/classes/sun/nio/fs/UnixConstants.java.template 2024-06-04 18:47:50.000000000 +0200
16080 +++ jdk22u-jdk-22.0.2-ga/src/java.base/unix/classes/sun/nio/fs/UnixConstants.java.template 2024-08-17 19:34:03.860241575 +0200
16081 @@ -35,6 +35,10 @@
16082 #include <sys/clonefile.h>
16083 #endif
16085 +/* On Solaris, "sun" is defined as a macro. Undefine to make package
16086 + declaration valid */
16087 +#undef sun
16089 /* To be able to name the Java constants the same as the C constants without
16090 having the preprocessor rewrite those identifiers, add PREFIX_ to all
16091 identifiers matching a C constant. The PREFIX_ is filtered out in the
16092 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java jdk22u-jdk-22.0.2-ga/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java
16093 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java 2024-06-04 18:47:50.000000000 +0200
16094 +++ jdk22u-jdk-22.0.2-ga/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java 2024-08-17 19:34:03.860782020 +0200
16095 @@ -128,6 +128,10 @@
16096 return rootDirectory;
16099 + boolean isSolaris() {
16100 + return false;
16103 static List<String> standardFileAttributeViews() {
16104 return Arrays.asList("basic", "posix", "unix", "owner");
16106 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/classes/sun/nio/fs/UnixPath.java jdk22u-jdk-22.0.2-ga/src/java.base/unix/classes/sun/nio/fs/UnixPath.java
16107 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/classes/sun/nio/fs/UnixPath.java 2024-06-04 18:47:50.000000000 +0200
16108 +++ jdk22u-jdk-22.0.2-ga/src/java.base/unix/classes/sun/nio/fs/UnixPath.java 2024-08-17 19:34:03.861300810 +0200
16109 @@ -831,7 +831,15 @@
16110 ("NOFOLLOW_LINKS is not supported on this platform");
16111 flags |= O_NOFOLLOW;
16113 - return open(this, flags, 0);
16114 + try {
16115 + return open(this, flags, 0);
16116 + } catch (UnixException x) {
16117 + // HACK: EINVAL instead of ELOOP on Solaris 10 prior to u4 (see 6460380)
16118 + if (getFileSystem().isSolaris() && x.errno() == EINVAL)
16119 + x.setError(ELOOP);
16121 + throw x;
16125 void checkRead() {
16126 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/classes/sun/security/provider/NativePRNG.java jdk22u-jdk-22.0.2-ga/src/java.base/unix/classes/sun/security/provider/NativePRNG.java
16127 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/classes/sun/security/provider/NativePRNG.java 2024-06-04 18:47:50.000000000 +0200
16128 +++ jdk22u-jdk-22.0.2-ga/src/java.base/unix/classes/sun/security/provider/NativePRNG.java 2024-08-17 19:34:03.861772427 +0200
16129 @@ -33,7 +33,7 @@
16130 import sun.security.util.Debug;
16133 - * Native PRNG implementation for Linux/MacOS.
16134 + * Native PRNG implementation for Solaris/Linux/MacOS.
16135 * <p>
16136 * It obtains seed and random numbers by reading system files such as
16137 * the special device files /dev/random and /dev/urandom. This
16138 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libjava/io_util_md.c jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libjava/io_util_md.c
16139 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libjava/io_util_md.c 2024-06-04 18:47:50.000000000 +0200
16140 +++ jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libjava/io_util_md.c 2024-08-17 19:34:03.865034463 +0200
16141 @@ -30,6 +30,10 @@
16142 #include <string.h>
16143 #include <unistd.h>
16145 +#ifdef __solaris__
16146 +#include <sys/filio.h>
16147 +#endif
16149 #if defined(__linux__) || defined(_ALLBSD_SOURCE) || defined(_AIX)
16150 #include <sys/ioctl.h>
16151 #endif
16152 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libjava/java_props_md.c jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libjava/java_props_md.c
16153 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libjava/java_props_md.c 2024-06-04 18:47:50.000000000 +0200
16154 +++ jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libjava/java_props_md.c 2024-08-17 19:34:03.865478858 +0200
16155 @@ -323,6 +323,27 @@
16157 #endif
16159 +#ifdef __solaris__
16160 + if (strcmp(p,"eucJP") == 0) {
16161 + /* For Solaris use customized vendor defined character
16162 + * customized EUC-JP converter
16163 + */
16164 + *std_encoding = "eucJP-open";
16165 + } else if (strcmp(p, "Big5") == 0 || strcmp(p, "BIG5") == 0) {
16166 + /*
16167 + * Remap the encoding string to Big5_Solaris which augments
16168 + * the default converter for Solaris Big5 locales to include
16169 + * seven additional ideographic characters beyond those included
16170 + * in the Java "Big5" converter.
16171 + */
16172 + *std_encoding = "Big5_Solaris";
16173 + } else if (strcmp(p, "Big5-HKSCS") == 0) {
16174 + /*
16175 + * Solaris uses HKSCS2001
16176 + */
16177 + *std_encoding = "Big5-HKSCS-2001";
16179 +#endif
16180 #ifdef MACOSX
16182 * For the case on MacOS X where encoding is set to US-ASCII, but we
16183 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libjava/jlong_md.h jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libjava/jlong_md.h
16184 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libjava/jlong_md.h 2024-06-04 18:47:50.000000000 +0200
16185 +++ jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libjava/jlong_md.h 2024-08-17 19:34:03.865880595 +0200
16186 @@ -23,8 +23,8 @@
16187 * questions.
16190 -#ifndef _UNIX_JLONG_MD_H_
16191 -#define _UNIX_JLONG_MD_H_
16192 +#ifndef _SOLARIS_JLONG_MD_H_
16193 +#define _SOLARIS_JLONG_MD_H_
16195 /* Make sure ptrdiff_t is defined */
16196 #include <stddef.h>
16197 @@ -97,4 +97,4 @@
16198 #define size_to_jlong(a) ((jlong)(a))
16199 #define long_to_jlong(a) ((jlong)(a))
16201 -#endif /* !_UNIX_JLONG_MD_H_ */
16202 +#endif /* !_SOLARIS_JLONG_MD_H_ */
16203 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c
16204 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c 2024-06-04 18:47:50.000000000 +0200
16205 +++ jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c 2024-08-17 19:34:03.862508362 +0200
16206 @@ -45,10 +45,20 @@
16207 #include <sys/stat.h>
16208 #include <sys/wait.h>
16210 +/* For POSIX-compliant getpwuid_r on Solaris */
16211 +#if defined(__solaris__)
16212 +#define _POSIX_PTHREAD_SEMANTICS
16213 +#endif
16214 #include <pwd.h>
16216 +#ifdef _AIX
16217 +#include <sys/procfs.h>
16218 +#endif
16219 +#ifdef __solaris__
16220 +#include <procfs.h>
16221 +#endif
16223 #if defined(_AIX)
16224 - #include <sys/procfs.h>
16225 #define DIR DIR64
16226 #define dirent dirent64
16227 #define opendir opendir64
16228 @@ -128,13 +138,18 @@
16229 #define WTERMSIG(status) ((status)&0x7F)
16230 #endif
16232 +#ifdef __solaris__
16233 /* The child exited because of a signal.
16234 * The best value to return is 0x80 + signal number,
16235 * because that is what all Unix shells do, and because
16236 * it allows callers to distinguish between process exit and
16237 * process death by signal.
16238 - */
16239 + * Unfortunately, the historical behavior on Solaris is to return
16240 + * the signal number, and we preserve this for compatibility. */
16241 +#define WTERMSIG_RETURN(status) WTERMSIG(status)
16242 +#else
16243 #define WTERMSIG_RETURN(status) (WTERMSIG(status) + 0x80)
16244 +#endif
16246 #define RESTARTABLE(_cmd, _result) do { \
16247 do { \
16248 @@ -488,7 +503,7 @@
16249 * The following functions are for Linux
16252 -#if defined (__linux__)
16253 +#if defined(__solaris__) || defined (__linux__)
16256 * Return pids of active processes, and optionally parent pids and
16257 @@ -617,13 +632,13 @@
16258 return count;
16261 -#endif // defined (__linux__)
16262 +#endif // defined(__solaris__) || defined (__linux__)
16265 - * The following functions are for AIX.
16266 + * The following functions are common on Solaris and AIX.
16269 -#if defined(_AIX)
16270 +#if defined(__solaris__) || defined(_AIX)
16273 * Helper function to get the 'psinfo_t' data from "/proc/%d/psinfo".
16274 @@ -687,6 +702,19 @@
16275 int ret;
16278 + * On Solaris, the full path to the executable command is the link in
16279 + * /proc/<pid>/paths/a.out. But it is only readable for processes we own.
16280 + */
16281 +#if defined(__solaris__)
16282 + snprintf(fn, sizeof fn, "/proc/%d/path/a.out", pid);
16283 + if ((ret = readlink(fn, exePath, PATH_MAX - 1)) > 0) {
16284 + // null terminate and create String to store for command
16285 + exePath[ret] = '\0';
16286 + CHECK_NULL(cmdexe = JNU_NewStringPlatform(env, exePath));
16288 +#endif
16290 + /*
16291 * Now try to open /proc/%d/psinfo
16293 if (getPsinfo(pid, &psinfo) < 0) {
16294 @@ -715,4 +743,4 @@
16295 prargs[0] == '\0' ? NULL : prargs);
16298 -#endif // defined(_AIX)
16299 +#endif // defined(__solaris__) || defined(_AIX)
16300 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.h jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.h
16301 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.h 2024-06-04 18:47:50.000000000 +0200
16302 +++ jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.h 2024-08-17 19:34:03.862875474 +0200
16303 @@ -29,7 +29,7 @@
16304 * Declaration of ProcessHandleImpl functions common on all Unix platforms.
16305 * 'unix_' functions have a single implementation in ProcessHandleImpl_unix.c
16306 * 'os_' prefixed functions have different, os-specific implementations in the
16307 - * various ProcessHandleImpl_{linux,macosx,aix}.c files.
16308 + * various ProcessHandleImpl_{linux,macosx,solaris,aix}.c files.
16309 * See ProcessHandleImpl_unix.c for more details.
16312 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libjava/ProcessImpl_md.c jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libjava/ProcessImpl_md.c
16313 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libjava/ProcessImpl_md.c 2024-06-04 18:47:50.000000000 +0200
16314 +++ jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libjava/ProcessImpl_md.c 2024-08-17 19:34:03.863445570 +0200
16315 @@ -230,7 +230,14 @@
16316 static const char*
16317 defaultPath(void)
16319 - return ":/bin:/usr/bin";
16320 +#ifdef __solaris__
16321 + /* These really are the Solaris defaults! */
16322 + return (geteuid() == 0 || getuid() == 0) ?
16323 + "/usr/xpg4/bin:/usr/bin:/opt/SUNWspro/bin:/usr/sbin" :
16324 + "/usr/xpg4/bin:/usr/bin:/opt/SUNWspro/bin:";
16325 +#else
16326 + return ":/bin:/usr/bin"; /* glibc */
16327 +#endif
16330 static const char*
16331 @@ -447,7 +454,7 @@
16332 #endif
16334 /* vfork(2) is deprecated on Darwin */
16335 -#ifndef __APPLE__
16336 +#ifndef __solaris__
16337 static pid_t
16338 vforkChild(ChildStuff *c) {
16339 volatile pid_t resultPid;
16340 @@ -602,7 +609,7 @@
16341 startChild(JNIEnv *env, jobject process, ChildStuff *c, const char *helperpath) {
16342 switch (c->mode) {
16343 /* vfork(2) is deprecated on Darwin*/
16344 - #ifndef __APPLE__
16345 + #ifndef __solaris__
16346 case MODE_VFORK:
16347 return vforkChild(c);
16348 #endif
16349 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libjava/TimeZone_md.c jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libjava/TimeZone_md.c
16350 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libjava/TimeZone_md.c 2024-06-04 18:47:50.000000000 +0200
16351 +++ jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libjava/TimeZone_md.c 2024-08-17 19:34:03.864203226 +0200
16352 @@ -35,6 +35,9 @@
16353 #include <string.h>
16354 #include <dirent.h>
16355 #include <unistd.h>
16356 +#if defined(__solaris__)
16357 +#include <libscf.h>
16358 +#endif
16360 #include "jvm.h"
16361 #include "TimeZone_md.h"
16362 @@ -50,9 +53,11 @@
16363 } while((_result == -1) && (errno == EINTR)); \
16364 } while(0)
16366 +#if !defined(__solaris__) || defined(__sparcv9) || defined(amd64)
16367 #define fileopen fopen
16368 #define filegets fgets
16369 #define fileclose fclose
16370 +#endif
16372 #if defined(_ALLBSD_SOURCE)
16373 #define stat64 stat
16374 @@ -76,7 +81,7 @@
16375 static const char *ETC_ENVIRONMENT_FILE = "/etc/environment";
16376 #endif
16378 -#if defined(__linux__) || defined(MACOSX)
16379 +#if defined(__linux__) || defined(MACOSX) || defined(__solaris__)
16382 * remove repeated path separators ('/') in the given 'path'.
16383 @@ -186,6 +191,13 @@
16385 if ((strcmp(dp->d_name, "ROC") == 0)
16386 || (strcmp(dp->d_name, "posixrules") == 0)
16387 +#if defined(__solaris__)
16388 + /*
16389 + * Skip the "src" and "tab" directories on Solaris.
16390 + */
16391 + || (strcmp(dp->d_name, "src") == 0)
16392 + || (strcmp(dp->d_name, "tab") == 0)
16393 +#endif
16394 || (strcmp(dp->d_name, "localtime") == 0)) {
16395 continue;
16397 @@ -257,6 +269,8 @@
16398 return possibleMatch;
16401 +#if defined(__linux__) || defined(MACOSX)
16404 * Performs Linux specific mapping and returns a zone ID
16405 * if found. Otherwise, NULL is returned.
16406 @@ -368,6 +382,183 @@
16407 return tz;
16410 +#elif defined(__solaris__)
16413 + * Performs Solaris dependent mapping. Returns a zone ID if
16414 + * found. Otherwise, NULL is returned. Solaris libc looks up
16415 + * "/etc/default/init" to get the default TZ value if TZ is not defined
16416 + * as an environment variable.
16417 + */
16418 +static char *
16419 +getPlatformTimeZoneID()
16421 + char *tz = NULL;
16422 + FILE *fp;
16424 + /*
16425 + * Try the TZ entry in /etc/default/init.
16426 + */
16427 + if ((fp = fileopen(SYS_INIT_FILE, "r")) != NULL) {
16428 + char line[256];
16429 + char quote = '\0';
16431 + while (filegets(line, sizeof(line), fp) != NULL) {
16432 + char *p = line;
16433 + char *s;
16434 + char c;
16436 + /* quick check for comment lines */
16437 + if (*p == '#') {
16438 + continue;
16440 + if (strncmp(p, "TZ=", 3) == 0) {
16441 + p += 3;
16442 + SKIP_SPACE(p);
16443 + c = *p;
16444 + if (c == '"' || c == '\'') {
16445 + quote = c;
16446 + p++;
16449 + /*
16450 + * PSARC/2001/383: quoted string support
16451 + */
16452 + for (s = p; (c = *s) != '\0' && c != '\n'; s++) {
16453 + /* No '\\' is supported here. */
16454 + if (c == quote) {
16455 + quote = '\0';
16456 + break;
16458 + if (c == ' ' && quote == '\0') {
16459 + break;
16462 + if (quote != '\0') {
16463 + jio_fprintf(stderr, "ZoneInfo: unterminated time zone name in /etc/TIMEZONE\n");
16465 + *s = '\0';
16466 + tz = strdup(p);
16467 + break;
16470 + (void) fileclose(fp);
16472 + return tz;
16475 +#define TIMEZONE_FMRI "svc:/system/timezone:default"
16476 +#define TIMEZONE_PG "timezone"
16477 +#define LOCALTIME_PROP "localtime"
16479 +static void
16480 +cleanupScf(scf_handle_t *h,
16481 + scf_snapshot_t *snap,
16482 + scf_instance_t *inst,
16483 + scf_propertygroup_t *pg,
16484 + scf_property_t *prop,
16485 + scf_value_t *val,
16486 + char *buf) {
16487 + if (buf != NULL) {
16488 + free(buf);
16490 + if (snap != NULL) {
16491 + scf_snapshot_destroy(snap);
16493 + if (val != NULL) {
16494 + scf_value_destroy(val);
16496 + if (prop != NULL) {
16497 + scf_property_destroy(prop);
16499 + if (pg != NULL) {
16500 + scf_pg_destroy(pg);
16502 + if (inst != NULL) {
16503 + scf_instance_destroy(inst);
16505 + if (h != NULL) {
16506 + scf_handle_destroy(h);
16511 + * Returns a zone ID of Solaris when the TZ value is "localtime".
16512 + * First, it tries scf. If scf fails, it looks for the same file as
16513 + * /usr/share/lib/zoneinfo/localtime under /usr/share/lib/zoneinfo/.
16514 + */
16515 +static char *
16516 +getSolarisDefaultZoneID() {
16517 + char *tz = NULL;
16518 + struct stat64 statbuf;
16519 + size_t size;
16520 + char *buf;
16521 + int fd;
16522 + int res;
16523 + /* scf specific variables */
16524 + scf_handle_t *h = NULL;
16525 + scf_snapshot_t *snap = NULL;
16526 + scf_instance_t *inst = NULL;
16527 + scf_propertygroup_t *pg = NULL;
16528 + scf_property_t *prop = NULL;
16529 + scf_value_t *val = NULL;
16531 + if ((h = scf_handle_create(SCF_VERSION)) != NULL
16532 + && scf_handle_bind(h) == 0
16533 + && (inst = scf_instance_create(h)) != NULL
16534 + && (snap = scf_snapshot_create(h)) != NULL
16535 + && (pg = scf_pg_create(h)) != NULL
16536 + && (prop = scf_property_create(h)) != NULL
16537 + && (val = scf_value_create(h)) != NULL
16538 + && scf_handle_decode_fmri(h, TIMEZONE_FMRI, NULL, NULL, inst,
16539 + NULL, NULL, SCF_DECODE_FMRI_REQUIRE_INSTANCE) == 0
16540 + && scf_instance_get_snapshot(inst, "running", snap) == 0
16541 + && scf_instance_get_pg_composed(inst, snap, TIMEZONE_PG, pg) == 0
16542 + && scf_pg_get_property(pg, LOCALTIME_PROP, prop) == 0
16543 + && scf_property_get_value(prop, val) == 0) {
16544 + ssize_t len;
16546 + /* Gets the length of the zone ID string */
16547 + len = scf_value_get_astring(val, NULL, 0);
16548 + if (len != -1) {
16549 + tz = malloc(++len); /* +1 for a null byte */
16550 + if (tz != NULL && scf_value_get_astring(val, tz, len) != -1) {
16551 + cleanupScf(h, snap, inst, pg, prop, val, NULL);
16552 + return tz;
16556 + cleanupScf(h, snap, inst, pg, prop, val, tz);
16558 + RESTARTABLE(stat64(DEFAULT_ZONEINFO_FILE, &statbuf), res);
16559 + if (res == -1) {
16560 + return NULL;
16562 + size = (size_t) statbuf.st_size;
16563 + buf = malloc(size);
16564 + if (buf == NULL) {
16565 + return NULL;
16567 + RESTARTABLE(open(DEFAULT_ZONEINFO_FILE, O_RDONLY), fd);
16568 + if (fd == -1) {
16569 + free((void *) buf);
16570 + return NULL;
16573 + RESTARTABLE(read(fd, buf, size), res);
16574 + if (res != (ssize_t) size) {
16575 + (void) close(fd);
16576 + free((void *) buf);
16577 + return NULL;
16579 + (void) close(fd);
16580 + tz = findZoneinfoFile(buf, size, ZONEINFO_DIR);
16581 + free((void *) buf);
16582 + return tz;
16585 +#endif /* defined(__solaris__) */
16587 #elif defined(_AIX)
16589 static char *
16590 @@ -533,6 +724,15 @@
16591 free((void *) freetz);
16593 #else
16594 +#if defined(__solaris__)
16595 + /* Solaris might use localtime, so handle it here. */
16596 + if (strcmp(tz, "localtime") == 0) {
16597 + javatz = getSolarisDefaultZoneID();
16598 + if (freetz != NULL) {
16599 + free((void *) freetz);
16601 + } else
16602 +#endif
16603 if (freetz == NULL) {
16604 /* strdup if we are still working on getenv result. */
16605 javatz = strdup(tz);
16606 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libjava/UnixFileSystem_md.c jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libjava/UnixFileSystem_md.c
16607 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libjava/UnixFileSystem_md.c 2024-06-04 18:47:50.000000000 +0200
16608 +++ jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libjava/UnixFileSystem_md.c 2024-08-17 19:34:03.864638994 +0200
16609 @@ -63,6 +63,10 @@
16610 #define stat stat64
16611 #endif
16613 +#if defined(__solaris__) && !defined(NAME_MAX)
16614 + #define NAME_MAX MAXNAMLEN
16615 +#endif
16617 #if defined(_ALLBSD_SOURCE)
16618 #ifndef MACOSX
16619 #define statvfs64 statvfs
16620 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libjsig/jsig.c jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libjsig/jsig.c
16621 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libjsig/jsig.c 2024-06-04 18:47:50.000000000 +0200
16622 +++ jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libjsig/jsig.c 2024-08-17 19:34:03.866591007 +0200
16623 @@ -35,6 +35,16 @@
16625 #include "jni.h"
16627 +#ifdef SOLARIS
16628 +/* Our redeclarations of the system functions must not have a less
16629 + * restrictive linker scoping, so we have to declare them as JNIEXPORT
16630 + * before including signal.h */
16631 +#include "sys/signal.h"
16632 +JNIEXPORT void (*signal(int sig, void (*disp)(int)))(int);
16633 +JNIEXPORT void (*sigset(int sig, void (*disp)(int)))(int);
16634 +JNIEXPORT int sigaction(int sig, const struct sigaction *act, struct sigaction *oact);
16635 +#endif
16637 #include <dlfcn.h>
16638 #include <errno.h>
16639 #include <pthread.h>
16640 @@ -51,9 +61,16 @@
16641 #define false 0
16642 #endif
16644 +#ifdef SOLARIS
16645 +#define MAX_SIGNALS (SIGRTMAX+1)
16647 +/* On solaris, MAX_SIGNALS is a macro, not a constant, so we must allocate sact dynamically. */
16648 +static struct sigaction *sact = (struct sigaction *)NULL; /* saved signal handlers */
16649 +#else
16650 #define MAX_SIGNALS NSIG
16652 static struct sigaction sact[MAX_SIGNALS]; /* saved signal handlers */
16653 +#endif
16655 static sigset_t jvmsigs; /* Signals used by jvm. */
16657 @@ -78,6 +95,20 @@
16658 static bool jvm_signal_installed = false;
16661 +/* assume called within signal_lock */
16662 +static void allocate_sact() {
16663 +#ifdef SOLARIS
16664 + if (sact == NULL) {
16665 + sact = (struct sigaction *)malloc((MAX_SIGNALS) * (size_t)sizeof(struct sigaction));
16666 + if (sact == NULL) {
16667 + printf("%s\n", "libjsig.so unable to allocate memory");
16668 + exit(0);
16670 + memset(sact, 0, (MAX_SIGNALS) * (size_t)sizeof(struct sigaction));
16672 +#endif
16675 static void signal_lock() {
16676 pthread_mutex_lock(&mutex);
16677 /* When the jvm is installing its set of signal handlers, threads
16678 @@ -137,7 +168,18 @@
16679 sact[sig].sa_handler = disp;
16680 sigemptyset(&set);
16681 sact[sig].sa_mask = set;
16682 - sact[sig].sa_flags = 0;
16683 + if (!is_sigset) {
16684 +#ifdef SOLARIS
16685 + sact[sig].sa_flags = SA_NODEFER;
16686 + if (sig != SIGILL && sig != SIGTRAP && sig != SIGPWR) {
16687 + sact[sig].sa_flags |= SA_RESETHAND;
16689 +#else
16690 + sact[sig].sa_flags = 0;
16691 +#endif
16692 + } else {
16693 + sact[sig].sa_flags = 0;
16697 static sa_handler_t set_signal(int sig, sa_handler_t disp, bool is_sigset) {
16698 @@ -146,6 +188,7 @@
16699 bool sigblocked;
16701 signal_lock();
16702 + allocate_sact();
16704 sigused = sigismember(&jvmsigs, sig);
16705 if (jvm_signal_installed && sigused) {
16706 @@ -157,6 +200,13 @@
16707 oldhandler = sact[sig].sa_handler;
16708 save_signal_handler(sig, disp, is_sigset);
16710 +#ifdef SOLARIS
16711 + if (is_sigset && sigblocked) {
16712 + /* We won't honor the SIG_HOLD request to change the signal mask */
16713 + oldhandler = SIG_HOLD;
16715 +#endif
16717 signal_unlock();
16718 return oldhandler;
16719 } else if (jvm_signal_installing) {
16720 @@ -234,6 +284,7 @@
16722 signal_lock();
16724 + allocate_sact();
16725 sigused = sigismember(&jvmsigs, sig);
16726 if (jvm_signal_installed && sigused) {
16727 /* jvm has installed its signal handler for this signal. */
16728 @@ -300,6 +351,7 @@
16731 JNIEXPORT struct sigaction *JVM_get_signal_action(int sig) {
16732 + allocate_sact();
16733 /* Does race condition make sense here? */
16734 if (sigismember(&jvmsigs, sig)) {
16735 return &sact[sig];
16736 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libnet/Inet4AddressImpl.c jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libnet/Inet4AddressImpl.c
16737 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libnet/Inet4AddressImpl.c 2024-06-04 18:47:50.000000000 +0200
16738 +++ jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libnet/Inet4AddressImpl.c 2024-08-17 19:34:03.867033517 +0200
16739 @@ -66,8 +66,27 @@
16740 if (gethostname(hostname, sizeof(hostname)) != 0) {
16741 strcpy(hostname, "localhost");
16742 } else {
16743 +#if defined(__solaris__)
16744 + // try to resolve hostname via nameservice
16745 + // if it is known but getnameinfo fails, hostname will still be the
16746 + // value from gethostname
16747 + struct addrinfo hints, *res;
16749 // make sure string is null-terminated
16750 hostname[NI_MAXHOST] = '\0';
16751 + memset(&hints, 0, sizeof(hints));
16752 + hints.ai_flags = AI_CANONNAME;
16753 + hints.ai_family = AF_INET;
16755 + if (getaddrinfo(hostname, NULL, &hints, &res) == 0) {
16756 + getnameinfo(res->ai_addr, res->ai_addrlen, hostname, sizeof(hostname),
16757 + NULL, 0, NI_NAMEREQD);
16758 + freeaddrinfo(res);
16760 +#else
16761 + // make sure string is null-terminated
16762 + hostname[NI_MAXHOST] = '\0';
16763 +#endif
16765 return (*env)->NewStringUTF(env, hostname);
16767 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libnet/Inet6AddressImpl.c jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libnet/Inet6AddressImpl.c
16768 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libnet/Inet6AddressImpl.c 2024-06-04 18:47:50.000000000 +0200
16769 +++ jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libnet/Inet6AddressImpl.c 2024-08-17 19:34:03.867486874 +0200
16770 @@ -67,8 +67,27 @@
16771 if (gethostname(hostname, sizeof(hostname)) != 0) {
16772 strcpy(hostname, "localhost");
16773 } else {
16774 +#if defined(__solaris__)
16775 + // try to resolve hostname via nameservice
16776 + // if it is known but getnameinfo fails, hostname will still be the
16777 + // value from gethostname
16778 + struct addrinfo hints, *res;
16780 // make sure string is null-terminated
16781 hostname[NI_MAXHOST] = '\0';
16782 + memset(&hints, 0, sizeof(hints));
16783 + hints.ai_flags = AI_CANONNAME;
16784 + hints.ai_family = AF_UNSPEC;
16786 + if (getaddrinfo(hostname, NULL, &hints, &res) == 0) {
16787 + getnameinfo(res->ai_addr, res->ai_addrlen, hostname, sizeof(hostname),
16788 + NULL, 0, NI_NAMEREQD);
16789 + freeaddrinfo(res);
16791 +#else
16792 + // make sure string is null-terminated
16793 + hostname[NI_MAXHOST] = '\0';
16794 +#endif
16796 return (*env)->NewStringUTF(env, hostname);
16798 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libnet/net_util_md.c jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libnet/net_util_md.c
16799 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libnet/net_util_md.c 2024-06-04 18:47:50.000000000 +0200
16800 +++ jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libnet/net_util_md.c 2024-08-17 19:34:03.869682644 +0200
16801 @@ -36,6 +36,14 @@
16802 #include <sys/utsname.h>
16803 #endif
16805 +#if defined(__solaris__)
16806 +#include <inet/nd.h>
16807 +#include <limits.h>
16808 +#include <stropts.h>
16809 +#include <sys/filio.h>
16810 +#include <sys/sockio.h>
16811 +#endif
16813 #if defined(MACOSX)
16814 #include <sys/sysctl.h>
16815 #endif
16816 @@ -50,12 +58,114 @@
16817 #define IPV6_FLOWINFO_SEND 33
16818 #endif
16820 +#if defined(__solaris__) && !defined(MAXINT)
16821 +#define MAXINT INT_MAX
16822 +#endif
16825 + * EXCLBIND socket options only on Solaris
16826 + */
16827 +#if defined(__solaris__) && !defined(TCP_EXCLBIND)
16828 +#define TCP_EXCLBIND 0x21
16829 +#endif
16830 +#if defined(__solaris__) && !defined(UDP_EXCLBIND)
16831 +#define UDP_EXCLBIND 0x0101
16832 +#endif
16834 void
16835 NET_ThrowByNameWithLastError(JNIEnv *env, const char *name,
16836 const char *defaultDetail) {
16837 JNU_ThrowByNameWithMessageAndLastError(env, name, defaultDetail);
16840 +#ifdef __solaris__
16841 +static int init_tcp_max_buf, init_udp_max_buf;
16842 +static int tcp_max_buf;
16843 +static int udp_max_buf;
16844 +static int useExclBind = 0;
16847 + * Get the specified parameter from the specified driver. The value
16848 + * of the parameter is assumed to be an 'int'. If the parameter
16849 + * cannot be obtained return -1
16850 + */
16851 +int net_getParam(char *driver, char *param)
16853 + struct strioctl stri;
16854 + char buf [64];
16855 + int s;
16856 + int value;
16858 + s = open (driver, O_RDWR);
16859 + if (s < 0) {
16860 + return -1;
16862 + strncpy (buf, param, sizeof(buf));
16863 + stri.ic_cmd = ND_GET;
16864 + stri.ic_timout = 0;
16865 + stri.ic_dp = buf;
16866 + stri.ic_len = sizeof(buf);
16867 + if (ioctl (s, I_STR, &stri) < 0) {
16868 + value = -1;
16869 + } else {
16870 + value = atoi(buf);
16872 + close (s);
16873 + return value;
16877 + * Iterative way to find the max value that SO_SNDBUF or SO_RCVBUF
16878 + * for Solaris versions that do not support the ioctl() in net_getParam().
16879 + * Ugly, but only called once (for each sotype).
16881 + * As an optimization, we make a guess using the default values for Solaris
16882 + * assuming they haven't been modified with ndd.
16883 + */
16885 +#define MAX_TCP_GUESS 1024 * 1024
16886 +#define MAX_UDP_GUESS 2 * 1024 * 1024
16888 +#define FAIL_IF_NOT_ENOBUFS if (errno != ENOBUFS) return -1
16890 +static int findMaxBuf(int fd, int opt, int sotype) {
16891 + int a = 0;
16892 + int b = MAXINT;
16893 + int initial_guess;
16894 + int limit = -1;
16896 + if (sotype == SOCK_DGRAM) {
16897 + initial_guess = MAX_UDP_GUESS;
16898 + } else {
16899 + initial_guess = MAX_TCP_GUESS;
16902 + if (setsockopt(fd, SOL_SOCKET, opt, &initial_guess, sizeof(int)) == 0) {
16903 + initial_guess++;
16904 + if (setsockopt(fd, SOL_SOCKET, opt, &initial_guess,sizeof(int)) < 0) {
16905 + FAIL_IF_NOT_ENOBUFS;
16906 + return initial_guess - 1;
16908 + a = initial_guess;
16909 + } else {
16910 + FAIL_IF_NOT_ENOBUFS;
16911 + b = initial_guess - 1;
16913 + do {
16914 + int mid = a + (b-a)/2;
16915 + if (setsockopt(fd, SOL_SOCKET, opt, &mid, sizeof(int)) == 0) {
16916 + limit = mid;
16917 + a = mid + 1;
16918 + } else {
16919 + FAIL_IF_NOT_ENOBUFS;
16920 + b = mid - 1;
16922 + } while (b >= a);
16924 + return limit;
16926 +#endif
16928 void
16929 NET_ThrowNew(JNIEnv *env, int errorNumber, char *msg) {
16930 char fullMsg[512];
16931 @@ -133,6 +243,50 @@
16933 #endif
16935 + /**
16936 + * On Solaris 8 it's possible to create INET6 sockets even
16937 + * though IPv6 is not enabled on all interfaces. Thus we
16938 + * query the number of IPv6 addresses to verify that IPv6
16939 + * has been configured on at least one interface.
16941 + * On Linux it doesn't matter - if IPv6 is built-in the
16942 + * kernel then IPv6 addresses will be bound automatically
16943 + * to all interfaces.
16944 + */
16945 +#ifdef __solaris__
16947 +#ifdef SIOCGLIFNUM
16949 + struct lifnum numifs;
16951 + numifs.lifn_family = AF_INET6;
16952 + numifs.lifn_flags = 0;
16953 + if (ioctl(fd, SIOCGLIFNUM, (char *)&numifs) < 0) {
16954 + /**
16955 + * SIOCGLIFNUM failed - assume IPv6 not configured
16956 + */
16957 + close(fd);
16958 + return JNI_FALSE;
16960 + /**
16961 + * If no IPv6 addresses then return false. If count > 0
16962 + * it's possible that all IPv6 addresses are "down" but
16963 + * that's okay as they may be brought "up" while the
16964 + * VM is running.
16965 + */
16966 + if (numifs.lifn_count == 0) {
16967 + close(fd);
16968 + return JNI_FALSE;
16971 +#else
16972 + /* SIOCGLIFNUM not defined in build environment ??? */
16973 + close(fd);
16974 + return JNI_FALSE;
16975 +#endif
16977 +#endif /* __solaris */
16980 * OK we may have the stack available in the kernel,
16981 * we should also check if the APIs are available.
16982 @@ -197,6 +351,26 @@
16986 +void parseExclusiveBindProperty(JNIEnv *env) {
16987 +#ifdef __solaris__
16988 + jstring s, flagSet;
16989 + jclass iCls;
16990 + jmethodID mid;
16992 + s = (*env)->NewStringUTF(env, "sun.net.useExclusiveBind");
16993 + CHECK_NULL(s);
16994 + iCls = (*env)->FindClass(env, "java/lang/System");
16995 + CHECK_NULL(iCls);
16996 + mid = (*env)->GetStaticMethodID(env, iCls, "getProperty",
16997 + "(Ljava/lang/String;)Ljava/lang/String;");
16998 + CHECK_NULL(mid);
16999 + flagSet = (*env)->CallStaticObjectMethod(env, iCls, mid, s);
17000 + if (flagSet != NULL) {
17001 + useExclBind = 1;
17003 +#endif
17006 JNIEXPORT jint JNICALL
17007 NET_EnableFastTcpLoopback(int fd) {
17008 return 0;
17009 @@ -438,6 +612,65 @@
17010 *iptos &= (IPTOS_TOS_MASK | IPTOS_PREC_MASK);
17013 + /*
17014 + * SOL_SOCKET/{SO_SNDBUF,SO_RCVBUF} - On Solaris we may need to clamp
17015 + * the value when it exceeds the system limit.
17016 + */
17017 +#ifdef __solaris__
17018 + if (level == SOL_SOCKET) {
17019 + if (opt == SO_SNDBUF || opt == SO_RCVBUF) {
17020 + int sotype=0;
17021 + socklen_t arglen;
17022 + int *bufsize, maxbuf;
17023 + int ret;
17025 + /* Attempt with the original size */
17026 + ret = setsockopt(fd, level, opt, arg, len);
17027 + if ((ret == 0) || (ret == -1 && errno != ENOBUFS))
17028 + return ret;
17030 + /* Exceeded system limit so clamp and retry */
17032 + arglen = sizeof(sotype);
17033 + if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *)&sotype,
17034 + &arglen) < 0) {
17035 + return -1;
17038 + /*
17039 + * We try to get tcp_maxbuf (and udp_max_buf) using
17040 + * an ioctl() that isn't available on all versions of Solaris.
17041 + * If that fails, we use the search algorithm in findMaxBuf()
17042 + */
17043 + if (!init_tcp_max_buf && sotype == SOCK_STREAM) {
17044 + tcp_max_buf = net_getParam("/dev/tcp", "tcp_max_buf");
17045 + if (tcp_max_buf == -1) {
17046 + tcp_max_buf = findMaxBuf(fd, opt, SOCK_STREAM);
17047 + if (tcp_max_buf == -1) {
17048 + return -1;
17051 + init_tcp_max_buf = 1;
17052 + } else if (!init_udp_max_buf && sotype == SOCK_DGRAM) {
17053 + udp_max_buf = net_getParam("/dev/udp", "udp_max_buf");
17054 + if (udp_max_buf == -1) {
17055 + udp_max_buf = findMaxBuf(fd, opt, SOCK_DGRAM);
17056 + if (udp_max_buf == -1) {
17057 + return -1;
17060 + init_udp_max_buf = 1;
17063 + maxbuf = (sotype == SOCK_STREAM) ? tcp_max_buf : udp_max_buf;
17064 + bufsize = (int *)arg;
17065 + if (*bufsize > maxbuf) {
17066 + *bufsize = maxbuf;
17070 +#endif
17072 #ifdef _AIX
17073 if (level == SOL_SOCKET) {
17074 if (opt == SO_SNDBUF || opt == SO_RCVBUF) {
17075 @@ -552,10 +785,20 @@
17077 * Linux allows a socket to bind to 127.0.0.255 which must be
17078 * caught.
17080 + * On Solaris with IPv6 enabled we must use an exclusive
17081 + * bind to guarantee a unique port number across the IPv4 and
17082 + * IPv6 port spaces.
17086 NET_Bind(int fd, SOCKETADDRESS *sa, int len)
17088 +#if defined(__solaris__)
17089 + int level = -1;
17090 + int exclbind = -1;
17091 + int arg, alen;
17092 +#endif
17093 int rv;
17095 #ifdef __linux__
17096 @@ -572,8 +815,61 @@
17098 #endif
17100 +#if defined(__solaris__)
17101 + /*
17102 + * Solaris has separate IPv4 and IPv6 port spaces so we
17103 + * use an exclusive bind when SO_REUSEADDR is not used to
17104 + * give the illusion of a unified port space.
17105 + * This also avoids problems with IPv6 sockets connecting
17106 + * to IPv4 mapped addresses whereby the socket conversion
17107 + * results in a late bind that fails because the
17108 + * corresponding IPv4 port is in use.
17109 + */
17110 + alen = sizeof(arg);
17112 + if (useExclBind ||
17113 + getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&arg, &alen) == 0)
17115 + if (useExclBind || arg == 0) {
17116 + /*
17117 + * SO_REUSEADDR is disabled or sun.net.useExclusiveBind
17118 + * property is true so enable TCP_EXCLBIND or
17119 + * UDP_EXCLBIND
17120 + */
17121 + alen = sizeof(arg);
17122 + if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&arg, &alen) == 0)
17124 + if (arg == SOCK_STREAM) {
17125 + level = IPPROTO_TCP;
17126 + exclbind = TCP_EXCLBIND;
17127 + } else {
17128 + level = IPPROTO_UDP;
17129 + exclbind = UDP_EXCLBIND;
17133 + arg = 1;
17134 + setsockopt(fd, level, exclbind, (char *)&arg, sizeof(arg));
17138 +#endif
17140 rv = bind(fd, &sa->sa, len);
17142 +#if defined(__solaris__)
17143 + if (rv < 0) {
17144 + int en = errno;
17145 + /* Restore *_EXCLBIND if the bind fails */
17146 + if (exclbind != -1) {
17147 + int arg = 0;
17148 + setsockopt(fd, level, exclbind, (char *)&arg,
17149 + sizeof(arg));
17151 + errno = en;
17153 +#endif
17155 return rv;
17158 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libnet/net_util_md.h jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libnet/net_util_md.h
17159 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libnet/net_util_md.h 2024-06-04 18:47:50.000000000 +0200
17160 +++ jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libnet/net_util_md.h 2024-08-17 19:34:03.870065573 +0200
17161 @@ -47,6 +47,8 @@
17162 #ifndef SO_REUSEPORT
17163 #ifdef __linux__
17164 #define SO_REUSEPORT 15
17165 +#elif defined(__solaris__)
17166 +#define SO_REUSEPORT 0x100e
17167 #elif defined(AIX) || defined(MACOSX)
17168 #define SO_REUSEPORT 0x0200
17169 #else
17170 @@ -80,4 +82,8 @@
17171 void NET_ThrowByNameWithLastError(JNIEnv *env, const char *name,
17172 const char *defaultDetail);
17174 +#ifdef __solaris__
17175 +int net_getParam(char *driver, char *param);
17176 +#endif
17178 #endif /* NET_UTILS_MD_H */
17179 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libnet/NetworkInterface.c jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libnet/NetworkInterface.c
17180 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libnet/NetworkInterface.c 2024-06-04 18:47:50.000000000 +0200
17181 +++ jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libnet/NetworkInterface.c 2024-08-17 19:34:03.868442634 +0200
17182 @@ -37,6 +37,12 @@
17183 #include <strings.h>
17184 #endif
17186 +#if defined(__solaris__)
17187 +#include <stropts.h>
17188 +#include <sys/dlpi.h>
17189 +#include <sys/sockio.h>
17190 +#endif
17192 #if defined(_ALLBSD_SOURCE)
17193 #include <net/ethernet.h>
17194 #include <net/if_dl.h>
17195 @@ -49,6 +55,11 @@
17197 #if defined(__linux__)
17198 #define _PATH_PROCNET_IFINET6 "/proc/net/if_inet6"
17199 +#elif defined(__solaris__)
17200 + #ifndef SIOCGLIFHWADDR
17201 + #define SIOCGLIFHWADDR _IOWR('i', 192, struct lifreq)
17202 + #endif
17203 + #define DEV_PREFIX "/dev/"
17204 #endif
17206 #ifdef LIFNAMSIZ
17207 @@ -135,6 +146,11 @@
17208 const struct in_addr *addr, unsigned char *buf);
17209 static int getMTU(JNIEnv *env, int sock, const char *ifname);
17211 +#if defined(__solaris__)
17212 +static int getMacFromDevice(JNIEnv *env, const char *ifname,
17213 + unsigned char *retbuf);
17214 +#endif
17216 /******************* Java entry points *****************************/
17219 @@ -1658,6 +1674,372 @@
17221 #endif /* _AIX */
17223 +/** Solaris **/
17224 +#if defined(__solaris__)
17227 + * Opens a socket for further ioctl calls. Tries AF_INET socket first and
17228 + * if it fails return AF_INET6 socket.
17229 + */
17230 +static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
17231 + int sock, alreadyV6 = 0;
17232 + struct lifreq if2;
17234 + if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
17235 + if (errno == EPROTONOSUPPORT || errno == EAFNOSUPPORT) {
17236 + if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
17237 + JNU_ThrowByNameWithMessageAndLastError
17238 + (env, JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
17239 + return -1;
17241 + alreadyV6 = 1;
17242 + } else { // errno is not NOSUPPORT
17243 + JNU_ThrowByNameWithMessageAndLastError
17244 + (env, JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed");
17245 + return -1;
17249 + // Solaris requires that we have an IPv6 socket to query an interface
17250 + // without an IPv4 address - check it here. POSIX 1 require the kernel to
17251 + // return ENOTTY if the call is inappropriate for a device e.g. the NETMASK
17252 + // for a device having IPv6 only address but not all devices follow the
17253 + // standard so fall back on any error. It's not an ecologically friendly
17254 + // gesture but more reliable.
17255 + if (!alreadyV6) {
17256 + memset((char *)&if2, 0, sizeof(if2));
17257 + strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
17258 + if (ioctl(sock, SIOCGLIFNETMASK, (char *)&if2) < 0) {
17259 + close(sock);
17260 + if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
17261 + JNU_ThrowByNameWithMessageAndLastError
17262 + (env, JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
17263 + return -1;
17268 + return sock;
17272 + * Enumerates and returns all IPv4 interfaces on Solaris.
17273 + */
17274 +static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
17275 + struct lifconf ifc;
17276 + struct lifreq *ifreqP;
17277 + struct lifnum numifs;
17278 + char *buf = NULL;
17279 + unsigned i;
17281 + // call SIOCGLIFNUM to get the interface count
17282 + numifs.lifn_family = AF_INET;
17283 + numifs.lifn_flags = 0;
17284 + if (ioctl(sock, SIOCGLIFNUM, (char *)&numifs) < 0) {
17285 + JNU_ThrowByNameWithMessageAndLastError
17286 + (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFNUM) failed");
17287 + return ifs;
17290 + // call SIOCGLIFCONF to enumerate the interfaces
17291 + ifc.lifc_len = numifs.lifn_count * sizeof(struct lifreq);
17292 + CHECKED_MALLOC3(buf, char *, ifc.lifc_len);
17293 + ifc.lifc_buf = buf;
17294 + ifc.lifc_family = AF_INET;
17295 + ifc.lifc_flags = 0;
17296 + if (ioctl(sock, SIOCGLIFCONF, (char *)&ifc) < 0) {
17297 + JNU_ThrowByNameWithMessageAndLastError
17298 + (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFCONF) failed");
17299 + free(buf);
17300 + return ifs;
17303 + // iterate through each interface
17304 + ifreqP = ifc.lifc_req;
17305 + for (i = 0; i < numifs.lifn_count; i++, ifreqP++) {
17306 + struct sockaddr addr, *broadaddrP = NULL;
17308 + // ignore non IPv4 addresses
17309 + if (ifreqP->lifr_addr.ss_family != AF_INET) {
17310 + continue;
17313 + // save socket address
17314 + memcpy(&addr, &(ifreqP->lifr_addr), sizeof(struct sockaddr));
17316 + // determine broadcast address, if applicable
17317 + if ((ioctl(sock, SIOCGLIFFLAGS, ifreqP) == 0) &&
17318 + ifreqP->lifr_flags & IFF_BROADCAST) {
17320 + // restore socket address to ifreqP
17321 + memcpy(&(ifreqP->lifr_addr), &addr, sizeof(struct sockaddr));
17323 + // query broadcast address and set pointer to it
17324 + if (ioctl(sock, SIOCGLIFBRDADDR, ifreqP) == 0) {
17325 + broadaddrP = (struct sockaddr *)&(ifreqP->lifr_broadaddr);
17329 + // add to the list
17330 + ifs = addif(env, sock, ifreqP->lifr_name, ifs,
17331 + &addr, broadaddrP, AF_INET, (short)ifreqP->lifr_addrlen);
17333 + // if an exception occurred we return immediately
17334 + if ((*env)->ExceptionOccurred(env)) {
17335 + free(buf);
17336 + return ifs;
17340 + // free buffer
17341 + free(buf);
17342 + return ifs;
17346 + * Enumerates and returns all IPv6 interfaces on Solaris.
17347 + */
17348 +static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
17349 + struct lifconf ifc;
17350 + struct lifreq *ifreqP;
17351 + struct lifnum numifs;
17352 + char *buf = NULL;
17353 + unsigned i;
17355 + // call SIOCGLIFNUM to get the interface count
17356 + numifs.lifn_family = AF_INET6;
17357 + numifs.lifn_flags = 0;
17358 + if (ioctl(sock, SIOCGLIFNUM, (char *)&numifs) < 0) {
17359 + JNU_ThrowByNameWithMessageAndLastError
17360 + (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFNUM) failed");
17361 + return ifs;
17364 + // call SIOCGLIFCONF to enumerate the interfaces
17365 + ifc.lifc_len = numifs.lifn_count * sizeof(struct lifreq);
17366 + CHECKED_MALLOC3(buf, char *, ifc.lifc_len);
17367 + ifc.lifc_buf = buf;
17368 + ifc.lifc_family = AF_INET6;
17369 + ifc.lifc_flags = 0;
17370 + if (ioctl(sock, SIOCGLIFCONF, (char *)&ifc) < 0) {
17371 + JNU_ThrowByNameWithMessageAndLastError
17372 + (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFCONF) failed");
17373 + free(buf);
17374 + return ifs;
17377 + // iterate through each interface
17378 + ifreqP = ifc.lifc_req;
17379 + for (i = 0; i < numifs.lifn_count; i++, ifreqP++) {
17381 + // ignore non IPv6 addresses
17382 + if (ifreqP->lifr_addr.ss_family != AF_INET6) {
17383 + continue;
17386 + // set scope ID to interface index
17387 + ((struct sockaddr_in6 *)&(ifreqP->lifr_addr))->sin6_scope_id =
17388 + getIndex(sock, ifreqP->lifr_name);
17390 + // add to the list
17391 + ifs = addif(env, sock, ifreqP->lifr_name, ifs,
17392 + (struct sockaddr *)&(ifreqP->lifr_addr),
17393 + NULL, AF_INET6, (short)ifreqP->lifr_addrlen);
17395 + // if an exception occurred we return immediately
17396 + if ((*env)->ExceptionOccurred(env)) {
17397 + free(buf);
17398 + return ifs;
17402 + // free buffer
17403 + free(buf);
17404 + return ifs;
17408 + * Try to get the interface index.
17409 + * (Not supported on Solaris 2.6 or 7)
17410 + */
17411 +static int getIndex(int sock, const char *name) {
17412 + struct lifreq if2;
17413 + memset((char *)&if2, 0, sizeof(if2));
17414 + strncpy(if2.lifr_name, name, sizeof(if2.lifr_name) - 1);
17416 + if (ioctl(sock, SIOCGLIFINDEX, (char *)&if2) < 0) {
17417 + return -1;
17420 + return if2.lifr_index;
17424 + * Solaris specific DLPI code to get hardware address from a device.
17425 + * Unfortunately, at least up to Solaris X, you have to have special
17426 + * privileges (i.e. be root).
17427 + */
17428 +static int getMacFromDevice
17429 + (JNIEnv *env, const char *ifname, unsigned char *retbuf)
17431 + char style1dev[MAXPATHLEN];
17432 + int fd;
17433 + dl_phys_addr_req_t dlpareq;
17434 + dl_phys_addr_ack_t *dlpaack;
17435 + dl_error_ack_t *dlerack;
17436 + struct strbuf msg;
17437 + char buf[128];
17438 + int flags = 0;
17440 + // Device is in /dev. e.g.: /dev/bge0
17441 + strcpy(style1dev, DEV_PREFIX);
17442 + strcat(style1dev, ifname);
17443 + if ((fd = open(style1dev, O_RDWR)) < 0) {
17444 + // Can't open it. We probably are missing the privilege.
17445 + // We'll have to try something else
17446 + return 0;
17449 + dlpareq.dl_primitive = DL_PHYS_ADDR_REQ;
17450 + dlpareq.dl_addr_type = DL_CURR_PHYS_ADDR;
17452 + msg.buf = (char *)&dlpareq;
17453 + msg.len = DL_PHYS_ADDR_REQ_SIZE;
17455 + if (putmsg(fd, &msg, NULL, 0) < 0) {
17456 + JNU_ThrowByNameWithMessageAndLastError
17457 + (env, JNU_JAVANETPKG "SocketException", "putmsg() failed");
17458 + return -1;
17461 + dlpaack = (dl_phys_addr_ack_t *)buf;
17463 + msg.buf = (char *)buf;
17464 + msg.len = 0;
17465 + msg.maxlen = sizeof (buf);
17466 + if (getmsg(fd, &msg, NULL, &flags) < 0) {
17467 + JNU_ThrowByNameWithMessageAndLastError
17468 + (env, JNU_JAVANETPKG "SocketException", "getmsg() failed");
17469 + return -1;
17472 + if (dlpaack->dl_primitive == DL_ERROR_ACK) {
17473 + dlerack = (dl_error_ack_t *)buf;
17474 + if (dlerack->dl_error_primitive != DL_PHYS_ADDR_REQ) {
17475 + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
17476 + "Couldn't obtain physical address\n");
17477 + return -1;
17479 + if (dlerack->dl_errno == DL_UNSUPPORTED) {
17480 + // fallback to lookup in the ARP table
17481 + return 0;
17485 + if (msg.len < DL_PHYS_ADDR_ACK_SIZE || dlpaack->dl_primitive != DL_PHYS_ADDR_ACK) {
17486 + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
17487 + "Couldn't obtain phys addr\n");
17488 + return -1;
17491 + memcpy(retbuf, &buf[dlpaack->dl_addr_offset], dlpaack->dl_addr_length);
17492 + return dlpaack->dl_addr_length;
17496 + * Gets the Hardware address (usually MAC address) for the named interface.
17497 + * On return puts the data in buf, and returns the length, in byte, of the
17498 + * MAC address. Returns -1 if there is no hardware address on that interface.
17499 + */
17500 +static int getMacAddress
17501 + (JNIEnv *env, const char *ifname, const struct in_addr *addr,
17502 + unsigned char *buf)
17504 + struct lifreq if2;
17505 + int len, i, sock;
17507 + if ((sock = openSocketWithFallback(env, ifname)) < 0) {
17508 + return -1;
17511 + // First, try the new (S11) SIOCGLIFHWADDR ioctl(). If that fails
17512 + // try the old way.
17513 + memset((char *)&if2, 0, sizeof(if2));
17514 + strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
17516 + if (ioctl(sock, SIOCGLIFHWADDR, &if2) != -1) {
17517 + struct sockaddr_dl *sp;
17518 + sp = (struct sockaddr_dl *)&if2.lifr_addr;
17519 + memcpy(buf, &sp->sdl_data[0], sp->sdl_alen);
17520 + close(sock);
17521 + return sp->sdl_alen;
17524 + // On Solaris we have to use DLPI, but it will only work if we have
17525 + // privileged access (i.e. root). If that fails, we try a lookup
17526 + // in the ARP table, which requires an IPv4 address.
17527 + if (((len = getMacFromDevice(env, ifname, buf)) == 0) && (addr != NULL)) {
17528 + struct arpreq arpreq;
17529 + struct sockaddr_in *sin;
17530 + struct sockaddr_in ipAddr;
17532 + len = 6; //???
17534 + sin = (struct sockaddr_in *)&arpreq.arp_pa;
17535 + memset((char *)&arpreq, 0, sizeof(struct arpreq));
17536 + ipAddr.sin_port = 0;
17537 + ipAddr.sin_family = AF_INET;
17538 + memcpy(&ipAddr.sin_addr, addr, sizeof(struct in_addr));
17539 + memcpy(&arpreq.arp_pa, &ipAddr, sizeof(struct sockaddr_in));
17540 + arpreq.arp_flags= ATF_PUBL;
17542 + if (ioctl(sock, SIOCGARP, &arpreq) < 0) {
17543 + close(sock);
17544 + return -1;
17547 + memcpy(buf, &arpreq.arp_ha.sa_data[0], len);
17549 + close(sock);
17551 + // all bytes to 0 means no hardware address
17552 + for (i = 0; i < len; i++) {
17553 + if (buf[i] != 0)
17554 + return len;
17557 + return -1;
17560 +static int getMTU(JNIEnv *env, int sock, const char *ifname) {
17561 + struct lifreq if2;
17562 + memset((char *)&if2, 0, sizeof(if2));
17563 + strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
17565 + if (ioctl(sock, SIOCGLIFMTU, (char *)&if2) < 0) {
17566 + JNU_ThrowByNameWithMessageAndLastError
17567 + (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFMTU) failed");
17568 + return -1;
17571 + return if2.lifr_mtu;
17574 +static int getFlags(int sock, const char *ifname, int *flags) {
17575 + struct lifreq if2;
17576 + memset((char *)&if2, 0, sizeof(if2));
17577 + strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
17579 + if (ioctl(sock, SIOCGLIFFLAGS, (char *)&if2) < 0) {
17580 + return -1;
17583 + *flags = if2.lifr_flags;
17584 + return 0;
17587 +#endif /* __solaris__ */
17589 /** BSD **/
17590 #if defined(_ALLBSD_SOURCE)
17592 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libnet/portconfig.c jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libnet/portconfig.c
17593 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libnet/portconfig.c 2024-06-04 18:47:50.000000000 +0200
17594 +++ jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libnet/portconfig.c 2024-08-17 19:34:03.870424081 +0200
17595 @@ -60,6 +60,13 @@
17597 return -1;
17600 +#elif defined(__solaris__)
17602 + range->higher = net_getParam("/dev/tcp", "tcp_largest_anon_port");
17603 + range->lower = net_getParam("/dev/tcp", "tcp_smallest_anon_port");
17604 + return 0;
17606 #elif defined(_ALLBSD_SOURCE)
17608 int ret;
17609 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libnet/SdpSupport.c jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libnet/SdpSupport.c
17610 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libnet/SdpSupport.c 2024-06-04 18:47:50.000000000 +0200
17611 +++ jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libnet/SdpSupport.c 2024-08-17 19:34:03.868835041 +0200
17612 @@ -27,7 +27,11 @@
17613 #include <sys/socket.h>
17614 #include <errno.h>
17616 -#if defined(__linux__)
17617 +#if defined(__solaris__)
17618 + #if !defined(PROTO_SDP)
17619 + #define PROTO_SDP 257
17620 + #endif
17621 +#elif defined(__linux__)
17622 #if !defined(AF_INET_SDP)
17623 #define AF_INET_SDP 27
17624 #endif
17625 @@ -51,7 +55,10 @@
17627 int s;
17629 -#if defined(__linux__)
17630 +#if defined(__solaris__)
17631 + int domain = ipv6_available() ? AF_INET6 : AF_INET;
17632 + s = socket(domain, SOCK_STREAM, PROTO_SDP);
17633 +#elif defined(__linux__)
17635 * IPv6 not supported by SDP on Linux
17637 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libnio/ch/DatagramChannelImpl.c jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libnio/ch/DatagramChannelImpl.c
17638 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libnio/ch/DatagramChannelImpl.c 2024-06-04 18:47:50.000000000 +0200
17639 +++ jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libnio/ch/DatagramChannelImpl.c 2024-08-17 19:34:03.870892579 +0200
17640 @@ -50,6 +50,9 @@
17641 jint fd = fdval(env, fdo);
17642 int rv;
17644 +#if defined(__solaris__)
17645 + rv = connect(fd, 0, 0);
17646 +#else
17647 #if defined(__APPLE__)
17648 // On macOS systems we use disconnectx
17649 rv = disconnectx(fd, SAE_ASSOCID_ANY, SAE_CONNID_ANY);
17650 @@ -83,6 +86,8 @@
17651 rv = errno = 0;
17652 #endif // defined(_ALLBSD_SOURCE) || defined(_AIX)
17654 +#endif // defined(__solaris__)
17656 if (rv < 0)
17657 handleSocketError(env, errno);
17659 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libnio/ch/NativeThread.c jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libnio/ch/NativeThread.c
17660 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libnio/ch/NativeThread.c 2024-06-04 18:47:50.000000000 +0200
17661 +++ jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libnio/ch/NativeThread.c 2024-08-17 19:34:03.871279608 +0200
17662 @@ -40,6 +40,9 @@
17663 #elif defined(_AIX)
17664 /* Also defined in net/aix_close.c */
17665 #define INTERRUPT_SIGNAL (SIGRTMAX - 1)
17666 +#elif defined(__solaris__)
17667 + #include <thread.h>
17668 + #define INTERRUPT_SIGNAL (SIGRTMAX - 2)
17669 #elif defined(_ALLBSD_SOURCE)
17670 /* Also defined in net/bsd_close.c */
17671 #define INTERRUPT_SIGNAL SIGIO
17672 @@ -73,14 +76,22 @@
17673 JNIEXPORT jlong JNICALL
17674 Java_sun_nio_ch_NativeThread_current0(JNIEnv *env, jclass cl)
17676 +#ifdef __solaris__
17677 + return (jlong)thr_self();
17678 +#else
17679 return (jlong)pthread_self();
17680 +#endif
17683 JNIEXPORT void JNICALL
17684 Java_sun_nio_ch_NativeThread_signal0(JNIEnv *env, jclass cl, jlong thread)
17686 int ret;
17687 +#ifdef __solaris__
17688 + ret = thr_kill((thread_t)thread, INTERRUPT_SIGNAL);
17689 +#else
17690 ret = pthread_kill((pthread_t)thread, INTERRUPT_SIGNAL);
17691 +#endif
17692 #ifdef MACOSX
17693 if (ret != 0 && ret != ESRCH)
17694 #else
17695 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libnio/ch/Net.c jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libnio/ch/Net.c
17696 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libnio/ch/Net.c 2024-06-04 18:47:50.000000000 +0200
17697 +++ jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libnio/ch/Net.c 2024-08-17 19:34:03.871828486 +0200
17698 @@ -25,6 +25,7 @@
17700 #include <poll.h>
17701 #include <sys/ioctl.h>
17702 +#include <sys/filio.h>
17703 #include <sys/types.h>
17704 #include <sys/socket.h>
17705 #include <string.h>
17706 @@ -220,7 +221,7 @@
17707 JNIEXPORT jboolean JNICALL
17708 Java_sun_nio_ch_Net_canIPv6SocketJoinIPv4Group0(JNIEnv* env, jclass cl)
17710 -#if defined(__linux__) || defined(__APPLE__)
17711 +#if defined(__linux__) || defined(__APPLE__) || defined(__solaris__)
17712 /* IPv6 sockets can join IPv4 multicast groups */
17713 return JNI_TRUE;
17714 #else
17715 @@ -232,7 +233,7 @@
17716 JNIEXPORT jboolean JNICALL
17717 Java_sun_nio_ch_Net_canJoin6WithIPv4Group0(JNIEnv* env, jclass cl)
17719 -#if defined(__APPLE__)
17720 +#if defined(__APPLE__) || defined(__solaris__)
17721 /* IPV6_ADD_MEMBERSHIP can be used to join IPv4 multicast groups */
17722 return JNI_TRUE;
17723 #else
17724 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libnio/ch/nio_util.h jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libnio/ch/nio_util.h
17725 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libnio/ch/nio_util.h 2024-06-04 18:47:50.000000000 +0200
17726 +++ jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libnio/ch/nio_util.h 2024-08-17 19:34:03.872182299 +0200
17727 @@ -41,6 +41,8 @@
17728 #ifndef SO_REUSEPORT
17729 #ifdef __linux__
17730 #define SO_REUSEPORT 15
17731 +#elif defined(__solaris__)
17732 +#define SO_REUSEPORT 0x100e
17733 #elif defined(AIX) || defined(MACOSX)
17734 #define SO_REUSEPORT 0x0200
17735 #else
17736 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c
17737 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c 2024-06-04 18:47:50.000000000 +0200
17738 +++ jdk22u-jdk-22.0.2-ga/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c 2024-08-17 19:34:03.872850000 +0200
17739 @@ -45,10 +45,17 @@
17740 #include <sys/xattr.h>
17741 #endif
17743 -/* For POSIX-compliant getpwuid_r */
17744 +/* For POSIX-compliant getpwuid_r, getgrgid_r on Solaris */
17745 +#if defined(__solaris__)
17746 +#define _POSIX_PTHREAD_SEMANTICS
17747 +#endif
17748 #include <pwd.h>
17749 #include <grp.h>
17751 +#ifdef __solaris__
17752 +#include <strings.h>
17753 +#endif
17755 #ifdef __linux__
17756 #include <sys/syscall.h>
17757 #include <sys/sysmacros.h> // makedev macros
17758 @@ -374,7 +381,8 @@
17760 /* system calls that might not be available at run time */
17762 -#if defined(_ALLBSD_SOURCE)
17763 +#if (defined(__solaris__) && defined(_LP64)) || defined(_ALLBSD_SOURCE)
17764 + /* Solaris 64-bit does not have openat64/fstatat64 */
17765 my_openat64_func = (openat64_func*)dlsym(RTLD_DEFAULT, "openat");
17766 my_fstatat64_func = (fstatat64_func*)dlsym(RTLD_DEFAULT, "fstatat");
17767 #else
17768 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.base/windows/native/libnet/net_util_md.c jdk22u-jdk-22.0.2-ga/src/java.base/windows/native/libnet/net_util_md.c
17769 --- jdk22u-jdk-22.0.2-ga.orig/src/java.base/windows/native/libnet/net_util_md.c 2024-06-04 18:47:50.000000000 +0200
17770 +++ jdk22u-jdk-22.0.2-ga/src/java.base/windows/native/libnet/net_util_md.c 2024-08-17 19:34:03.873347863 +0200
17771 @@ -125,6 +125,8 @@
17773 return TRUE;
17776 +void parseExclusiveBindProperty(JNIEnv *env) {}
17779 * Since winsock doesn't have the equivalent of strerror(errno)
17780 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/share/classes/sun/awt/FontConfiguration.java jdk22u-jdk-22.0.2-ga/src/java.desktop/share/classes/sun/awt/FontConfiguration.java
17781 --- jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/share/classes/sun/awt/FontConfiguration.java 2024-06-04 18:47:50.000000000 +0200
17782 +++ jdk22u-jdk-22.0.2-ga/src/java.desktop/share/classes/sun/awt/FontConfiguration.java 2024-08-17 19:34:03.874451141 +0200
17783 @@ -1422,6 +1422,22 @@
17787 + if (OSInfo.getOSType() == OSInfo.OSType.SOLARIS) {
17788 + for (int ii = 0; ii < table_awtfontpaths.length; ii++) {
17789 + if (table_awtfontpaths[ii] == 0) {
17790 + String script = getString(table_scriptIDs[ii]);
17791 + if (script.contains("dingbats") ||
17792 + script.contains("symbol")) {
17793 + continue;
17795 + System.err.println("\nError: "
17796 + + "<awtfontpath."
17797 + + script
17798 + + "> entry is missing!!!");
17799 + errors++;
17803 if (errors != 0) {
17804 System.err.println("!!THERE ARE " + errors + " ERROR(S) IN "
17805 + "THE FONTCONFIG FILE, PLEASE CHECK ITS CONTENT!!\n");
17806 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/share/classes/sun/awt/OSInfo.java jdk22u-jdk-22.0.2-ga/src/java.desktop/share/classes/sun/awt/OSInfo.java
17807 --- jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/share/classes/sun/awt/OSInfo.java 2024-06-04 18:47:50.000000000 +0200
17808 +++ jdk22u-jdk-22.0.2-ga/src/java.desktop/share/classes/sun/awt/OSInfo.java 2024-08-17 19:34:03.874860639 +0200
17809 @@ -39,6 +39,7 @@
17810 public static enum OSType {
17811 WINDOWS,
17812 LINUX,
17813 + SOLARIS,
17814 MACOSX,
17815 AIX,
17816 UNKNOWN
17817 @@ -95,6 +96,7 @@
17818 // Map OperatingSystem enum values to OSType enum values.
17819 case WINDOWS -> WINDOWS;
17820 case LINUX -> LINUX;
17821 + case SOLARIS -> SOLARIS;
17822 case MACOS -> MACOSX;
17823 case AIX -> AIX;
17824 default -> UNKNOWN;
17825 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/share/classes/sun/font/FontUtilities.java jdk22u-jdk-22.0.2-ga/src/java.desktop/share/classes/sun/font/FontUtilities.java
17826 --- jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/share/classes/sun/font/FontUtilities.java 2024-06-04 18:47:50.000000000 +0200
17827 +++ jdk22u-jdk-22.0.2-ga/src/java.desktop/share/classes/sun/font/FontUtilities.java 2024-08-17 19:34:03.875438669 +0200
17828 @@ -41,6 +41,8 @@
17830 public final class FontUtilities {
17832 + public static boolean isSolaris;
17834 public static boolean isLinux;
17836 public static boolean isMacOSX;
17837 @@ -66,6 +68,8 @@
17838 @Override
17839 public Object run() {
17841 + isSolaris = OSInfo.getOSType() == OSInfo.OSType.SOLARIS;
17843 isLinux = OSInfo.getOSType() == OSInfo.OSType.LINUX;
17845 isMacOSX = OSInfo.getOSType() == OSInfo.OSType.MACOSX;
17846 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/share/native/libjsound/SoundDefs.h jdk22u-jdk-22.0.2-ga/src/java.desktop/share/native/libjsound/SoundDefs.h
17847 --- jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/share/native/libjsound/SoundDefs.h 2024-06-04 18:47:50.000000000 +0200
17848 +++ jdk22u-jdk-22.0.2-ga/src/java.desktop/share/native/libjsound/SoundDefs.h 2024-08-17 19:34:03.875947752 +0200
17849 @@ -29,9 +29,10 @@
17851 // types for X_PLATFORM
17852 #define X_WINDOWS 1
17853 -#define X_LINUX 2
17854 -#define X_BSD 3
17855 -#define X_MACOSX 4
17856 +#define X_SOLARIS 2
17857 +#define X_LINUX 3
17858 +#define X_BSD 4
17859 +#define X_MACOSX 5
17861 // **********************************
17862 // Make sure you set X_PLATFORM defines correctly.
17863 @@ -44,7 +45,7 @@
17866 // following is needed for _LP64
17867 -#if ((X_PLATFORM == X_LINUX) || (X_PLATFORM == X_MACOSX))
17868 +#if ((X_PLATFORM == X_SOLARIS) || (X_PLATFORM == X_LINUX) || (X_PLATFORM == X_MACOSX))
17869 #include <sys/types.h>
17870 #endif
17872 @@ -114,6 +115,11 @@
17873 #endif
17876 +#if X_PLATFORM == X_SOLARIS
17877 +#define INLINE
17878 +#endif
17881 #if X_PLATFORM == X_LINUX
17882 #define INLINE inline
17883 #endif
17884 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/solaris/classes/sun/font/X11CNS11643.java jdk22u-jdk-22.0.2-ga/src/java.desktop/solaris/classes/sun/font/X11CNS11643.java
17885 --- jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/solaris/classes/sun/font/X11CNS11643.java 1970-01-01 01:00:00.000000000 +0100
17886 +++ jdk22u-jdk-22.0.2-ga/src/java.desktop/solaris/classes/sun/font/X11CNS11643.java 2024-08-17 19:34:03.917369552 +0200
17887 @@ -0,0 +1,178 @@
17889 + * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
17890 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
17892 + * This code is free software; you can redistribute it and/or modify it
17893 + * under the terms of the GNU General Public License version 2 only, as
17894 + * published by the Free Software Foundation. Oracle designates this
17895 + * particular file as subject to the "Classpath" exception as provided
17896 + * by Oracle in the LICENSE file that accompanied this code.
17898 + * This code is distributed in the hope that it will be useful, but WITHOUT
17899 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17900 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17901 + * version 2 for more details (a copy is included in the LICENSE file that
17902 + * accompanied this code).
17904 + * You should have received a copy of the GNU General Public License version
17905 + * 2 along with this work; if not, write to the Free Software Foundation,
17906 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17908 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
17909 + * or visit www.oracle.com if you need additional information or have any
17910 + * questions.
17911 + */
17913 +package sun.font;
17915 +import java.nio.CharBuffer;
17916 +import java.nio.ByteBuffer;
17917 +import java.nio.charset.*;
17918 +import sun.nio.cs.*;
17920 +public abstract class X11CNS11643 extends Charset {
17921 + private final int plane;
17922 + public X11CNS11643 (int plane, String name) {
17923 + super(name, null);
17924 + switch (plane) {
17925 + case 1:
17926 + this.plane = 0; // CS1
17927 + break;
17928 + case 2:
17929 + case 3:
17930 + this.plane = plane;
17931 + break;
17932 + default:
17933 + throw new IllegalArgumentException
17934 + ("Only planes 1, 2, and 3 supported");
17938 + public CharsetEncoder newEncoder() {
17939 + return new Encoder(this, plane);
17942 + public CharsetDecoder newDecoder() {
17943 + return new Decoder(this, plane);
17946 + public boolean contains(Charset cs) {
17947 + return cs instanceof X11CNS11643;
17950 + private class Encoder extends EUC_TW.Encoder {
17951 + private int plane;
17952 + public Encoder(Charset cs, int plane) {
17953 + super(cs);
17954 + this.plane = plane;
17957 + private byte[] bb = new byte[4];
17958 + public boolean canEncode(char c) {
17959 + if (c <= 0x7F) {
17960 + return false;
17962 + int nb = toEUC(c, bb);
17963 + if (nb == -1)
17964 + return false;
17965 + int p = 0;
17966 + if (nb == 4)
17967 + p = (bb[1] & 0xff) - 0xa0;
17968 + return (p == plane);
17971 + public boolean isLegalReplacement(byte[] repl) {
17972 + return true;
17975 + protected CoderResult encodeLoop(CharBuffer src, ByteBuffer dst) {
17976 + char[] sa = src.array();
17977 + int sp = src.arrayOffset() + src.position();
17978 + int sl = src.arrayOffset() + src.limit();
17979 + byte[] da = dst.array();
17980 + int dp = dst.arrayOffset() + dst.position();
17981 + int dl = dst.arrayOffset() + dst.limit();
17983 + try {
17984 + while (sp < sl) {
17985 + char c = sa[sp];
17986 + if ( c > '\u007f'&& c < '\uFFFE') {
17987 + int nb = toEUC(c, bb);
17988 + if (nb != -1) {
17989 + int p = 0;
17990 + if (nb == 4)
17991 + p = (bb[1] & 0xff) - 0xa0;
17992 + if (p == plane) {
17993 + if (dl - dp < 2)
17994 + return CoderResult.OVERFLOW;
17995 + if (nb == 2) {
17996 + da[dp++] = (byte)(bb[0] & 0x7f);
17997 + da[dp++] = (byte)(bb[1] & 0x7f);
17998 + } else {
17999 + da[dp++] = (byte)(bb[2] & 0x7f);
18000 + da[dp++] = (byte)(bb[3] & 0x7f);
18002 + sp++;
18003 + continue;
18007 + return CoderResult.unmappableForLength(1);
18009 + return CoderResult.UNDERFLOW;
18010 + } finally {
18011 + src.position(sp - src.arrayOffset());
18012 + dst.position(dp - dst.arrayOffset());
18017 + private class Decoder extends EUC_TW.Decoder {
18018 + int plane;
18019 + private String table;
18020 + protected Decoder(Charset cs, int plane) {
18021 + super(cs);
18022 + if (plane == 0)
18023 + this.plane = plane;
18024 + else if (plane == 2 || plane == 3)
18025 + this.plane = plane - 1;
18026 + else
18027 + throw new IllegalArgumentException
18028 + ("Only planes 1, 2, and 3 supported");
18031 + //we only work on array backed buffer.
18032 + protected CoderResult decodeLoop(ByteBuffer src, CharBuffer dst) {
18033 + byte[] sa = src.array();
18034 + int sp = src.arrayOffset() + src.position();
18035 + int sl = src.arrayOffset() + src.limit();
18037 + char[] da = dst.array();
18038 + int dp = dst.arrayOffset() + dst.position();
18039 + int dl = dst.arrayOffset() + dst.limit();
18041 + try {
18042 + while (sp < sl) {
18043 + if ( sl - sp < 2) {
18044 + return CoderResult.UNDERFLOW;
18046 + int b1 = (sa[sp] & 0xff) | 0x80;
18047 + int b2 = (sa[sp + 1] & 0xff) | 0x80;
18048 + char[] cc = toUnicode(b1, b2, plane);
18049 + // plane3 has non-bmp characters(added), x11cnsp3
18050 + // however does not support them
18051 + if (cc == null || cc.length == 2)
18052 + return CoderResult.unmappableForLength(2);
18053 + if (dl - dp < 1)
18054 + return CoderResult.OVERFLOW;
18055 + da[dp++] = cc[0];
18056 + sp +=2;
18058 + return CoderResult.UNDERFLOW;
18059 + } finally {
18060 + src.position(sp - src.arrayOffset());
18061 + dst.position(dp - dst.arrayOffset());
18066 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/solaris/classes/sun/font/X11CNS11643P1.java jdk22u-jdk-22.0.2-ga/src/java.desktop/solaris/classes/sun/font/X11CNS11643P1.java
18067 --- jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/solaris/classes/sun/font/X11CNS11643P1.java 1970-01-01 01:00:00.000000000 +0100
18068 +++ jdk22u-jdk-22.0.2-ga/src/java.desktop/solaris/classes/sun/font/X11CNS11643P1.java 2024-08-17 19:34:03.917632238 +0200
18069 @@ -0,0 +1,33 @@
18071 + * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
18072 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
18074 + * This code is free software; you can redistribute it and/or modify it
18075 + * under the terms of the GNU General Public License version 2 only, as
18076 + * published by the Free Software Foundation. Oracle designates this
18077 + * particular file as subject to the "Classpath" exception as provided
18078 + * by Oracle in the LICENSE file that accompanied this code.
18080 + * This code is distributed in the hope that it will be useful, but WITHOUT
18081 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18082 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18083 + * version 2 for more details (a copy is included in the LICENSE file that
18084 + * accompanied this code).
18086 + * You should have received a copy of the GNU General Public License version
18087 + * 2 along with this work; if not, write to the Free Software Foundation,
18088 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18090 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
18091 + * or visit www.oracle.com if you need additional information or have any
18092 + * questions.
18093 + */
18096 +package sun.font;
18098 +public class X11CNS11643P1 extends X11CNS11643 {
18099 + public X11CNS11643P1() {
18100 + super(1, "X11CNS11643P1");
18103 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/solaris/classes/sun/font/X11CNS11643P2.java jdk22u-jdk-22.0.2-ga/src/java.desktop/solaris/classes/sun/font/X11CNS11643P2.java
18104 --- jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/solaris/classes/sun/font/X11CNS11643P2.java 1970-01-01 01:00:00.000000000 +0100
18105 +++ jdk22u-jdk-22.0.2-ga/src/java.desktop/solaris/classes/sun/font/X11CNS11643P2.java 2024-08-17 19:34:03.917885340 +0200
18106 @@ -0,0 +1,32 @@
18108 + * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
18109 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
18111 + * This code is free software; you can redistribute it and/or modify it
18112 + * under the terms of the GNU General Public License version 2 only, as
18113 + * published by the Free Software Foundation. Oracle designates this
18114 + * particular file as subject to the "Classpath" exception as provided
18115 + * by Oracle in the LICENSE file that accompanied this code.
18117 + * This code is distributed in the hope that it will be useful, but WITHOUT
18118 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18119 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18120 + * version 2 for more details (a copy is included in the LICENSE file that
18121 + * accompanied this code).
18123 + * You should have received a copy of the GNU General Public License version
18124 + * 2 along with this work; if not, write to the Free Software Foundation,
18125 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18127 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
18128 + * or visit www.oracle.com if you need additional information or have any
18129 + * questions.
18130 + */
18132 +package sun.font;
18134 +public class X11CNS11643P2 extends X11CNS11643 {
18135 + public X11CNS11643P2() {
18136 + super(2, "X11CNS11643P2");
18139 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/solaris/classes/sun/font/X11CNS11643P3.java jdk22u-jdk-22.0.2-ga/src/java.desktop/solaris/classes/sun/font/X11CNS11643P3.java
18140 --- jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/solaris/classes/sun/font/X11CNS11643P3.java 1970-01-01 01:00:00.000000000 +0100
18141 +++ jdk22u-jdk-22.0.2-ga/src/java.desktop/solaris/classes/sun/font/X11CNS11643P3.java 2024-08-17 19:34:03.918146805 +0200
18142 @@ -0,0 +1,32 @@
18144 + * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved.
18145 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
18147 + * This code is free software; you can redistribute it and/or modify it
18148 + * under the terms of the GNU General Public License version 2 only, as
18149 + * published by the Free Software Foundation. Oracle designates this
18150 + * particular file as subject to the "Classpath" exception as provided
18151 + * by Oracle in the LICENSE file that accompanied this code.
18153 + * This code is distributed in the hope that it will be useful, but WITHOUT
18154 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18155 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18156 + * version 2 for more details (a copy is included in the LICENSE file that
18157 + * accompanied this code).
18159 + * You should have received a copy of the GNU General Public License version
18160 + * 2 along with this work; if not, write to the Free Software Foundation,
18161 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18163 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
18164 + * or visit www.oracle.com if you need additional information or have any
18165 + * questions.
18166 + */
18168 +package sun.font;
18170 +public class X11CNS11643P3 extends X11CNS11643 {
18171 + public X11CNS11643P3() {
18172 + super(3, "X11CNS11643P3");
18175 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/solaris/data/fontconfig/fontconfig.properties jdk22u-jdk-22.0.2-ga/src/java.desktop/solaris/data/fontconfig/fontconfig.properties
18176 --- jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/solaris/data/fontconfig/fontconfig.properties 1970-01-01 01:00:00.000000000 +0100
18177 +++ jdk22u-jdk-22.0.2-ga/src/java.desktop/solaris/data/fontconfig/fontconfig.properties 2024-08-17 19:34:03.892433077 +0200
18178 @@ -0,0 +1,516 @@
18181 +# Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
18182 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
18184 +# This code is free software; you can redistribute it and/or modify it
18185 +# under the terms of the GNU General Public License version 2 only, as
18186 +# published by the Free Software Foundation. Oracle designates this
18187 +# particular file as subject to the "Classpath" exception as provided
18188 +# by Oracle in the LICENSE file that accompanied this code.
18190 +# This code is distributed in the hope that it will be useful, but WITHOUT
18191 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18192 +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18193 +# version 2 for more details (a copy is included in the LICENSE file that
18194 +# accompanied this code).
18196 +# You should have received a copy of the GNU General Public License version
18197 +# 2 along with this work; if not, write to the Free Software Foundation,
18198 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18200 +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
18201 +# or visit www.oracle.com if you need additional information or have any
18202 +# questions.
18205 +# Version
18207 +version=1
18209 +# Component Font Mappings
18211 +allfonts.chinese-gb2312=-arphic-uming-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18212 +allfonts.chinese-gbk=-arphic-uming-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18213 +allfonts.chinese-gb18030-0=-arphic-uming-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18214 +allfonts.chinese-gb18030-1=-arphic-uming-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18215 +allfonts.chinese-cns11643-1=-arphic-uming-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18216 +allfonts.chinese-cns11643-2=-arphic-uming-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18217 +allfonts.chinese-cns11643-3=-arphic-uming-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18218 +allfonts.chinese-big5=-arphic-uming-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18219 +allfonts.chinese-hkscs=-arphic-uming-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18220 +allfonts.dingbats=-microsoft-wingdings-medium-r-normal--*-%d-*-*-p-*-adobe-fontspecific
18221 +allfonts.japanese-x0212=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18222 +allfonts.korean=-hanyang-gothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18223 +allfonts.korean-johab=-hanyang-gothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18224 +allfonts.symbol=-monotype-symbol-medium-r-normal--*-%d-*-*-p-*-adobe-symbol
18225 +allfonts.bengali=-misc-lohit bengali-medium-r-normal--0-0-0-0-p-0-iso10646-1
18226 +allfonts.gujarati=-misc-lohit gujarati-medium-r-normal--0-0-0-0-p-0-iso10646-1
18227 +allfonts.hindi=-misc-lohit hindi-medium-r-normal--0-0-0-0-p-0-iso10646-1
18228 +allfonts.kannada=-misc-lohit kannada-medium-r-normal--0-0-0-0-p-0-iso10646-1
18229 +allfonts.malayalam=-misc-lohit malayalam-medium-r-normal--0-0-0-0-p-0-iso10646-1
18230 +allfonts.marathi=-misc-lohit marathi-medium-r-normal--0-0-0-0-p-0-iso10646-1
18231 +allfonts.tamil=-misc-lohit tamil-medium-r-normal--0-0-0-0-p-0-iso10646-1
18232 +allfonts.telugu=-misc-lohit telugu-medium-r-normal--0-0-0-0-p-0-iso10646-1
18233 +allfonts.dejavusans=-misc-dejavu sans-medium-r-normal--0-0-0-0-p-0-iso10646-1
18235 +serif.plain.arabic=-monotype-times new roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18236 +serif.plain.cyrillic-iso8859-5=-monotype-times new roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18237 +serif.plain.cyrillic-cp1251=-monotype-times new roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18238 +serif.plain.cyrillic-koi8-r=-monotype-times new roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18239 +serif.plain.greek=-monotype-times new roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18240 +serif.plain.hebrew=-monotype-times new roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18241 +serif.plain.japanese-x0201=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18242 +serif.plain.japanese-x0208=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18243 +serif.plain.latin-1=-monotype-times new roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18244 +serif.plain.latin-2=-monotype-times new roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18245 +serif.plain.latin-5=-monotype-times new roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18246 +serif.plain.latin-7=-monotype-times new roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18247 +serif.plain.latin-9=-monotype-times new roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18248 +serif.plain.thai=-monotype-angsana new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18250 +serif.bold.arabic=-monotype-times new roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18251 +serif.bold.cyrillic-iso8859-5=-monotype-times new roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18252 +serif.bold.cyrillic-cp1251=-monotype-times new roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18253 +serif.bold.cyrillic-koi8-r=-monotype-times new roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18254 +serif.bold.greek=-monotype-times new roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18255 +serif.bold.hebrew=-monotype-times new roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18256 +serif.bold.japanese-x0201=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18257 +serif.bold.japanese-x0208=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18258 +serif.bold.latin-1=-monotype-times new roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18259 +serif.bold.latin-2=-monotype-times new roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18260 +serif.bold.latin-5=-monotype-times new roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18261 +serif.bold.latin-7=-monotype-times new roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18262 +serif.bold.latin-9=-monotype-times new roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18263 +serif.bold.thai=-monotype-angsana new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18265 +serif.italic.arabic=-monotype-times new roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18266 +serif.italic.cyrillic-iso8859-5=-monotype-times new roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18267 +serif.italic.cyrillic-cp1251=-monotype-times new roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18268 +serif.italic.cyrillic-koi8-r=-monotype-times new roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18269 +serif.italic.greek=-monotype-times new roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18270 +serif.italic.hebrew=-monotype-times new roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18271 +serif.italic.japanese-x0201=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18272 +serif.italic.japanese-x0208=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18273 +serif.italic.latin-1=-monotype-times new roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18274 +serif.italic.latin-2=-monotype-times new roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18275 +serif.italic.latin-5=-monotype-times new roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18276 +serif.italic.latin-7=-monotype-times new roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18277 +serif.italic.latin-9=-monotype-times new roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18278 +serif.italic.thai=-monotype-angsana new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18280 +serif.bolditalic.arabic=-monotype-times new roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18281 +serif.bolditalic.cyrillic-iso8859-5=-monotype-times new roman-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18282 +serif.bolditalic.cyrillic-cp1251=-monotype-times new roman-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18283 +serif.bolditalic.cyrillic-koi8-r=-monotype-times new roman-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18284 +serif.bolditalic.greek=-monotype-times new roman-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18285 +serif.bolditalic.hebrew=-monotype-times new roman-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18286 +serif.bolditalic.japanese-x0201=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18287 +serif.bolditalic.japanese-x0208=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18288 +serif.bolditalic.latin-1=-monotype-times new roman-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18289 +serif.bolditalic.latin-2=-monotype-times new roman-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18290 +serif.bolditalic.latin-5=-monotype-times new roman-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18291 +serif.bolditalic.latin-7=-monotype-times new roman-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18292 +serif.bolditalic.latin-9=-monotype-times new roman-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18293 +serif.bolditalic.thai=-monotype-angsana new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18295 +sansserif.plain.arabic=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18296 +sansserif.plain.cyrillic-iso8859-5=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18297 +sansserif.plain.cyrillic-cp1251=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18298 +sansserif.plain.cyrillic-koi8-r=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18299 +sansserif.plain.greek=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18300 +sansserif.plain.hebrew=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18301 +sansserif.plain.japanese-x0201=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18302 +sansserif.plain.japanese-x0208=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18303 +sansserif.plain.latin-1=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18304 +sansserif.plain.latin-2=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18305 +sansserif.plain.latin-5=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18306 +sansserif.plain.latin-7=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18307 +sansserif.plain.latin-9=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18308 +sansserif.plain.thai=-monotype-browallia new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18310 +sansserif.bold.arabic=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18311 +sansserif.bold.cyrillic-iso8859-5=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18312 +sansserif.bold.cyrillic-cp1251=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18313 +sansserif.bold.cyrillic-koi8-r=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18314 +sansserif.bold.greek=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18315 +sansserif.bold.hebrew=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18316 +sansserif.bold.japanese-x0201=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18317 +sansserif.bold.japanese-x0208=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18318 +sansserif.bold.latin-1=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18319 +sansserif.bold.latin-2=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18320 +sansserif.bold.latin-5=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18321 +sansserif.bold.latin-7=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18322 +sansserif.bold.latin-9=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18323 +sansserif.bold.thai=-monotype-browallia new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18325 +sansserif.italic.arabic=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18326 +sansserif.italic.cyrillic-iso8859-5=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18327 +sansserif.italic.cyrillic-cp1251=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18328 +sansserif.italic.cyrillic-koi8-r=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18329 +sansserif.italic.greek=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18330 +sansserif.italic.hebrew=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18331 +sansserif.italic.japanese-x0201=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18332 +sansserif.italic.japanese-x0208=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18333 +sansserif.italic.latin-1=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18334 +sansserif.italic.latin-2=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18335 +sansserif.italic.latin-5=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18336 +sansserif.italic.latin-7=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18337 +sansserif.italic.latin-9=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18338 +sansserif.italic.thai=-monotype-browallia new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18340 +sansserif.bolditalic.arabic=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18341 +sansserif.bolditalic.cyrillic-iso8859-5=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18342 +sansserif.bolditalic.cyrillic-cp1251=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18343 +sansserif.bolditalic.cyrillic-koi8-r=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18344 +sansserif.bolditalic.greek=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18345 +sansserif.bolditalic.hebrew=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18346 +sansserif.bolditalic.japanese-x0201=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18347 +sansserif.bolditalic.japanese-x0208=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18348 +sansserif.bolditalic.latin-1=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18349 +sansserif.bolditalic.latin-2=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18350 +sansserif.bolditalic.latin-5=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18351 +sansserif.bolditalic.latin-7=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18352 +sansserif.bolditalic.latin-9=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18353 +sansserif.bolditalic.thai=-monotype-browallia new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18355 +monospaced.plain.arabic=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18356 +monospaced.plain.cyrillic-iso8859-5=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18357 +monospaced.plain.cyrillic-cp1251=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18358 +monospaced.plain.cyrillic-koi8-r=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18359 +monospaced.plain.greek=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18360 +monospaced.plain.hebrew=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18361 +monospaced.plain.japanese-x0201=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18362 +monospaced.plain.japanese-x0208=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18363 +monospaced.plain.latin-1=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18364 +monospaced.plain.latin-2=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18365 +monospaced.plain.latin-5=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18366 +monospaced.plain.latin-7=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18367 +monospaced.plain.latin-9=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18368 +monospaced.plain.thai=-monotype-cordia new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18370 +monospaced.bold.arabic=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18371 +monospaced.bold.cyrillic-iso8859-5=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18372 +monospaced.bold.cyrillic-cp1251=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18373 +monospaced.bold.cyrillic-koi8-r=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18374 +monospaced.bold.greek=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18375 +monospaced.bold.hebrew=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18376 +monospaced.bold.japanese-x0201=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18377 +monospaced.bold.japanese-x0208=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18378 +monospaced.bold.latin-1=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18379 +monospaced.bold.latin-2=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18380 +monospaced.bold.latin-5=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18381 +monospaced.bold.latin-7=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18382 +monospaced.bold.latin-9=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18383 +monospaced.bold.thai=-monotype-cordia new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18385 +monospaced.italic.arabic=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18386 +monospaced.italic.cyrillic-iso8859-5=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18387 +monospaced.italic.cyrillic-cp1251=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18388 +monospaced.italic.cyrillic-koi8-r=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18389 +monospaced.italic.greek=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18390 +monospaced.italic.hebrew=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18391 +monospaced.italic.japanese-x0201=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18392 +monospaced.italic.japanese-x0208=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18393 +monospaced.italic.latin-1=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18394 +monospaced.italic.latin-2=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18395 +monospaced.italic.latin-5=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18396 +monospaced.italic.latin-7=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18397 +monospaced.italic.latin-9=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18398 +monospaced.italic.thai=-monotype-cordia new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18400 +monospaced.bolditalic.arabic=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18401 +monospaced.bolditalic.cyrillic-iso8859-5=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18402 +monospaced.bolditalic.cyrillic-cp1251=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18403 +monospaced.bolditalic.cyrillic-koi8-r=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18404 +monospaced.bolditalic.greek=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18405 +monospaced.bolditalic.hebrew=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18406 +monospaced.bolditalic.japanese-x0201=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18407 +monospaced.bolditalic.japanese-x0208=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18408 +monospaced.bolditalic.latin-1=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18409 +monospaced.bolditalic.latin-2=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18410 +monospaced.bolditalic.latin-5=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18411 +monospaced.bolditalic.latin-7=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18412 +monospaced.bolditalic.latin-9=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18413 +monospaced.bolditalic.thai=-monotype-cordia new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18415 +dialog.plain.arabic=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18416 +dialog.plain.cyrillic-iso8859-5=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18417 +dialog.plain.cyrillic-cp1251=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18418 +dialog.plain.cyrillic-koi8-r=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18419 +dialog.plain.greek=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18420 +dialog.plain.hebrew=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18421 +dialog.plain.japanese-x0201=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18422 +dialog.plain.japanese-x0208=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18423 +dialog.plain.latin-1=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18424 +dialog.plain.latin-2=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18425 +dialog.plain.latin-5=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18426 +dialog.plain.latin-7=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18427 +dialog.plain.latin-9=-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18428 +dialog.plain.thai=-monotype-browallia new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18430 +dialog.bold.arabic=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18431 +dialog.bold.cyrillic-iso8859-5=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18432 +dialog.bold.cyrillic-cp1251=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18433 +dialog.bold.cyrillic-koi8-r=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18434 +dialog.bold.greek=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18435 +dialog.bold.hebrew=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18436 +dialog.bold.japanese-x0201=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18437 +dialog.bold.japanese-x0208=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18438 +dialog.bold.latin-1=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18439 +dialog.bold.latin-2=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18440 +dialog.bold.latin-5=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18441 +dialog.bold.latin-7=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18442 +dialog.bold.latin-9=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18443 +dialog.bold.thai=-monotype-browallia new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18445 +dialog.italic.arabic=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18446 +dialog.italic.cyrillic-iso8859-5=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18447 +dialog.italic.cyrillic-cp1251=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18448 +dialog.italic.cyrillic-koi8-r=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18449 +dialog.italic.greek=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18450 +dialog.italic.hebrew=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18451 +dialog.italic.japanese-x0201=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18452 +dialog.italic.japanese-x0208=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18453 +dialog.italic.latin-1=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18454 +dialog.italic.latin-2=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18455 +dialog.italic.latin-5=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18456 +dialog.italic.latin-7=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18457 +dialog.italic.latin-9=-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18458 +dialog.italic.thai=-monotype-browallia new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18460 +dialog.bolditalic.arabic=-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18461 +dialog.bolditalic.cyrillic-iso8859-5=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18462 +dialog.bolditalic.cyrillic-cp1251=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18463 +dialog.bolditalic.cyrillic-koi8-r=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18464 +dialog.bolditalic.greek=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18465 +dialog.bolditalic.hebrew=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18466 +dialog.bolditalic.japanese-x0201=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18467 +dialog.bolditalic.japanese-x0208=-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18468 +dialog.bolditalic.latin-1=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18469 +dialog.bolditalic.latin-2=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18470 +dialog.bolditalic.latin-5=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18471 +dialog.bolditalic.latin-7=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18472 +dialog.bolditalic.latin-9=-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18473 +dialog.bolditalic.thai=-monotype-browallia new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18475 +dialoginput.plain.arabic=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18476 +dialoginput.plain.cyrillic-iso8859-5=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18477 +dialoginput.plain.cyrillic-cp1251=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18478 +dialoginput.plain.cyrillic-koi8-r=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18479 +dialoginput.plain.greek=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18480 +dialoginput.plain.hebrew=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18481 +dialoginput.plain.japanese-x0201=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18482 +dialoginput.plain.japanese-x0208=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18483 +dialoginput.plain.latin-1=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18484 +dialoginput.plain.latin-2=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18485 +dialoginput.plain.latin-5=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18486 +dialoginput.plain.latin-7=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18487 +dialoginput.plain.latin-9=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18488 +dialoginput.plain.thai=-monotype-cordia new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18490 +dialoginput.bold.arabic=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18491 +dialoginput.bold.cyrillic-iso8859-5=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18492 +dialoginput.bold.cyrillic-cp1251=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18493 +dialoginput.bold.cyrillic-koi8-r=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18494 +dialoginput.bold.greek=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18495 +dialoginput.bold.hebrew=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18496 +dialoginput.bold.japanese-x0201=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18497 +dialoginput.bold.japanese-x0208=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18498 +dialoginput.bold.latin-1=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18499 +dialoginput.bold.latin-2=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18500 +dialoginput.bold.latin-5=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18501 +dialoginput.bold.latin-7=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18502 +dialoginput.bold.latin-9=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18503 +dialoginput.bold.thai=-monotype-cordia new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18505 +dialoginput.italic.arabic=-monotype-courier new-medium-r-normal--*-%d-*-*-p-*-iso10646-1
18506 +dialoginput.italic.cyrillic-iso8859-5=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18507 +dialoginput.italic.cyrillic-cp1251=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18508 +dialoginput.italic.cyrillic-koi8-r=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18509 +dialoginput.italic.greek=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18510 +dialoginput.italic.hebrew=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18511 +dialoginput.italic.japanese-x0201=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18512 +dialoginput.italic.japanese-x0208=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18513 +dialoginput.italic.latin-1=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18514 +dialoginput.italic.latin-2=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18515 +dialoginput.italic.latin-5=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18516 +dialoginput.italic.latin-7=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18517 +dialoginput.italic.latin-9=-monotype-courier new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18518 +dialoginput.italic.thai=-monotype-cordia new-medium-i-normal--*-%d-*-*-p-*-iso10646-1
18520 +dialoginput.bolditalic.arabic=-monotype-courier new-bold-r-normal--*-%d-*-*-p-*-iso10646-1
18521 +dialoginput.bolditalic.cyrillic-iso8859-5=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18522 +dialoginput.bolditalic.cyrillic-cp1251=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18523 +dialoginput.bolditalic.cyrillic-koi8-r=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18524 +dialoginput.bolditalic.greek=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18525 +dialoginput.bolditalic.hebrew=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18526 +dialoginput.bolditalic.japanese-x0201=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18527 +dialoginput.bolditalic.japanese-x0208=-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1
18528 +dialoginput.bolditalic.latin-1=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18529 +dialoginput.bolditalic.latin-2=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18530 +dialoginput.bolditalic.latin-5=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18531 +dialoginput.bolditalic.latin-7=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18532 +dialoginput.bolditalic.latin-9=-monotype-courier new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18533 +dialoginput.bolditalic.thai=-monotype-cordia new-bold-i-normal--*-%d-*-*-p-*-iso10646-1
18535 +# Search Sequences
18537 +sequence.allfonts=latin-1
18539 +sequence.allfonts.Big5=latin-1,chinese-big5
18541 +sequence.allfonts.Big5-HKSCS-2001=latin-1,chinese-big5,chinese-hkscs
18543 +sequence.allfonts.windows-1251=cyrillic-cp1251,latin-1
18545 +sequence.allfonts.GB2312=latin-1,chinese-gb2312
18547 +sequence.allfonts.x-eucJP-Open=latin-1,japanese-x0201,japanese-x0208,japanese-x0212
18549 +sequence.allfonts.EUC-KR=latin-1,korean
18551 +sequence.allfonts.x-EUC-TW=latin-1,chinese-cns11643-1,chinese-cns11643-2,chinese-cns11643-3
18553 +sequence.allfonts.GBK=latin-1,chinese-gbk
18555 +sequence.allfonts.GB18030=latin-1,chinese-gb18030-0,chinese-gb18030-1
18557 +sequence.allfonts.ISO-8859-2=latin-2,latin-1
18559 +sequence.allfonts.ISO-8859-5=cyrillic-iso8859-5,latin-1
18561 +sequence.allfonts.ISO-8859-6=arabic,latin-1
18563 +sequence.allfonts.ISO-8859-7=latin-1,greek
18565 +sequence.allfonts.ISO-8859-8=latin-1,hebrew
18567 +sequence.allfonts.ISO-8859-9=latin-5,latin-1
18569 +sequence.allfonts.ISO-8859-13=latin-7,latin-1
18571 +sequence.allfonts.ISO-8859-15=latin-9
18573 +sequence.allfonts.KOI8-R=cyrillic-koi8-r,latin-1
18575 +sequence.allfonts.x-PCK=latin-1,japanese-x0201,japanese-x0208,japanese-x0212
18577 +sequence.allfonts.TIS-620=latin-1,thai
18579 +sequence.allfonts.UTF-8=latin-1
18580 +sequence.allfonts.UTF-8.en=latin-1
18581 +sequence.allfonts.UTF-8.hi=latin-1,hindi
18582 +sequence.allfonts.UTF-8.be=latin-1,bengali
18583 +sequence.allfonts.UTF-8.te=latin-1,telugu
18584 +sequence.allfonts.UTF-8.mr=latin-1,marathi
18585 +sequence.allfonts.UTF-8.ta=latin-1,tamil
18586 +sequence.allfonts.UTF-8.gu=latin-1,gujarati
18587 +sequence.allfonts.UTF-8.kn=latin-1,kannada
18588 +sequence.allfonts.UTF-8.ma=latin-1,malayalam
18590 +sequence.allfonts.UTF-8.ko=latin-1,korean-johab,japanese-x0201,japanese-x0208,japanese-x0212
18592 +sequence.allfonts.UTF-8.th=latin-1,thai
18594 +sequence.allfonts.UTF-8.zh.CN=latin-1,chinese-gb18030-0,chinese-gb18030-1,chinese-big5,chinese-hkscs
18596 +sequence.allfonts.UTF-8.zh.HK=latin-1,chinese-big5,chinese-hkscs,chinese-gb18030-0,chinese-gb18030-1
18598 +sequence.allfonts.UTF-8.zh.TW=latin-1,chinese-big5,chinese-hkscs,chinese-gb18030-0,chinese-gb18030-1
18600 +# the fallback sequence omits the following character subsets:
18601 +# - chinese: all same file : just use chinese-gb18030-0
18602 +# - japanese-x0208: same files as japanese-x0201
18603 +# - japanese-x0212: same files as japanese-x0201
18604 +# - korean: same file as korean-johab
18605 +sequence.fallback=latin-1,latin-2,latin-7,cyrillic-iso8859-5,greek,latin-5,latin-9,\
18606 + arabic,hebrew,thai,\
18607 + chinese-gb18030-0,\
18608 + japanese-x0201,korean-johab,\
18609 + hindi,bengali,telugu,marathi,tamil,gujarati,kannada,malayalam,\
18610 + dejavusans,dingbats,symbol
18612 +# Font File Names
18614 +filename.-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/arial.ttf
18615 +filename.-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/ariali.ttf
18616 +filename.-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/arialbd.ttf
18617 +filename.-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/arialbi.ttf
18618 +filename.-monotype-courier_new-medium-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/cour.ttf
18619 +filename.-monotype-courier_new-medium-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/couri.ttf
18620 +filename.-monotype-courier_new-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/courbd.ttf
18621 +filename.-monotype-courier_new-bold-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/courbi.ttf
18622 +filename.-monotype-times_new_roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/times.ttf
18623 +filename.-monotype-times_new_roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/timesi.ttf
18624 +filename.-monotype-times_new_roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/timesbd.ttf
18625 +filename.-monotype-times_new_roman-bold-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/timesbi.ttf
18627 +filename.-monotype-angsana_new-medium-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/angsa.ttf
18628 +filename.-monotype-angsana_new-medium-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/angsai.ttf
18629 +filename.-monotype-angsana_new-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/angsab.ttf
18630 +filename.-monotype-angsana_new-bold-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/angsaz.ttf
18631 +filename.-monotype-browallia_new-medium-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/browa.ttf
18632 +filename.-monotype-browallia_new-medium-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/browai.ttf
18633 +filename.-monotype-browallia_new-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/browab.ttf
18634 +filename.-monotype-browallia_new-bold-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/browaz.ttf
18635 +filename.-monotype-cordia_new-medium-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/cordia.ttf
18636 +filename.-monotype-cordia_new-medium-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/cordiai.ttf
18637 +filename.-monotype-cordia_new-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/cordiab.ttf
18638 +filename.-monotype-cordia_new-bold-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/cordiaz.ttf
18640 +filename.-misc-ipagothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1=/usr/share/fonts/TrueType/ipafont/ipag.otf
18641 +filename.-misc-ipamincho-medium-r-normal--*-%d-*-*-m-*-iso10646-1=/usr/share/fonts/TrueType/ipafont/ipam.otf
18642 +filename.-hanyang-gothic-medium-r-normal--*-%d-*-*-m-*-iso10646-1=/usr/share/fonts/TrueType/hanyang/h2gtrm.ttf
18643 +filename.-arphic-uming-medium-r-normal--*-%d-*-*-m-*-iso10646-1=/usr/share/fonts/TrueType/arphic/uming.ttf
18644 +filename.-monotype-symbol-medium-r-normal--*-%d-*-*-p-*-adobe-symbol=/usr/share/fonts/TrueType/core/symbol.ttf
18645 +filename.-microsoft-wingdings-medium-r-normal--*-%d-*-*-p-*-adobe-fontspecific=/usr/share/fonts/TrueType/core/wingdings.ttf
18646 +filename.-misc-lohit_bengali-medium-r-normal--0-0-0-0-p-0-iso10646-1=/usr/share/fonts/TrueType/lohit/Lohit-Bengali.ttf
18647 +filename.-misc-lohit_gujarati-medium-r-normal--0-0-0-0-p-0-iso10646-1=/usr/share/fonts/TrueType/lohit/Lohit-Gujarati.ttf
18648 +filename.-misc-lohit_hindi-medium-r-normal--0-0-0-0-p-0-iso10646-1=/usr/share/fonts/TrueType/lohit/Lohit-Hindi.ttf
18649 +filename.-misc-lohit_kannada-medium-r-normal--0-0-0-0-p-0-iso10646-1=/usr/share/fonts/TrueType/lohit/Lohit-Kannada.ttf
18650 +filename.-misc-lohit_malayalam-medium-r-normal--0-0-0-0-p-0-iso10646-1=/usr/share/fonts/TrueType/lohit/Lohit-Malayalam.ttf
18651 +filename.-misc-lohit_marathi-medium-r-normal--0-0-0-0-p-0-iso10646-1=/usr/share/fonts/TrueType/lohit/Lohit-Marathi.ttf
18652 +filename.-misc-lohit_tamil-medium-r-normal--0-0-0-0-p-0-iso10646-1=/usr/share/fonts/TrueType/lohit/Lohit-Tamil.ttf
18653 +filename.-misc-lohit_telugu-medium-r-normal--0-0-0-0-p-0-iso10646-1=/usr/share/fonts/TrueType/lohit/Lohit-Telugu.ttf
18654 +filename.-misc-dejavu_sans-medium-r-normal--0-0-0-0-p-0-iso10646-1=/usr/share/fonts/TrueType/dejavu/DejaVuSans.ttf
18656 +# AWT X11 font paths
18657 +awtfontpath.latin-1=/usr/share/fonts/TrueType/core
18658 +awtfontpath.latin-2=/usr/share/fonts/TrueType/core
18659 +awtfontpath.latin-5=/usr/share/fonts/TrueType/core
18660 +awtfontpath.latin-7=/usr/share/fonts/TrueType/core
18661 +awtfontpath.latin-9=/usr/share/fonts/TrueType/core
18662 +awtfontpath.hebrew=/usr/share/fonts/TrueType/core
18663 +awtfontpath.arabic=/usr/share/fonts/TrueType/core
18664 +awtfontpath.thai=/usr/share/fonts/TrueType/core
18665 +awtfontpath.greek=/usr/share/fonts/TrueType/core
18666 +awtfontpath.cyrillic-iso8859-5=/usr/share/fonts/TrueType/core
18667 +awtfontpath.cyrillic-cp1251=/usr/share/fonts/TrueType/core
18668 +awtfontpath.cyrillic-koi8-r=/usr/share/fonts/TrueType/core
18669 +awtfontpath.korean=/usr/share/fonts/TrueType/hanyang
18670 +awtfontpath.korean-johab=/usr/share/fonts/TrueType/hanyang
18671 +awtfontpath.japanese-x0201=/usr/share/fonts/TrueType/ipafont
18672 +awtfontpath.japanese-x0208=/usr/share/fonts/TrueType/ipafont
18673 +awtfontpath.japanese-x0212=/usr/share/fonts/TrueType/ipafont
18674 +awtfontpath.chinese-gbk=/usr/share/fonts/TrueType/arphic
18675 +awtfontpath.chinese-cns11643-1=/usr/share/fonts/TrueType/arphic
18676 +awtfontpath.chinese-cns11643-2=/usr/share/fonts/TrueType/arphic
18677 +awtfontpath.chinese-cns11643-3=/usr/share/fonts/TrueType/arphic
18678 +awtfontpath.chinese-big5=/usr/share/fonts/TrueType/arphic
18679 +awtfontpath.chinese-gb2312=/usr/share/fonts/TrueType/arphic
18680 +awtfontpath.chinese-gb18030-0=/usr/share/fonts/TrueType/arphic
18681 +awtfontpath.chinese-gb18030-1=/usr/share/fonts/TrueType/arphic
18682 +awtfontpath.chinese-hkscs=/usr/share/fonts/TrueType/arphic
18683 +awtfontpath.bengali=/usr/share/fonts/TrueType/lohit
18684 +awtfontpath.gujarati=/usr/share/fonts/TrueType/lohit
18685 +awtfontpath.hindi=/usr/share/fonts/TrueType/lohit
18686 +awtfontpath.kannada=/usr/share/fonts/TrueType/lohit
18687 +awtfontpath.malayalam=/usr/share/fonts/TrueType/lohit
18688 +awtfontpath.marathi=/usr/share/fonts/TrueType/lohit
18689 +awtfontpath.tamil=/usr/share/fonts/TrueType/lohit
18690 +awtfontpath.telugu=/usr/share/fonts/TrueType/lohit
18691 +awtfontpath.dejavusans=/usr/share/fonts/TrueType/dejavu
18693 +# Appended Font Path
18695 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_PCM.c jdk22u-jdk-22.0.2-ga/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_PCM.c
18696 --- jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_PCM.c 1970-01-01 01:00:00.000000000 +0100
18697 +++ jdk22u-jdk-22.0.2-ga/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_PCM.c 2024-08-17 19:34:03.918752166 +0200
18698 @@ -0,0 +1,627 @@
18700 + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
18701 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
18703 + * This code is free software; you can redistribute it and/or modify it
18704 + * under the terms of the GNU General Public License version 2 only, as
18705 + * published by the Free Software Foundation. Oracle designates this
18706 + * particular file as subject to the "Classpath" exception as provided
18707 + * by Oracle in the LICENSE file that accompanied this code.
18709 + * This code is distributed in the hope that it will be useful, but WITHOUT
18710 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18711 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18712 + * version 2 for more details (a copy is included in the LICENSE file that
18713 + * accompanied this code).
18715 + * You should have received a copy of the GNU General Public License version
18716 + * 2 along with this work; if not, write to the Free Software Foundation,
18717 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18719 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
18720 + * or visit www.oracle.com if you need additional information or have any
18721 + * questions.
18722 + */
18724 +#define USE_ERROR
18725 +#define USE_TRACE
18727 +#include "PLATFORM_API_SolarisOS_Utils.h"
18728 +#include "DirectAudio.h"
18730 +#if USE_DAUDIO == TRUE
18733 +// The default buffer time
18734 +#define DEFAULT_PERIOD_TIME_MILLIS 50
18736 +///// implemented functions of DirectAudio.h
18738 +INT32 DAUDIO_GetDirectAudioDeviceCount() {
18739 + return (INT32) getAudioDeviceCount();
18743 +INT32 DAUDIO_GetDirectAudioDeviceDescription(INT32 mixerIndex,
18744 + DirectAudioDeviceDescription* description) {
18745 + AudioDeviceDescription desc;
18747 + if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, TRUE)) {
18748 + description->maxSimulLines = desc.maxSimulLines;
18749 + strncpy(description->name, desc.name, DAUDIO_STRING_LENGTH-1);
18750 + description->name[DAUDIO_STRING_LENGTH-1] = 0;
18751 + strncpy(description->vendor, desc.vendor, DAUDIO_STRING_LENGTH-1);
18752 + description->vendor[DAUDIO_STRING_LENGTH-1] = 0;
18753 + strncpy(description->version, desc.version, DAUDIO_STRING_LENGTH-1);
18754 + description->version[DAUDIO_STRING_LENGTH-1] = 0;
18755 + /*strncpy(description->description, desc.description, DAUDIO_STRING_LENGTH-1);*/
18756 + strncpy(description->description, "Solaris Mixer", DAUDIO_STRING_LENGTH-1);
18757 + description->description[DAUDIO_STRING_LENGTH-1] = 0;
18758 + return TRUE;
18760 + return FALSE;
18764 +#define MAX_SAMPLE_RATES 20
18766 +void DAUDIO_GetFormats(INT32 mixerIndex, INT32 deviceID, int isSource, void* creator) {
18767 + int fd = -1;
18768 + AudioDeviceDescription desc;
18769 + am_sample_rates_t *sr;
18770 + /* hardcoded bits and channels */
18771 + int bits[] = {8, 16};
18772 + int bitsCount = 2;
18773 + int channels[] = {1, 2};
18774 + int channelsCount = 2;
18775 + /* for querying sample rates */
18776 + int err;
18777 + int ch, b;
18778 + uint_t s;
18780 + TRACE2("DAUDIO_GetFormats, mixer %d, isSource=%d\n", mixerIndex, isSource);
18781 + if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, FALSE)) {
18782 + fd = open(desc.pathctl, O_RDONLY);
18784 + if (fd < 0) {
18785 + ERROR1("Couldn't open audio device ctl for device %d!\n", mixerIndex);
18786 + return;
18789 + /* get sample rates */
18790 + sr = (am_sample_rates_t*) malloc(AUDIO_MIXER_SAMP_RATES_STRUCT_SIZE(MAX_SAMPLE_RATES));
18791 + if (sr == NULL) {
18792 + ERROR1("DAUDIO_GetFormats: out of memory for mixer %d\n", (int) mixerIndex);
18793 + close(fd);
18794 + return;
18797 + sr->num_samp_rates = MAX_SAMPLE_RATES;
18798 + sr->type = isSource?AUDIO_PLAY:AUDIO_RECORD;
18799 + sr->samp_rates[0] = -2;
18800 + err = ioctl(fd, AUDIO_MIXER_GET_SAMPLE_RATES, sr);
18801 + if (err < 0) {
18802 + ERROR1(" DAUDIO_GetFormats: AUDIO_MIXER_GET_SAMPLE_RATES failed for mixer %d!\n",
18803 + (int)mixerIndex);
18804 + ERROR2(" -> num_sample_rates=%d sample_rates[0] = %d\n",
18805 + (int) sr->num_samp_rates,
18806 + (int) sr->samp_rates[0]);
18807 + /* Some Solaris 8 drivers fail for get sample rates!
18808 + * Do as if we support all sample rates
18809 + */
18810 + sr->flags = MIXER_SR_LIMITS;
18812 + if ((sr->flags & MIXER_SR_LIMITS)
18813 + || (sr->num_samp_rates > MAX_SAMPLE_RATES)) {
18814 +#ifdef USE_TRACE
18815 + if ((sr->flags & MIXER_SR_LIMITS)) {
18816 + TRACE1(" DAUDIO_GetFormats: floating sample rate allowed by mixer %d\n",
18817 + (int)mixerIndex);
18819 + if (sr->num_samp_rates > MAX_SAMPLE_RATES) {
18820 + TRACE2(" DAUDIO_GetFormats: more than %d formats. Use -1 for sample rates mixer %d\n",
18821 + MAX_SAMPLE_RATES, (int)mixerIndex);
18823 +#endif
18824 + /*
18825 + * Fake it to have only one sample rate: -1
18826 + */
18827 + sr->num_samp_rates = 1;
18828 + sr->samp_rates[0] = -1;
18830 + close(fd);
18832 + for (ch = 0; ch < channelsCount; ch++) {
18833 + for (b = 0; b < bitsCount; b++) {
18834 + for (s = 0; s < sr->num_samp_rates; s++) {
18835 + DAUDIO_AddAudioFormat(creator,
18836 + bits[b], /* significant bits */
18837 + 0, /* frameSize: let it be calculated */
18838 + channels[ch],
18839 + (float) ((int) sr->samp_rates[s]),
18840 + DAUDIO_PCM, /* encoding - let's only do PCM */
18841 + (bits[b] > 8)?TRUE:TRUE, /* isSigned */
18842 +#ifdef _LITTLE_ENDIAN
18843 + FALSE /* little endian */
18844 +#else
18845 + (bits[b] > 8)?TRUE:FALSE /* big endian */
18846 +#endif
18847 + );
18851 + free(sr);
18855 +typedef struct {
18856 + int fd;
18857 + audio_info_t info;
18858 + int bufferSizeInBytes;
18859 + int frameSize; /* storage size in Bytes */
18860 + /* how many bytes were written or read */
18861 + INT32 transferedBytes;
18862 + /* if transferedBytes exceed 32-bit boundary,
18863 + * it will be reset and positionOffset will receive
18864 + * the offset
18865 + */
18866 + INT64 positionOffset;
18867 +} SolPcmInfo;
18870 +void* DAUDIO_Open(INT32 mixerIndex, INT32 deviceID, int isSource,
18871 + int encoding, float sampleRate, int sampleSizeInBits,
18872 + int frameSize, int channels,
18873 + int isSigned, int isBigEndian, int bufferSizeInBytes) {
18874 + int err = 0;
18875 + int openMode;
18876 + AudioDeviceDescription desc;
18877 + SolPcmInfo* info;
18879 + TRACE0("> DAUDIO_Open\n");
18880 + if (encoding != DAUDIO_PCM) {
18881 + ERROR1(" DAUDIO_Open: invalid encoding %d\n", (int) encoding);
18882 + return NULL;
18884 + if (channels <= 0) {
18885 + ERROR1(" DAUDIO_Open: Invalid number of channels=%d!\n", channels);
18886 + return NULL;
18889 + info = (SolPcmInfo*) malloc(sizeof(SolPcmInfo));
18890 + if (!info) {
18891 + ERROR0("Out of memory\n");
18892 + return NULL;
18894 + memset(info, 0, sizeof(SolPcmInfo));
18895 + info->frameSize = frameSize;
18896 + info->fd = -1;
18898 + if (isSource) {
18899 + openMode = O_WRONLY;
18900 + } else {
18901 + openMode = O_RDONLY;
18904 +#ifndef __linux__
18905 + /* blackdown does not use NONBLOCK */
18906 + openMode |= O_NONBLOCK;
18907 +#endif
18909 + if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, FALSE)) {
18910 + info->fd = open(desc.path, openMode);
18912 + if (info->fd < 0) {
18913 + ERROR1("Couldn't open audio device for mixer %d!\n", mixerIndex);
18914 + free(info);
18915 + return NULL;
18917 + /* set to multiple open */
18918 + if (ioctl(info->fd, AUDIO_MIXER_MULTIPLE_OPEN, NULL) >= 0) {
18919 + TRACE1("DAUDIO_Open: %s set to multiple open\n", desc.path);
18920 + } else {
18921 + ERROR1("DAUDIO_Open: ioctl AUDIO_MIXER_MULTIPLE_OPEN failed on %s!\n", desc.path);
18924 + AUDIO_INITINFO(&(info->info));
18925 + /* need AUDIO_GETINFO ioctl to get this to work on solaris x86 */
18926 + err = ioctl(info->fd, AUDIO_GETINFO, &(info->info));
18928 + /* not valid to call AUDIO_SETINFO ioctl with all the fields from AUDIO_GETINFO. */
18929 + AUDIO_INITINFO(&(info->info));
18931 + if (isSource) {
18932 + info->info.play.sample_rate = sampleRate;
18933 + info->info.play.precision = sampleSizeInBits;
18934 + info->info.play.channels = channels;
18935 + info->info.play.encoding = AUDIO_ENCODING_LINEAR;
18936 + info->info.play.buffer_size = bufferSizeInBytes;
18937 + info->info.play.pause = 1;
18938 + } else {
18939 + info->info.record.sample_rate = sampleRate;
18940 + info->info.record.precision = sampleSizeInBits;
18941 + info->info.record.channels = channels;
18942 + info->info.record.encoding = AUDIO_ENCODING_LINEAR;
18943 + info->info.record.buffer_size = bufferSizeInBytes;
18944 + info->info.record.pause = 1;
18946 + err = ioctl(info->fd, AUDIO_SETINFO, &(info->info));
18947 + if (err < 0) {
18948 + ERROR0("DAUDIO_Open: could not set info!\n");
18949 + DAUDIO_Close((void*) info, isSource);
18950 + return NULL;
18952 + DAUDIO_Flush((void*) info, isSource);
18954 + err = ioctl(info->fd, AUDIO_GETINFO, &(info->info));
18955 + if (err >= 0) {
18956 + if (isSource) {
18957 + info->bufferSizeInBytes = info->info.play.buffer_size;
18958 + } else {
18959 + info->bufferSizeInBytes = info->info.record.buffer_size;
18961 + TRACE2("DAUDIO: buffersize in bytes: requested=%d, got %d\n",
18962 + (int) bufferSizeInBytes,
18963 + (int) info->bufferSizeInBytes);
18964 + } else {
18965 + ERROR0("DAUDIO_Open: cannot get info!\n");
18966 + DAUDIO_Close((void*) info, isSource);
18967 + return NULL;
18969 + TRACE0("< DAUDIO_Open: Opened device successfully.\n");
18970 + return (void*) info;
18974 +int DAUDIO_Start(void* id, int isSource) {
18975 + SolPcmInfo* info = (SolPcmInfo*) id;
18976 + int err, modified;
18977 + audio_info_t audioInfo;
18979 + TRACE0("> DAUDIO_Start\n");
18981 + AUDIO_INITINFO(&audioInfo);
18982 + err = ioctl(info->fd, AUDIO_GETINFO, &audioInfo);
18983 + if (err >= 0) {
18984 + // unpause
18985 + modified = FALSE;
18986 + if (isSource && audioInfo.play.pause) {
18987 + audioInfo.play.pause = 0;
18988 + modified = TRUE;
18990 + if (!isSource && audioInfo.record.pause) {
18991 + audioInfo.record.pause = 0;
18992 + modified = TRUE;
18994 + if (modified) {
18995 + err = ioctl(info->fd, AUDIO_SETINFO, &audioInfo);
18999 + TRACE1("< DAUDIO_Start %s\n", (err>=0)?"success":"error");
19000 + return (err >= 0)?TRUE:FALSE;
19003 +int DAUDIO_Stop(void* id, int isSource) {
19004 + SolPcmInfo* info = (SolPcmInfo*) id;
19005 + int err, modified;
19006 + audio_info_t audioInfo;
19008 + TRACE0("> DAUDIO_Stop\n");
19010 + AUDIO_INITINFO(&audioInfo);
19011 + err = ioctl(info->fd, AUDIO_GETINFO, &audioInfo);
19012 + if (err >= 0) {
19013 + // pause
19014 + modified = FALSE;
19015 + if (isSource && !audioInfo.play.pause) {
19016 + audioInfo.play.pause = 1;
19017 + modified = TRUE;
19019 + if (!isSource && !audioInfo.record.pause) {
19020 + audioInfo.record.pause = 1;
19021 + modified = TRUE;
19023 + if (modified) {
19024 + err = ioctl(info->fd, AUDIO_SETINFO, &audioInfo);
19028 + TRACE1("< DAUDIO_Stop %s\n", (err>=0)?"success":"error");
19029 + return (err >= 0)?TRUE:FALSE;
19032 +void DAUDIO_Close(void* id, int isSource) {
19033 + SolPcmInfo* info = (SolPcmInfo*) id;
19035 + TRACE0("DAUDIO_Close\n");
19036 + if (info != NULL) {
19037 + if (info->fd >= 0) {
19038 + DAUDIO_Flush(id, isSource);
19039 + close(info->fd);
19041 + free(info);
19045 +#ifndef USE_TRACE
19046 +/* close to 2^31 */
19047 +#define POSITION_MAX 2000000000
19048 +#else
19049 +/* for testing */
19050 +#define POSITION_MAX 1000000
19051 +#endif
19053 +void resetErrorFlagAndAdjustPosition(SolPcmInfo* info, int isSource, int count) {
19054 + audio_info_t audioInfo;
19055 + audio_prinfo_t* prinfo;
19056 + int err;
19057 + int offset = -1;
19058 + int underrun = FALSE;
19059 + int devBytes = 0;
19061 + if (count > 0) {
19062 + info->transferedBytes += count;
19064 + if (isSource) {
19065 + prinfo = &(audioInfo.play);
19066 + } else {
19067 + prinfo = &(audioInfo.record);
19069 + AUDIO_INITINFO(&audioInfo);
19070 + err = ioctl(info->fd, AUDIO_GETINFO, &audioInfo);
19071 + if (err >= 0) {
19072 + underrun = prinfo->error;
19073 + devBytes = prinfo->samples * info->frameSize;
19075 + AUDIO_INITINFO(&audioInfo);
19076 + if (underrun) {
19077 + /* if an underrun occurred, reset */
19078 + ERROR1("DAUDIO_Write/Read: Underrun/overflow: adjusting positionOffset by %d:\n",
19079 + (devBytes - info->transferedBytes));
19080 + ERROR1(" devBytes from %d to 0, ", devBytes);
19081 + ERROR2(" positionOffset from %d to %d ",
19082 + (int) info->positionOffset,
19083 + (int) (info->positionOffset + info->transferedBytes));
19084 + ERROR1(" transferedBytes from %d to 0\n",
19085 + (int) info->transferedBytes);
19086 + prinfo->samples = 0;
19087 + info->positionOffset += info->transferedBytes;
19088 + info->transferedBytes = 0;
19090 + else if (info->transferedBytes > POSITION_MAX) {
19091 + /* we will reset transferedBytes and
19092 + * the samples field in prinfo
19093 + */
19094 + offset = devBytes;
19095 + prinfo->samples = 0;
19097 + /* reset error flag */
19098 + prinfo->error = 0;
19100 + err = ioctl(info->fd, AUDIO_SETINFO, &audioInfo);
19101 + if (err >= 0) {
19102 + if (offset > 0) {
19103 + /* upon exit of AUDIO_SETINFO, the samples parameter
19104 + * was set to the previous value. This is our
19105 + * offset.
19106 + */
19107 + TRACE1("Adjust samplePos: offset=%d, ", (int) offset);
19108 + TRACE2("transferedBytes=%d -> %d, ",
19109 + (int) info->transferedBytes,
19110 + (int) (info->transferedBytes - offset));
19111 + TRACE2("positionOffset=%d -> %d\n",
19112 + (int) (info->positionOffset),
19113 + (int) (((int) info->positionOffset) + offset));
19114 + info->transferedBytes -= offset;
19115 + info->positionOffset += offset;
19117 + } else {
19118 + ERROR0("DAUDIO: resetErrorFlagAndAdjustPosition ioctl failed!\n");
19123 +// returns -1 on error
19124 +int DAUDIO_Write(void* id, char* data, int byteSize) {
19125 + SolPcmInfo* info = (SolPcmInfo*) id;
19126 + int ret = -1;
19128 + TRACE1("> DAUDIO_Write %d bytes\n", byteSize);
19129 + if (info!=NULL) {
19130 + ret = write(info->fd, data, byteSize);
19131 + resetErrorFlagAndAdjustPosition(info, TRUE, ret);
19132 + /* sets ret to -1 if buffer full, no error! */
19133 + if (ret < 0) {
19134 + ret = 0;
19137 + TRACE1("< DAUDIO_Write: returning %d bytes.\n", ret);
19138 + return ret;
19141 +// returns -1 on error
19142 +int DAUDIO_Read(void* id, char* data, int byteSize) {
19143 + SolPcmInfo* info = (SolPcmInfo*) id;
19144 + int ret = -1;
19146 + TRACE1("> DAUDIO_Read %d bytes\n", byteSize);
19147 + if (info != NULL) {
19148 + ret = read(info->fd, data, byteSize);
19149 + resetErrorFlagAndAdjustPosition(info, TRUE, ret);
19150 + /* sets ret to -1 if buffer full, no error! */
19151 + if (ret < 0) {
19152 + ret = 0;
19155 + TRACE1("< DAUDIO_Read: returning %d bytes.\n", ret);
19156 + return ret;
19160 +int DAUDIO_GetBufferSize(void* id, int isSource) {
19161 + SolPcmInfo* info = (SolPcmInfo*) id;
19162 + if (info) {
19163 + return info->bufferSizeInBytes;
19165 + return 0;
19168 +int DAUDIO_StillDraining(void* id, int isSource) {
19169 + SolPcmInfo* info = (SolPcmInfo*) id;
19170 + audio_info_t audioInfo;
19171 + audio_prinfo_t* prinfo;
19172 + int ret = FALSE;
19174 + if (info!=NULL) {
19175 + if (isSource) {
19176 + prinfo = &(audioInfo.play);
19177 + } else {
19178 + prinfo = &(audioInfo.record);
19180 + /* check error flag */
19181 + AUDIO_INITINFO(&audioInfo);
19182 + ioctl(info->fd, AUDIO_GETINFO, &audioInfo);
19183 + ret = (prinfo->error != 0)?FALSE:TRUE;
19185 + return ret;
19189 +int getDevicePosition(SolPcmInfo* info, int isSource) {
19190 + audio_info_t audioInfo;
19191 + audio_prinfo_t* prinfo;
19192 + int err;
19194 + if (isSource) {
19195 + prinfo = &(audioInfo.play);
19196 + } else {
19197 + prinfo = &(audioInfo.record);
19199 + AUDIO_INITINFO(&audioInfo);
19200 + err = ioctl(info->fd, AUDIO_GETINFO, &audioInfo);
19201 + if (err >= 0) {
19202 + /*TRACE2("---> device paused: %d eof=%d\n",
19203 + prinfo->pause, prinfo->eof);
19204 + */
19205 + return (int) (prinfo->samples * info->frameSize);
19207 + ERROR0("DAUDIO: getDevicePosition: ioctl failed!\n");
19208 + return -1;
19211 +int DAUDIO_Flush(void* id, int isSource) {
19212 + SolPcmInfo* info = (SolPcmInfo*) id;
19213 + int err = -1;
19214 + int pos;
19216 + TRACE0("DAUDIO_Flush\n");
19217 + if (info) {
19218 + if (isSource) {
19219 + err = ioctl(info->fd, I_FLUSH, FLUSHW);
19220 + } else {
19221 + err = ioctl(info->fd, I_FLUSH, FLUSHR);
19223 + if (err >= 0) {
19224 + /* resets the transferedBytes parameter to
19225 + * the current samples count of the device
19226 + */
19227 + pos = getDevicePosition(info, isSource);
19228 + if (pos >= 0) {
19229 + info->transferedBytes = pos;
19233 + if (err < 0) {
19234 + ERROR0("ERROR in DAUDIO_Flush\n");
19236 + return (err < 0)?FALSE:TRUE;
19239 +int DAUDIO_GetAvailable(void* id, int isSource) {
19240 + SolPcmInfo* info = (SolPcmInfo*) id;
19241 + int ret = 0;
19242 + int pos;
19244 + if (info) {
19245 + /* unfortunately, the STREAMS architecture
19246 + * seems to not have a method for querying
19247 + * the available bytes to read/write!
19248 + * estimate it...
19249 + */
19250 + pos = getDevicePosition(info, isSource);
19251 + if (pos >= 0) {
19252 + if (isSource) {
19253 + /* we usually have written more bytes
19254 + * to the queue than the device position should be
19255 + */
19256 + ret = (info->bufferSizeInBytes) - (info->transferedBytes - pos);
19257 + } else {
19258 + /* for record, the device stream should
19259 + * be usually ahead of our read actions
19260 + */
19261 + ret = pos - info->transferedBytes;
19263 + if (ret > info->bufferSizeInBytes) {
19264 + ERROR2("DAUDIO_GetAvailable: available=%d, too big at bufferSize=%d!\n",
19265 + (int) ret, (int) info->bufferSizeInBytes);
19266 + ERROR2(" devicePos=%d, transferedBytes=%d\n",
19267 + (int) pos, (int) info->transferedBytes);
19268 + ret = info->bufferSizeInBytes;
19270 + else if (ret < 0) {
19271 + ERROR1("DAUDIO_GetAvailable: available=%d, in theory not possible!\n",
19272 + (int) ret);
19273 + ERROR2(" devicePos=%d, transferedBytes=%d\n",
19274 + (int) pos, (int) info->transferedBytes);
19275 + ret = 0;
19280 + TRACE1("DAUDIO_GetAvailable returns %d bytes\n", ret);
19281 + return ret;
19284 +INT64 DAUDIO_GetBytePosition(void* id, int isSource, INT64 javaBytePos) {
19285 + SolPcmInfo* info = (SolPcmInfo*) id;
19286 + int ret;
19287 + int pos;
19288 + INT64 result = javaBytePos;
19290 + if (info) {
19291 + pos = getDevicePosition(info, isSource);
19292 + if (pos >= 0) {
19293 + result = info->positionOffset + pos;
19297 + //printf("getbyteposition: javaBytePos=%d , return=%d\n", (int) javaBytePos, (int) result);
19298 + return result;
19302 +void DAUDIO_SetBytePosition(void* id, int isSource, INT64 javaBytePos) {
19303 + SolPcmInfo* info = (SolPcmInfo*) id;
19304 + int ret;
19305 + int pos;
19307 + if (info) {
19308 + pos = getDevicePosition(info, isSource);
19309 + if (pos >= 0) {
19310 + info->positionOffset = javaBytePos - pos;
19315 +int DAUDIO_RequiresServicing(void* id, int isSource) {
19316 + // never need servicing on Solaris
19317 + return FALSE;
19320 +void DAUDIO_Service(void* id, int isSource) {
19321 + // never need servicing on Solaris
19325 +#endif // USE_DAUDIO
19326 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Ports.c jdk22u-jdk-22.0.2-ga/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Ports.c
19327 --- jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Ports.c 1970-01-01 01:00:00.000000000 +0100
19328 +++ jdk22u-jdk-22.0.2-ga/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Ports.c 2024-08-17 19:34:03.919267169 +0200
19329 @@ -0,0 +1,600 @@
19331 + * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
19332 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
19334 + * This code is free software; you can redistribute it and/or modify it
19335 + * under the terms of the GNU General Public License version 2 only, as
19336 + * published by the Free Software Foundation. Oracle designates this
19337 + * particular file as subject to the "Classpath" exception as provided
19338 + * by Oracle in the LICENSE file that accompanied this code.
19340 + * This code is distributed in the hope that it will be useful, but WITHOUT
19341 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19342 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19343 + * version 2 for more details (a copy is included in the LICENSE file that
19344 + * accompanied this code).
19346 + * You should have received a copy of the GNU General Public License version
19347 + * 2 along with this work; if not, write to the Free Software Foundation,
19348 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19350 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19351 + * or visit www.oracle.com if you need additional information or have any
19352 + * questions.
19353 + */
19355 +#define USE_ERROR
19356 +//#define USE_TRACE
19358 +#include "Ports.h"
19359 +#include "PLATFORM_API_SolarisOS_Utils.h"
19361 +#if USE_PORTS == TRUE
19363 +#define MONITOR_GAIN_STRING "Monitor Gain"
19365 +#define ALL_TARGET_PORT_COUNT 6
19367 +// define the following to not use audio_prinfo_t.mod_ports
19368 +#define SOLARIS7_COMPATIBLE
19370 +// Solaris audio defines
19371 +static int targetPorts[ALL_TARGET_PORT_COUNT] = {
19372 + AUDIO_SPEAKER,
19373 + AUDIO_HEADPHONE,
19374 + AUDIO_LINE_OUT,
19375 + AUDIO_AUX1_OUT,
19376 + AUDIO_AUX2_OUT,
19377 + AUDIO_SPDIF_OUT
19380 +static char* targetPortNames[ALL_TARGET_PORT_COUNT] = {
19381 + "Speaker",
19382 + "Headphone",
19383 + "Line Out",
19384 + "AUX1 Out",
19385 + "AUX2 Out",
19386 + "SPDIF Out"
19389 +// defined in Ports.h
19390 +static int targetPortJavaSoundMapping[ALL_TARGET_PORT_COUNT] = {
19391 + PORT_DST_SPEAKER,
19392 + PORT_DST_HEADPHONE,
19393 + PORT_DST_LINE_OUT,
19394 + PORT_DST_UNKNOWN,
19395 + PORT_DST_UNKNOWN,
19396 + PORT_DST_UNKNOWN,
19399 +#define ALL_SOURCE_PORT_COUNT 7
19401 +// Solaris audio defines
19402 +static int sourcePorts[ALL_SOURCE_PORT_COUNT] = {
19403 + AUDIO_MICROPHONE,
19404 + AUDIO_LINE_IN,
19405 + AUDIO_CD,
19406 + AUDIO_AUX1_IN,
19407 + AUDIO_AUX2_IN,
19408 + AUDIO_SPDIF_IN,
19409 + AUDIO_CODEC_LOOPB_IN
19412 +static char* sourcePortNames[ALL_SOURCE_PORT_COUNT] = {
19413 + "Microphone In",
19414 + "Line In",
19415 + "Compact Disc In",
19416 + "AUX1 In",
19417 + "AUX2 In",
19418 + "SPDIF In",
19419 + "Internal Loopback"
19422 +// Ports.h defines
19423 +static int sourcePortJavaSoundMapping[ALL_SOURCE_PORT_COUNT] = {
19424 + PORT_SRC_MICROPHONE,
19425 + PORT_SRC_LINE_IN,
19426 + PORT_SRC_COMPACT_DISC,
19427 + PORT_SRC_UNKNOWN,
19428 + PORT_SRC_UNKNOWN,
19429 + PORT_SRC_UNKNOWN,
19430 + PORT_SRC_UNKNOWN
19433 +struct tag_PortControlID;
19435 +typedef struct tag_PortInfo {
19436 + int fd; // file descriptor of the pseudo device
19437 + audio_info_t audioInfo;
19438 + // ports
19439 + int targetPortCount;
19440 + int sourcePortCount;
19441 + // indexes to sourcePorts/targetPorts
19442 + // contains first target ports, then source ports
19443 + int ports[ALL_TARGET_PORT_COUNT + ALL_SOURCE_PORT_COUNT];
19444 + // controls
19445 + int maxControlCount; // upper bound of number of controls
19446 + int usedControlIDs; // number of items already filled in controlIDs
19447 + struct tag_PortControlID* controlIDs; // the control IDs themselves
19448 +} PortInfo;
19450 +#define PORT_CONTROL_TYPE_PLAY 0x4000000
19451 +#define PORT_CONTROL_TYPE_RECORD 0x8000000
19452 +#define PORT_CONTROL_TYPE_SELECT_PORT 1
19453 +#define PORT_CONTROL_TYPE_GAIN 2
19454 +#define PORT_CONTROL_TYPE_BALANCE 3
19455 +#define PORT_CONTROL_TYPE_MONITOR_GAIN 10
19456 +#define PORT_CONTROL_TYPE_OUTPUT_MUTED 11
19457 +#define PORT_CONTROL_TYPE_PLAYRECORD_MASK PORT_CONTROL_TYPE_PLAY | PORT_CONTROL_TYPE_RECORD
19458 +#define PORT_CONTROL_TYPE_MASK 0xFFFFFF
19461 +typedef struct tag_PortControlID {
19462 + PortInfo* portInfo;
19463 + INT32 controlType; // PORT_CONTROL_TYPE_XX
19464 + uint_t port;
19465 +} PortControlID;
19468 +///// implemented functions of Ports.h
19470 +INT32 PORT_GetPortMixerCount() {
19471 + return (INT32) getAudioDeviceCount();
19475 +INT32 PORT_GetPortMixerDescription(INT32 mixerIndex, PortMixerDescription* description) {
19476 + AudioDeviceDescription desc;
19478 + if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, TRUE)) {
19479 + strncpy(description->name, desc.name, PORT_STRING_LENGTH-1);
19480 + description->name[PORT_STRING_LENGTH-1] = 0;
19481 + strncpy(description->vendor, desc.vendor, PORT_STRING_LENGTH-1);
19482 + description->vendor[PORT_STRING_LENGTH-1] = 0;
19483 + strncpy(description->version, desc.version, PORT_STRING_LENGTH-1);
19484 + description->version[PORT_STRING_LENGTH-1] = 0;
19485 + /*strncpy(description->description, desc.description, PORT_STRING_LENGTH-1);*/
19486 + strncpy(description->description, "Solaris Ports", PORT_STRING_LENGTH-1);
19487 + description->description[PORT_STRING_LENGTH-1] = 0;
19488 + return TRUE;
19490 + return FALSE;
19494 +void* PORT_Open(INT32 mixerIndex) {
19495 + PortInfo* info = NULL;
19496 + int fd = -1;
19497 + AudioDeviceDescription desc;
19498 + int success = FALSE;
19500 + TRACE0("PORT_Open\n");
19501 + if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, FALSE)) {
19502 + fd = open(desc.pathctl, O_RDWR);
19504 + if (fd < 0) {
19505 + ERROR1("Couldn't open audio device ctl for device %d!\n", mixerIndex);
19506 + return NULL;
19509 + info = (PortInfo*) malloc(sizeof(PortInfo));
19510 + if (info != NULL) {
19511 + memset(info, 0, sizeof(PortInfo));
19512 + info->fd = fd;
19513 + success = TRUE;
19515 + if (!success) {
19516 + if (fd >= 0) {
19517 + close(fd);
19519 + PORT_Close((void*) info);
19520 + info = NULL;
19522 + return info;
19525 +void PORT_Close(void* id) {
19526 + TRACE0("PORT_Close\n");
19527 + if (id != NULL) {
19528 + PortInfo* info = (PortInfo*) id;
19529 + if (info->fd >= 0) {
19530 + close(info->fd);
19531 + info->fd = -1;
19533 + if (info->controlIDs) {
19534 + free(info->controlIDs);
19535 + info->controlIDs = NULL;
19537 + free(info);
19543 +INT32 PORT_GetPortCount(void* id) {
19544 + int ret = 0;
19545 + PortInfo* info = (PortInfo*) id;
19546 + if (info != NULL) {
19547 + if (!info->targetPortCount && !info->sourcePortCount) {
19548 + int i;
19549 + AUDIO_INITINFO(&info->audioInfo);
19550 + if (ioctl(info->fd, AUDIO_GETINFO, &info->audioInfo) >= 0) {
19551 + for (i = 0; i < ALL_TARGET_PORT_COUNT; i++) {
19552 + if (info->audioInfo.play.avail_ports & targetPorts[i]) {
19553 + info->ports[info->targetPortCount] = i;
19554 + info->targetPortCount++;
19556 +#ifdef SOLARIS7_COMPATIBLE
19557 + TRACE3("Target %d %s: avail=%d\n", i, targetPortNames[i],
19558 + info->audioInfo.play.avail_ports & targetPorts[i]);
19559 +#else
19560 + TRACE4("Target %d %s: avail=%d mod=%d\n", i, targetPortNames[i],
19561 + info->audioInfo.play.avail_ports & targetPorts[i],
19562 + info->audioInfo.play.mod_ports & targetPorts[i]);
19563 +#endif
19565 + for (i = 0; i < ALL_SOURCE_PORT_COUNT; i++) {
19566 + if (info->audioInfo.record.avail_ports & sourcePorts[i]) {
19567 + info->ports[info->targetPortCount + info->sourcePortCount] = i;
19568 + info->sourcePortCount++;
19570 +#ifdef SOLARIS7_COMPATIBLE
19571 + TRACE3("Source %d %s: avail=%d\n", i, sourcePortNames[i],
19572 + info->audioInfo.record.avail_ports & sourcePorts[i]);
19573 +#else
19574 + TRACE4("Source %d %s: avail=%d mod=%d\n", i, sourcePortNames[i],
19575 + info->audioInfo.record.avail_ports & sourcePorts[i],
19576 + info->audioInfo.record.mod_ports & sourcePorts[i]);
19577 +#endif
19581 + ret = info->targetPortCount + info->sourcePortCount;
19583 + return ret;
19586 +int isSourcePort(PortInfo* info, INT32 portIndex) {
19587 + return (portIndex >= info->targetPortCount);
19590 +INT32 PORT_GetPortType(void* id, INT32 portIndex) {
19591 + PortInfo* info = (PortInfo*) id;
19592 + if ((portIndex >= 0) && (portIndex < PORT_GetPortCount(id))) {
19593 + if (isSourcePort(info, portIndex)) {
19594 + return sourcePortJavaSoundMapping[info->ports[portIndex]];
19595 + } else {
19596 + return targetPortJavaSoundMapping[info->ports[portIndex]];
19599 + return 0;
19602 +// pre-condition: portIndex must have been verified!
19603 +char* getPortName(PortInfo* info, INT32 portIndex) {
19604 + char* ret = NULL;
19606 + if (isSourcePort(info, portIndex)) {
19607 + ret = sourcePortNames[info->ports[portIndex]];
19608 + } else {
19609 + ret = targetPortNames[info->ports[portIndex]];
19611 + return ret;
19614 +INT32 PORT_GetPortName(void* id, INT32 portIndex, char* name, INT32 len) {
19615 + PortInfo* info = (PortInfo*) id;
19616 + char* n;
19618 + if ((portIndex >= 0) && (portIndex < PORT_GetPortCount(id))) {
19619 + n = getPortName(info, portIndex);
19620 + if (n) {
19621 + strncpy(name, n, len-1);
19622 + name[len-1] = 0;
19623 + return TRUE;
19626 + return FALSE;
19629 +void createPortControl(PortInfo* info, PortControlCreator* creator, INT32 portIndex,
19630 + INT32 type, void** controlObjects, int* controlCount) {
19631 + PortControlID* controlID;
19632 + void* newControl = NULL;
19633 + int controlIndex;
19634 + char* jsType = NULL;
19635 + int isBoolean = FALSE;
19637 + TRACE0(">createPortControl\n");
19639 + // fill the ControlID structure and add this control
19640 + if (info->usedControlIDs >= info->maxControlCount) {
19641 + ERROR1("not enough free controlIDs !! maxControlIDs = %d\n", info->maxControlCount);
19642 + return;
19644 + controlID = &(info->controlIDs[info->usedControlIDs]);
19645 + controlID->portInfo = info;
19646 + controlID->controlType = type;
19647 + controlIndex = info->ports[portIndex];
19648 + if (isSourcePort(info, portIndex)) {
19649 + controlID->port = sourcePorts[controlIndex];
19650 + } else {
19651 + controlID->port = targetPorts[controlIndex];
19653 + switch (type & PORT_CONTROL_TYPE_MASK) {
19654 + case PORT_CONTROL_TYPE_SELECT_PORT:
19655 + jsType = CONTROL_TYPE_SELECT; isBoolean = TRUE; break;
19656 + case PORT_CONTROL_TYPE_GAIN:
19657 + jsType = CONTROL_TYPE_VOLUME; break;
19658 + case PORT_CONTROL_TYPE_BALANCE:
19659 + jsType = CONTROL_TYPE_BALANCE; break;
19660 + case PORT_CONTROL_TYPE_MONITOR_GAIN:
19661 + jsType = CONTROL_TYPE_VOLUME; break;
19662 + case PORT_CONTROL_TYPE_OUTPUT_MUTED:
19663 + jsType = CONTROL_TYPE_MUTE; isBoolean = TRUE; break;
19665 + if (isBoolean) {
19666 + TRACE0(" PORT_CONTROL_TYPE_BOOLEAN\n");
19667 + newControl = (creator->newBooleanControl)(creator, controlID, jsType);
19669 + else if (jsType == CONTROL_TYPE_BALANCE) {
19670 + TRACE0(" PORT_CONTROL_TYPE_BALANCE\n");
19671 + newControl = (creator->newFloatControl)(creator, controlID, jsType,
19672 + -1.0f, 1.0f, 2.0f / 65.0f, "");
19673 + } else {
19674 + TRACE0(" PORT_CONTROL_TYPE_FLOAT\n");
19675 + newControl = (creator->newFloatControl)(creator, controlID, jsType,
19676 + 0.0f, 1.0f, 1.0f / 256.0f, "");
19678 + if (newControl) {
19679 + controlObjects[*controlCount] = newControl;
19680 + (*controlCount)++;
19681 + info->usedControlIDs++;
19683 + TRACE0("<createPortControl\n");
19687 +void addCompoundControl(PortInfo* info, PortControlCreator* creator, char* name, void** controlObjects, int* controlCount) {
19688 + void* compControl;
19690 + TRACE1(">addCompoundControl %d controls\n", *controlCount);
19691 + if (*controlCount) {
19692 + // create compound control and add it to the vector
19693 + compControl = (creator->newCompoundControl)(creator, name, controlObjects, *controlCount);
19694 + if (compControl) {
19695 + TRACE1(" addCompoundControl: calling addControl %p\n", compControl);
19696 + (creator->addControl)(creator, compControl);
19698 + *controlCount = 0;
19700 + TRACE0("<addCompoundControl\n");
19703 +void addAllControls(PortInfo* info, PortControlCreator* creator, void** controlObjects, int* controlCount) {
19704 + int i = 0;
19706 + TRACE0(">addAllControl\n");
19707 + // go through all controls and add them to the vector
19708 + for (i = 0; i < *controlCount; i++) {
19709 + (creator->addControl)(creator, controlObjects[i]);
19711 + *controlCount = 0;
19712 + TRACE0("<addAllControl\n");
19715 +void PORT_GetControls(void* id, INT32 portIndex, PortControlCreator* creator) {
19716 + PortInfo* info = (PortInfo*) id;
19717 + int portCount = PORT_GetPortCount(id);
19718 + void* controls[4];
19719 + int controlCount = 0;
19720 + INT32 type;
19721 + int selectable = 1;
19722 + memset(controls, 0, sizeof(controls));
19724 + TRACE4(">PORT_GetControls(id=%p, portIndex=%d). controlIDs=%p, maxControlCount=%d\n",
19725 + id, portIndex, info->controlIDs, info->maxControlCount);
19726 + if ((portIndex >= 0) && (portIndex < portCount)) {
19727 + // if the memory isn't reserved for the control structures, allocate it
19728 + if (!info->controlIDs) {
19729 + int maxCount = 0;
19730 + TRACE0("getControl: allocate mem\n");
19731 + // get a maximum number of controls:
19732 + // each port has a select, balance, and volume control.
19733 + maxCount = 3 * portCount;
19734 + // then there is monitorGain and outputMuted
19735 + maxCount += (2 * info->targetPortCount);
19736 + info->maxControlCount = maxCount;
19737 + info->controlIDs = (PortControlID*) malloc(sizeof(PortControlID) * maxCount);
19739 + if (!isSourcePort(info, portIndex)) {
19740 + type = PORT_CONTROL_TYPE_PLAY;
19741 + // add master mute control
19742 + createPortControl(info, creator, portIndex,
19743 + type | PORT_CONTROL_TYPE_OUTPUT_MUTED,
19744 + controls, &controlCount);
19745 + addAllControls(info, creator, controls, &controlCount);
19746 +#ifdef SOLARIS7_COMPATIBLE
19747 + selectable = info->audioInfo.play.avail_ports & targetPorts[info->ports[portIndex]];
19748 +#else
19749 + selectable = info->audioInfo.play.mod_ports & targetPorts[info->ports[portIndex]];
19750 +#endif
19751 + } else {
19752 + type = PORT_CONTROL_TYPE_RECORD;
19753 +#ifdef SOLARIS7_COMPATIBLE
19754 + selectable = info->audioInfo.record.avail_ports & sourcePorts[info->ports[portIndex]];
19755 +#else
19756 + selectable = info->audioInfo.record.mod_ports & sourcePorts[info->ports[portIndex]];
19757 +#endif
19759 + // add a mixer strip with volume, ...
19760 + createPortControl(info, creator, portIndex,
19761 + type | PORT_CONTROL_TYPE_GAIN,
19762 + controls, &controlCount);
19763 + // ... balance, ...
19764 + createPortControl(info, creator, portIndex,
19765 + type | PORT_CONTROL_TYPE_BALANCE,
19766 + controls, &controlCount);
19767 + // ... and select control (if not always on)...
19768 + if (selectable) {
19769 + createPortControl(info, creator, portIndex,
19770 + type | PORT_CONTROL_TYPE_SELECT_PORT,
19771 + controls, &controlCount);
19773 + // ... packaged in a compound control.
19774 + addCompoundControl(info, creator, getPortName(info, portIndex), controls, &controlCount);
19776 + if (type == PORT_CONTROL_TYPE_PLAY) {
19777 + // add a single strip for source ports with monitor gain
19778 + createPortControl(info, creator, portIndex,
19779 + type | PORT_CONTROL_TYPE_MONITOR_GAIN,
19780 + controls, &controlCount);
19781 + // also in a compound control
19782 + addCompoundControl(info, creator, MONITOR_GAIN_STRING, controls, &controlCount);
19785 + TRACE0("< PORT_getControls\n");
19788 +INT32 PORT_GetIntValue(void* controlIDV) {
19789 + PortControlID* controlID = (PortControlID*) controlIDV;
19790 + audio_info_t audioInfo;
19791 + audio_prinfo_t* prinfo;
19793 + AUDIO_INITINFO(&audioInfo);
19794 + if (ioctl(controlID->portInfo->fd, AUDIO_GETINFO, &audioInfo) >= 0) {
19795 + if (controlID->controlType & PORT_CONTROL_TYPE_PLAY) {
19796 + prinfo = &(audioInfo.play);
19797 + } else {
19798 + prinfo = &(audioInfo.record);
19800 + switch (controlID->controlType & PORT_CONTROL_TYPE_MASK) {
19801 + case PORT_CONTROL_TYPE_SELECT_PORT:
19802 + return (prinfo->port & controlID->port)?TRUE:FALSE;
19803 + case PORT_CONTROL_TYPE_OUTPUT_MUTED:
19804 + return (audioInfo.output_muted)?TRUE:FALSE;
19805 + default:
19806 + ERROR1("PORT_GetIntValue: Wrong type %d !\n", controlID->controlType & PORT_CONTROL_TYPE_MASK);
19809 + ERROR0("PORT_GetIntValue: Could not ioctl!\n");
19810 + return 0;
19813 +void PORT_SetIntValue(void* controlIDV, INT32 value) {
19814 + PortControlID* controlID = (PortControlID*) controlIDV;
19815 + audio_info_t audioInfo;
19816 + audio_prinfo_t* prinfo;
19817 + int setPort;
19819 + if (controlID->controlType & PORT_CONTROL_TYPE_PLAY) {
19820 + prinfo = &(audioInfo.play);
19821 + } else {
19822 + prinfo = &(audioInfo.record);
19824 + switch (controlID->controlType & PORT_CONTROL_TYPE_MASK) {
19825 + case PORT_CONTROL_TYPE_SELECT_PORT:
19826 + // first try to just add this port. if that fails, set ONLY to this port.
19827 + AUDIO_INITINFO(&audioInfo);
19828 + if (ioctl(controlID->portInfo->fd, AUDIO_GETINFO, &audioInfo) >= 0) {
19829 + if (value) {
19830 + setPort = (prinfo->port | controlID->port);
19831 + } else {
19832 + setPort = (prinfo->port - controlID->port);
19834 + AUDIO_INITINFO(&audioInfo);
19835 + prinfo->port = setPort;
19836 + if (ioctl(controlID->portInfo->fd, AUDIO_SETINFO, &audioInfo) < 0) {
19837 + // didn't work. Either this line doesn't support to select several
19838 + // ports at once (e.g. record), or a real error
19839 + if (value) {
19840 + // set to ONLY this port (and disable any other currently selected ports)
19841 + AUDIO_INITINFO(&audioInfo);
19842 + prinfo->port = controlID->port;
19843 + if (ioctl(controlID->portInfo->fd, AUDIO_SETINFO, &audioInfo) < 0) {
19844 + ERROR2("Error setting output select port %d to port %d!\n", controlID->port, controlID->port);
19846 + } else {
19847 + // assume it's an error
19848 + ERROR2("Error setting output select port %d to port %d!\n", controlID->port, setPort);
19851 + break;
19852 + case PORT_CONTROL_TYPE_OUTPUT_MUTED:
19853 + AUDIO_INITINFO(&audioInfo);
19854 + audioInfo.output_muted = (value?TRUE:FALSE);
19855 + if (ioctl(controlID->portInfo->fd, AUDIO_SETINFO, &audioInfo) < 0) {
19856 + ERROR2("Error setting output muted on port %d to %d!\n", controlID->port, value);
19858 + break;
19859 + default:
19860 + ERROR1("PORT_SetIntValue: Wrong type %d !\n", controlID->controlType & PORT_CONTROL_TYPE_MASK);
19865 +float PORT_GetFloatValue(void* controlIDV) {
19866 + PortControlID* controlID = (PortControlID*) controlIDV;
19867 + audio_info_t audioInfo;
19868 + audio_prinfo_t* prinfo;
19870 + AUDIO_INITINFO(&audioInfo);
19871 + if (ioctl(controlID->portInfo->fd, AUDIO_GETINFO, &audioInfo) >= 0) {
19872 + if (controlID->controlType & PORT_CONTROL_TYPE_PLAY) {
19873 + prinfo = &(audioInfo.play);
19874 + } else {
19875 + prinfo = &(audioInfo.record);
19877 + switch (controlID->controlType & PORT_CONTROL_TYPE_MASK) {
19878 + case PORT_CONTROL_TYPE_GAIN:
19879 + return ((float) (prinfo->gain - AUDIO_MIN_GAIN))
19880 + / ((float) (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN));
19881 + case PORT_CONTROL_TYPE_BALANCE:
19882 + return ((float) ((prinfo->balance - AUDIO_LEFT_BALANCE - AUDIO_MID_BALANCE) << 1))
19883 + / ((float) (AUDIO_RIGHT_BALANCE - AUDIO_LEFT_BALANCE));
19884 + case PORT_CONTROL_TYPE_MONITOR_GAIN:
19885 + return ((float) (audioInfo.monitor_gain - AUDIO_MIN_GAIN))
19886 + / ((float) (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN));
19887 + default:
19888 + ERROR1("PORT_GetFloatValue: Wrong type %d !\n", controlID->controlType & PORT_CONTROL_TYPE_MASK);
19891 + ERROR0("PORT_GetFloatValue: Could not ioctl!\n");
19892 + return 0.0f;
19895 +void PORT_SetFloatValue(void* controlIDV, float value) {
19896 + PortControlID* controlID = (PortControlID*) controlIDV;
19897 + audio_info_t audioInfo;
19898 + audio_prinfo_t* prinfo;
19900 + AUDIO_INITINFO(&audioInfo);
19902 + if (controlID->controlType & PORT_CONTROL_TYPE_PLAY) {
19903 + prinfo = &(audioInfo.play);
19904 + } else {
19905 + prinfo = &(audioInfo.record);
19907 + switch (controlID->controlType & PORT_CONTROL_TYPE_MASK) {
19908 + case PORT_CONTROL_TYPE_GAIN:
19909 + prinfo->gain = AUDIO_MIN_GAIN
19910 + + (int) ((value * ((float) (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN))) + 0.5f);
19911 + break;
19912 + case PORT_CONTROL_TYPE_BALANCE:
19913 + prinfo->balance = AUDIO_LEFT_BALANCE + AUDIO_MID_BALANCE
19914 + + ((int) (value * ((float) ((AUDIO_RIGHT_BALANCE - AUDIO_LEFT_BALANCE) >> 1))) + 0.5f);
19915 + break;
19916 + case PORT_CONTROL_TYPE_MONITOR_GAIN:
19917 + audioInfo.monitor_gain = AUDIO_MIN_GAIN
19918 + + (int) ((value * ((float) (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN))) + 0.5f);
19919 + break;
19920 + default:
19921 + ERROR1("PORT_SetFloatValue: Wrong type %d !\n", controlID->controlType & PORT_CONTROL_TYPE_MASK);
19922 + return;
19924 + if (ioctl(controlID->portInfo->fd, AUDIO_SETINFO, &audioInfo) < 0) {
19925 + ERROR0("PORT_SetFloatValue: Could not ioctl!\n");
19929 +#endif // USE_PORTS
19930 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Utils.c jdk22u-jdk-22.0.2-ga/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Utils.c
19931 --- jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Utils.c 1970-01-01 01:00:00.000000000 +0100
19932 +++ jdk22u-jdk-22.0.2-ga/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Utils.c 2024-08-17 19:34:03.919578145 +0200
19933 @@ -0,0 +1,193 @@
19935 + * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
19936 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
19938 + * This code is free software; you can redistribute it and/or modify it
19939 + * under the terms of the GNU General Public License version 2 only, as
19940 + * published by the Free Software Foundation. Oracle designates this
19941 + * particular file as subject to the "Classpath" exception as provided
19942 + * by Oracle in the LICENSE file that accompanied this code.
19944 + * This code is distributed in the hope that it will be useful, but WITHOUT
19945 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19946 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19947 + * version 2 for more details (a copy is included in the LICENSE file that
19948 + * accompanied this code).
19950 + * You should have received a copy of the GNU General Public License version
19951 + * 2 along with this work; if not, write to the Free Software Foundation,
19952 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19954 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19955 + * or visit www.oracle.com if you need additional information or have any
19956 + * questions.
19957 + */
19959 +#define USE_ERROR
19960 +#define USE_TRACE
19962 +#include "PLATFORM_API_SolarisOS_Utils.h"
19964 +#define MAX_AUDIO_DEVICES 20
19966 +// not thread safe...
19967 +static AudioDevicePath globalADPaths[MAX_AUDIO_DEVICES];
19968 +static int globalADCount = -1;
19969 +static int globalADCacheTime = -1;
19970 +/* how many seconds do we cache devices */
19971 +#define AD_CACHE_TIME 30
19973 +// return seconds
19974 +long getTimeInSeconds() {
19975 + struct timeval tv;
19976 + gettimeofday(&tv, NULL);
19977 + return tv.tv_sec;
19981 +int getAudioDeviceCount() {
19982 + int count = MAX_AUDIO_DEVICES;
19984 + getAudioDevices(globalADPaths, &count);
19985 + return count;
19988 +/* returns TRUE if the path exists at all */
19989 +int addAudioDevice(char* path, AudioDevicePath* adPath, int* count) {
19990 + int i;
19991 + int found = 0;
19992 + int fileExists = 0;
19993 + // not thread safe...
19994 + static struct stat statBuf;
19996 + // get stats on the file
19997 + if (stat(path, &statBuf) == 0) {
19998 + // file exists.
19999 + fileExists = 1;
20000 + // If it is not yet in the adPath array, add it to the array
20001 + for (i = 0; i < *count; i++) {
20002 + if (adPath[i].st_ino == statBuf.st_ino
20003 + && adPath[i].st_dev == statBuf.st_dev) {
20004 + found = 1;
20005 + break;
20008 + if (!found) {
20009 + adPath[*count].st_ino = statBuf.st_ino;
20010 + adPath[*count].st_dev = statBuf.st_dev;
20011 + strncpy(adPath[*count].path, path, MAX_NAME_LENGTH);
20012 + adPath[*count].path[MAX_NAME_LENGTH - 1] = 0;
20013 + (*count)++;
20014 + TRACE1("Added audio device %s\n", path);
20017 + return fileExists;
20021 +void getAudioDevices(AudioDevicePath* adPath, int* count) {
20022 + int maxCount = *count;
20023 + char* audiodev;
20024 + char devsound[15];
20025 + int i;
20026 + long timeInSeconds = getTimeInSeconds();
20028 + if (globalADCount < 0
20029 + || (getTimeInSeconds() - globalADCacheTime) > AD_CACHE_TIME
20030 + || (adPath != globalADPaths)) {
20031 + *count = 0;
20032 + // first device, if set, is AUDIODEV variable
20033 + audiodev = getenv("AUDIODEV");
20034 + if (audiodev != NULL && audiodev[0] != 0) {
20035 + addAudioDevice(audiodev, adPath, count);
20037 + // then try /dev/audio
20038 + addAudioDevice("/dev/audio", adPath, count);
20039 + // then go through all of the /dev/sound/? devices
20040 + for (i = 0; i < 100; i++) {
20041 + sprintf(devsound, "/dev/sound/%d", i);
20042 + if (!addAudioDevice(devsound, adPath, count)) {
20043 + break;
20046 + if (adPath == globalADPaths) {
20047 + /* commit cache */
20048 + globalADCount = *count;
20049 + /* set cache time */
20050 + globalADCacheTime = timeInSeconds;
20052 + } else {
20053 + /* return cache */
20054 + *count = globalADCount;
20056 + // that's it
20059 +int getAudioDeviceDescriptionByIndex(int index, AudioDeviceDescription* adDesc, int getNames) {
20060 + int count = MAX_AUDIO_DEVICES;
20061 + int ret = 0;
20063 + getAudioDevices(globalADPaths, &count);
20064 + if (index>=0 && index < count) {
20065 + ret = getAudioDeviceDescription(globalADPaths[index].path, adDesc, getNames);
20067 + return ret;
20070 +int getAudioDeviceDescription(char* path, AudioDeviceDescription* adDesc, int getNames) {
20071 + int fd;
20072 + int mixerMode;
20073 + int len;
20074 + audio_info_t info;
20075 + audio_device_t deviceInfo;
20077 + strncpy(adDesc->path, path, MAX_NAME_LENGTH);
20078 + adDesc->path[MAX_NAME_LENGTH] = 0;
20079 + strcpy(adDesc->pathctl, adDesc->path);
20080 + strcat(adDesc->pathctl, "ctl");
20081 + strcpy(adDesc->name, adDesc->path);
20082 + adDesc->vendor[0] = 0;
20083 + adDesc->version[0] = 0;
20084 + adDesc->description[0] = 0;
20085 + adDesc->maxSimulLines = 1;
20087 + // try to open the pseudo device and get more information
20088 + fd = open(adDesc->pathctl, O_WRONLY | O_NONBLOCK);
20089 + if (fd >= 0) {
20090 + close(fd);
20091 + if (getNames) {
20092 + fd = open(adDesc->pathctl, O_RDONLY);
20093 + if (fd >= 0) {
20094 + if (ioctl(fd, AUDIO_GETDEV, &deviceInfo) >= 0) {
20095 + strncpy(adDesc->vendor, deviceInfo.name, MAX_AUDIO_DEV_LEN);
20096 + adDesc->vendor[MAX_AUDIO_DEV_LEN] = 0;
20097 + strncpy(adDesc->version, deviceInfo.version, MAX_AUDIO_DEV_LEN);
20098 + adDesc->version[MAX_AUDIO_DEV_LEN] = 0;
20099 + /* add config string to the dev name
20100 + * creates a string like "/dev/audio (onboard1)"
20101 + */
20102 + len = strlen(adDesc->name) + 1;
20103 + if (MAX_NAME_LENGTH - len > 3) {
20104 + strcat(adDesc->name, " (");
20105 + strncat(adDesc->name, deviceInfo.config, MAX_NAME_LENGTH - len);
20106 + strcat(adDesc->name, ")");
20108 + adDesc->name[MAX_NAME_LENGTH-1] = 0;
20110 + if (ioctl(fd, AUDIO_MIXERCTL_GET_MODE, &mixerMode) >= 0) {
20111 + if (mixerMode == AM_MIXER_MODE) {
20112 + TRACE1(" getAudioDeviceDescription: %s is in mixer mode\n", adDesc->path);
20113 + adDesc->maxSimulLines = -1;
20115 + } else {
20116 + ERROR1("ioctl AUDIO_MIXERCTL_GET_MODE failed on %s!\n", adDesc->path);
20118 + close(fd);
20119 + } else {
20120 + ERROR1("could not open %s!\n", adDesc->pathctl);
20123 + return 1;
20125 + return 0;
20127 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Utils.h jdk22u-jdk-22.0.2-ga/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Utils.h
20128 --- jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Utils.h 1970-01-01 01:00:00.000000000 +0100
20129 +++ jdk22u-jdk-22.0.2-ga/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Utils.h 2024-08-17 19:34:03.919840905 +0200
20130 @@ -0,0 +1,97 @@
20132 + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
20133 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
20135 + * This code is free software; you can redistribute it and/or modify it
20136 + * under the terms of the GNU General Public License version 2 only, as
20137 + * published by the Free Software Foundation. Oracle designates this
20138 + * particular file as subject to the "Classpath" exception as provided
20139 + * by Oracle in the LICENSE file that accompanied this code.
20141 + * This code is distributed in the hope that it will be useful, but WITHOUT
20142 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20143 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20144 + * version 2 for more details (a copy is included in the LICENSE file that
20145 + * accompanied this code).
20147 + * You should have received a copy of the GNU General Public License version
20148 + * 2 along with this work; if not, write to the Free Software Foundation,
20149 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20151 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20152 + * or visit www.oracle.com if you need additional information or have any
20153 + * questions.
20154 + */
20156 +#include <Utilities.h>
20157 +#include <string.h>
20158 +#include <stdlib.h>
20159 +#include <fcntl.h>
20160 +/* does not work on Solaris 2.7 */
20161 +#include <sys/audio.h>
20162 +#include <sys/mixer.h>
20163 +#include <sys/types.h>
20164 +#ifndef __linux__
20165 +#include <stropts.h>
20166 +#endif
20167 +#include <sys/conf.h>
20168 +#include <sys/stat.h>
20169 +#include <unistd.h>
20171 +#ifndef PLATFORM_API_SOLARISOS_UTILS_H_INCLUDED
20172 +#define PLATFORM_API_SOLARISOS_UTILS_H_INCLUDED
20174 +/* defines for Solaris 2.7
20175 + #ifndef AUDIO_AUX1_OUT
20176 + #define AUDIO_AUX1_OUT (0x08) // output to aux1 out
20177 + #define AUDIO_AUX2_OUT (0x10) // output to aux2 out
20178 + #define AUDIO_SPDIF_OUT (0x20) // output to SPDIF port
20179 + #define AUDIO_AUX1_IN (0x08) // input from aux1 in
20180 + #define AUDIO_AUX2_IN (0x10) // input from aux2 in
20181 + #define AUDIO_SPDIF_IN (0x20) // input from SPDIF port
20182 + #endif
20185 +/* input from Codec inter. loopback */
20186 +#ifndef AUDIO_CODEC_LOOPB_IN
20187 +#define AUDIO_CODEC_LOOPB_IN (0x40)
20188 +#endif
20191 +#define MAX_NAME_LENGTH 300
20193 +typedef struct tag_AudioDevicePath {
20194 + char path[MAX_NAME_LENGTH];
20195 + ino_t st_ino; // inode number to detect duplicate devices
20196 + dev_t st_dev; // device ID to detect duplicate audio devices
20197 +} AudioDevicePath;
20199 +typedef struct tag_AudioDeviceDescription {
20200 + INT32 maxSimulLines;
20201 + char path[MAX_NAME_LENGTH+1];
20202 + char pathctl[MAX_NAME_LENGTH+4];
20203 + char name[MAX_NAME_LENGTH+1];
20204 + char vendor[MAX_NAME_LENGTH+1];
20205 + char version[MAX_NAME_LENGTH+1];
20206 + char description[MAX_NAME_LENGTH+1];
20207 +} AudioDeviceDescription;
20209 +int getAudioDeviceCount();
20212 + * adPath is an array of AudioDevicePath structures
20213 + * count contains initially the number of elements in adPath
20214 + * and will be set to the returned number of paths.
20215 + */
20216 +void getAudioDevices(AudioDevicePath* adPath, int* count);
20219 + * fills adDesc from the audio device given in path
20220 + * returns 0 if an error occurred
20221 + * if getNames is 0, only path and pathctl are filled
20222 + */
20223 +int getAudioDeviceDescription(char* path, AudioDeviceDescription* adDesc, int getNames);
20224 +int getAudioDeviceDescriptionByIndex(int index, AudioDeviceDescription* adDesc, int getNames);
20227 +#endif // PLATFORM_API_SOLARISOS_UTILS_H_INCLUDED
20228 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/unix/classes/sun/awt/X11FontManager.java jdk22u-jdk-22.0.2-ga/src/java.desktop/unix/classes/sun/awt/X11FontManager.java
20229 --- jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/unix/classes/sun/awt/X11FontManager.java 2024-06-04 18:47:50.000000000 +0200
20230 +++ jdk22u-jdk-22.0.2-ga/src/java.desktop/unix/classes/sun/awt/X11FontManager.java 2024-08-17 19:34:03.876497968 +0200
20231 @@ -686,7 +686,8 @@
20232 * and do the best we can.
20234 FontConfiguration mFontConfig = new MFontConfiguration(this);
20235 - if ((FontUtilities.isLinux && !mFontConfig.foundOsSpecificFile())) {
20236 + if ((FontUtilities.isLinux && !mFontConfig.foundOsSpecificFile()) ||
20237 + (FontUtilities.isSolaris && !mFontConfig.fontFilesArePresent())) {
20238 FcFontConfiguration fcFontConfig =
20239 new FcFontConfiguration(this);
20240 if (fcFontConfig.init()) {
20241 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/unix/classes/sun/font/MFontConfiguration.java jdk22u-jdk-22.0.2-ga/src/java.desktop/unix/classes/sun/font/MFontConfiguration.java
20242 --- jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/unix/classes/sun/font/MFontConfiguration.java 2024-06-04 18:47:50.000000000 +0200
20243 +++ jdk22u-jdk-22.0.2-ga/src/java.desktop/unix/classes/sun/font/MFontConfiguration.java 2024-08-17 19:34:03.877071255 +0200
20244 @@ -68,7 +68,59 @@
20246 protected void initReorderMap() {
20247 reorderMap = new HashMap<>();
20248 + if (osName == null) { /* null means SunOS */
20249 + initReorderMapForSolaris();
20250 + } else {
20251 + initReorderMapForLinux();
20255 + private void initReorderMapForSolaris() {
20256 + /* Don't create a no-op entry, so we can optimize this case
20257 + * i.e. we don't need to do anything so can avoid slower paths in
20258 + * the code.
20259 + */
20260 +// reorderMap.put("UTF-8", "latin-1");
20261 + reorderMap.put("UTF-8.hi", "devanagari"); // NB is in Lucida.
20262 + reorderMap.put("UTF-8.ja",
20263 + new String[] {"japanese-x0201", "japanese-x0208", "japanese-x0212"});
20264 + reorderMap.put("UTF-8.ko", "korean-johab");
20265 + reorderMap.put("UTF-8.th", "thai");
20266 + reorderMap.put("UTF-8.zh.TW", "chinese-big5");
20267 + reorderMap.put("UTF-8.zh.HK", new String[] {"chinese-big5", "chinese-hkscs"});
20268 + reorderMap.put("UTF-8.zh.CN",
20269 + new String[] {"chinese-gb18030-0", "chinese-gb18030-1"});
20270 + reorderMap.put("UTF-8.zh",
20271 + new String[] {"chinese-big5", "chinese-hkscs", "chinese-gb18030-0,chinese-gb18030-1"});
20272 + reorderMap.put("Big5", "chinese-big5");
20273 + reorderMap.put("Big5-HKSCS", new String[] {"chinese-big5", "chinese-hkscs"});
20274 + reorderMap.put("GB2312", new String[] {"chinese-gbk", "chinese-gb2312"});
20275 + reorderMap.put("x-EUC-TW",
20276 + new String[] {"chinese-cns11643-1", "chinese-cns11643-2", "chinese-cns11643-3"});
20277 + reorderMap.put("GBK", "chinese-gbk");
20278 + reorderMap.put("GB18030",new String[] {"chinese-gb18030-0", "chinese-gb18030-1"});
20280 + reorderMap.put("TIS-620", "thai");
20281 + reorderMap.put("x-PCK",
20282 + new String[] {"japanese-x0201", "japanese-x0208", "japanese-x0212"});
20283 + reorderMap.put("x-eucJP-Open",
20284 + new String[] {"japanese-x0201", "japanese-x0208", "japanese-x0212"});
20285 + reorderMap.put("EUC-KR", "korean");
20286 + /* Don't create a no-op entry, so we can optimize this case */
20287 +// reorderMap.put("ISO-8859-1", "latin-1");
20288 + reorderMap.put("ISO-8859-2", "latin-2");
20289 + reorderMap.put("ISO-8859-5", "cyrillic-iso8859-5");
20290 + reorderMap.put("windows-1251", "cyrillic-cp1251");
20291 + reorderMap.put("KOI8-R", "cyrillic-koi8-r");
20292 + reorderMap.put("ISO-8859-6", "arabic");
20293 + reorderMap.put("ISO-8859-7", "greek");
20294 + reorderMap.put("ISO-8859-8", "hebrew");
20295 + reorderMap.put("ISO-8859-9", "latin-5");
20296 + reorderMap.put("ISO-8859-13", "latin-7");
20297 + reorderMap.put("ISO-8859-15", "latin-9");
20300 + private void initReorderMapForLinux() {
20301 reorderMap.put("UTF-8.ja.JP", "japanese-iso10646");
20302 reorderMap.put("UTF-8.ko.KR", "korean-iso10646");
20303 reorderMap.put("UTF-8.zh.TW", "chinese-tw-iso10646");
20304 @@ -78,7 +130,12 @@
20305 reorderMap.put("GB2312", "chinese-gb18030");
20306 reorderMap.put("Big5", "chinese-big5");
20307 reorderMap.put("EUC-KR", "korean");
20308 - reorderMap.put("GB18030", "chinese-gb18030");
20309 + if (osName.equals("Sun")){
20310 + reorderMap.put("GB18030", "chinese-cn-iso10646");
20312 + else {
20313 + reorderMap.put("GB18030", "chinese-gb18030");
20318 @@ -87,7 +144,10 @@
20319 protected void setOsNameAndVersion(){
20320 super.setOsNameAndVersion();
20322 - if (osName.equals("Linux")) {
20323 + if (osName.equals("SunOS")) {
20324 + //don't care os name on Solaris
20325 + osName = null;
20326 + } else if (osName.equals("Linux")) {
20327 try {
20328 File f;
20329 if ((f = new File("/etc/fedora-release")).canRead()) {
20330 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java jdk22u-jdk-22.0.2-ga/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java
20331 --- jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java 2024-06-04 18:47:50.000000000 +0200
20332 +++ jdk22u-jdk-22.0.2-ga/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java 2024-08-17 19:34:03.877825186 +0200
20333 @@ -150,6 +150,10 @@
20334 return OSInfo.getOSType() == OSInfo.OSType.MACOSX;
20337 + static boolean isSysV() {
20338 + return OSInfo.getOSType() == OSInfo.OSType.SOLARIS;
20341 static boolean isLinux() {
20342 return OSInfo.getOSType() == OSInfo.OSType.LINUX;
20344 @@ -301,7 +305,7 @@
20347 } else {
20348 - if (isMac()) {
20349 + if (isMac() || isSysV()) {
20350 printers = getAllPrinterNamesSysV();
20351 } else if (isAIX()) {
20352 printers = getAllPrinterNamesAIX();
20353 @@ -485,7 +489,7 @@
20355 /* fallback if nothing not having a printer at this point */
20356 PrintService printer = null;
20357 - if (isMac()) {
20358 + if (isMac() || isSysV()) {
20359 printer = getNamedPrinterNameSysV(name);
20360 } else if (isAIX()) {
20361 printer = getNamedPrinterNameAIX(name);
20362 @@ -656,7 +660,7 @@
20363 psuri = printerInfo[1];
20365 } else {
20366 - if (isMac()) {
20367 + if (isMac() || isSysV()) {
20368 defaultPrinter = getDefaultPrinterNameSysV();
20369 } else if (isAIX()) {
20370 defaultPrinter = getDefaultPrinterNameAIX();
20371 @@ -876,7 +880,7 @@
20372 ArrayList<String> results = null;
20373 try {
20374 final String[] cmd = new String[3];
20375 - if (isAIX()) {
20376 + if (isSysV() || isAIX()) {
20377 cmd[0] = "/usr/bin/sh";
20378 cmd[1] = "-c";
20379 cmd[2] = "env LC_ALL=C " + command;
20380 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/unix/classes/sun/print/UnixPrintJob.java jdk22u-jdk-22.0.2-ga/src/java.desktop/unix/classes/sun/print/UnixPrintJob.java
20381 --- jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/unix/classes/sun/print/UnixPrintJob.java 2024-06-04 18:47:50.000000000 +0200
20382 +++ jdk22u-jdk-22.0.2-ga/src/java.desktop/unix/classes/sun/print/UnixPrintJob.java 2024-08-17 19:34:03.878367064 +0200
20383 @@ -872,25 +872,51 @@
20384 isAttributeCategorySupported(JobSheets.class)) {
20385 ncomps+=1;
20387 - execCmd = new String[ncomps];
20388 - execCmd[n++] = "/usr/bin/lpr";
20389 - if ((pFlags & PRINTER) != 0) {
20390 - execCmd[n++] = "-P" + printer;
20392 - if ((pFlags & JOBTITLE) != 0) {
20393 - execCmd[n++] = "-J " + jobTitle;
20395 - if ((pFlags & COPIES) != 0) {
20396 - execCmd[n++] = "-#" + copies;
20398 - if ((pFlags & NOSHEET) != 0) {
20399 - execCmd[n++] = "-h";
20400 - } else if (getPrintService().
20401 - isAttributeCategorySupported(JobSheets.class)) {
20402 - execCmd[n++] = "-o job-sheets=standard";
20404 - if ((pFlags & OPTIONS) != 0) {
20405 - execCmd[n++] = "-o" + options;
20406 + if (PrintServiceLookupProvider.isSysV()) {
20407 + ncomps+=1; // lp uses 1 more arg than lpr (make a copy)
20408 + execCmd = new String[ncomps];
20409 + execCmd[n++] = "/usr/bin/lp";
20410 + execCmd[n++] = "-c"; // make a copy of the spool file
20411 + if ((pFlags & PRINTER) != 0) {
20412 + execCmd[n++] = "-d" + printer;
20414 + if ((pFlags & JOBTITLE) != 0) {
20415 + String quoteChar = "\"";
20416 + execCmd[n++] = "-t " + quoteChar+jobTitle+quoteChar;
20418 + if ((pFlags & COPIES) != 0) {
20419 + execCmd[n++] = "-n " + copies;
20421 + if ((pFlags & NOSHEET) != 0) {
20422 + execCmd[n++] = "-o nobanner";
20423 + } else if (getPrintService().
20424 + isAttributeCategorySupported(JobSheets.class)) {
20425 + execCmd[n++] = "-o job-sheets=standard";
20427 + if ((pFlags & OPTIONS) != 0) {
20428 + execCmd[n++] = "-o " + options;
20430 + } else {
20431 + execCmd = new String[ncomps];
20432 + execCmd[n++] = "/usr/bin/lpr";
20433 + if ((pFlags & PRINTER) != 0) {
20434 + execCmd[n++] = "-P" + printer;
20436 + if ((pFlags & JOBTITLE) != 0) {
20437 + execCmd[n++] = "-J " + jobTitle;
20439 + if ((pFlags & COPIES) != 0) {
20440 + execCmd[n++] = "-#" + copies;
20442 + if ((pFlags & NOSHEET) != 0) {
20443 + execCmd[n++] = "-h";
20444 + } else if (getPrintService().
20445 + isAttributeCategorySupported(JobSheets.class)) {
20446 + execCmd[n++] = "-o job-sheets=standard";
20448 + if ((pFlags & OPTIONS) != 0) {
20449 + execCmd[n++] = "-o" + options;
20452 execCmd[n++] = spoolFile;
20453 if (IPPPrintService.debugPrint) {
20454 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/unix/classes/sun/print/UnixPrintService.java jdk22u-jdk-22.0.2-ga/src/java.desktop/unix/classes/sun/print/UnixPrintService.java
20455 --- jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/unix/classes/sun/print/UnixPrintService.java 2024-06-04 18:47:50.000000000 +0200
20456 +++ jdk22u-jdk-22.0.2-ga/src/java.desktop/unix/classes/sun/print/UnixPrintService.java 2024-08-17 19:34:03.879626157 +0200
20457 @@ -220,6 +220,31 @@
20458 return name;
20461 + private PrinterIsAcceptingJobs getPrinterIsAcceptingJobsSysV() {
20462 + String command = "/usr/bin/lpstat -a " + printer;
20463 + String[] results= PrintServiceLookupProvider.execCmd(command);
20465 + if (results != null && results.length > 0) {
20466 + if (results[0].startsWith(printer + " accepting requests")) {
20467 + return PrinterIsAcceptingJobs.ACCEPTING_JOBS;
20469 + else if (results[0].startsWith(printer)) {
20470 + /* As well as "myprinter accepting requests", look for
20471 + * "myprinter@somehost accepting requests".
20472 + */
20473 + int index = printer.length();
20474 + String str = results[0];
20475 + if (str.length() > index &&
20476 + str.charAt(index) == '@' &&
20477 + str.indexOf(" accepting requests", index) > 0 &&
20478 + str.indexOf(" not accepting requests", index) == -1) {
20479 + return PrinterIsAcceptingJobs.ACCEPTING_JOBS;
20483 + return PrinterIsAcceptingJobs.NOT_ACCEPTING_JOBS ;
20486 private PrinterIsAcceptingJobs getPrinterIsAcceptingJobsBSD() {
20487 if (PrintServiceLookupProvider.cmdIndex ==
20488 PrintServiceLookupProvider.UNINITIALIZED) {
20489 @@ -297,7 +322,9 @@
20492 private PrinterIsAcceptingJobs getPrinterIsAcceptingJobs() {
20493 - if (PrintServiceLookupProvider.isBSD()) {
20494 + if (PrintServiceLookupProvider.isSysV()) {
20495 + return getPrinterIsAcceptingJobsSysV();
20496 + } else if (PrintServiceLookupProvider.isBSD()) {
20497 return getPrinterIsAcceptingJobsBSD();
20498 } else if (PrintServiceLookupProvider.isAIX()) {
20499 return getPrinterIsAcceptingJobsAIX();
20500 @@ -324,6 +351,14 @@
20504 + private QueuedJobCount getQueuedJobCountSysV() {
20505 + String command = "/usr/bin/lpstat -R " + printer;
20506 + String[] results= PrintServiceLookupProvider.execCmd(command);
20507 + int qlen = (results == null) ? 0 : results.length;
20509 + return new QueuedJobCount(qlen);
20512 private QueuedJobCount getQueuedJobCountBSD() {
20513 if (PrintServiceLookupProvider.cmdIndex ==
20514 PrintServiceLookupProvider.UNINITIALIZED) {
20515 @@ -380,7 +415,9 @@
20518 private QueuedJobCount getQueuedJobCount() {
20519 - if (PrintServiceLookupProvider.isBSD()) {
20520 + if (PrintServiceLookupProvider.isSysV()) {
20521 + return getQueuedJobCountSysV();
20522 + } else if (PrintServiceLookupProvider.isBSD()) {
20523 return getQueuedJobCountBSD();
20524 } else if (PrintServiceLookupProvider.isAIX()) {
20525 return getQueuedJobCountAIX();
20526 @@ -389,6 +426,13 @@
20530 + private PrintServiceAttributeSet getSysVServiceAttributes() {
20531 + PrintServiceAttributeSet attrs = new HashPrintServiceAttributeSet();
20532 + attrs.add(getQueuedJobCountSysV());
20533 + attrs.add(getPrinterIsAcceptingJobsSysV());
20534 + return attrs;
20537 private PrintServiceAttributeSet getBSDServiceAttributes() {
20538 PrintServiceAttributeSet attrs = new HashPrintServiceAttributeSet();
20539 attrs.add(getQueuedJobCountBSD());
20540 @@ -427,7 +471,9 @@
20543 private PrintServiceAttributeSet getDynamicAttributes() {
20544 - if (PrintServiceLookupProvider.isAIX()) {
20545 + if (PrintServiceLookupProvider.isSysV()) {
20546 + return getSysVServiceAttributes();
20547 + } else if (PrintServiceLookupProvider.isAIX()) {
20548 return getAIXServiceAttributes();
20549 } else {
20550 return getBSDServiceAttributes();
20551 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/unix/native/common/awt/fontpath.c jdk22u-jdk-22.0.2-ga/src/java.desktop/unix/native/common/awt/fontpath.c
20552 --- jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/unix/native/common/awt/fontpath.c 2024-06-04 18:47:50.000000000 +0200
20553 +++ jdk22u-jdk-22.0.2-ga/src/java.desktop/unix/native/common/awt/fontpath.c 2024-08-17 19:34:03.880348835 +0200
20554 @@ -57,7 +57,57 @@
20556 #define MAXFDIRS 512 /* Max number of directories that contain fonts */
20558 -#if defined( __linux__)
20559 +#if defined(__solaris__)
20561 + * This can be set in the makefile to "/usr/X11" if so desired.
20562 + */
20563 +#ifndef OPENWINHOMELIB
20564 +#define OPENWINHOMELIB "/usr/openwin/lib/"
20565 +#endif
20567 +/* This is all known Solaris X11 directories on Solaris 8, 9 and 10.
20568 + * It is ordered to give precedence to TrueType directories.
20569 + * It is needed if fontconfig is not installed or configured properly.
20570 + */
20571 +static char *fullSolarisFontPath[] = {
20572 + OPENWINHOMELIB "X11/fonts/TrueType",
20573 + OPENWINHOMELIB "locale/euro_fonts/X11/fonts/TrueType",
20574 + OPENWINHOMELIB "locale/iso_8859_2/X11/fonts/TrueType",
20575 + OPENWINHOMELIB "locale/iso_8859_5/X11/fonts/TrueType",
20576 + OPENWINHOMELIB "locale/iso_8859_7/X11/fonts/TrueType",
20577 + OPENWINHOMELIB "locale/iso_8859_8/X11/fonts/TrueType",
20578 + OPENWINHOMELIB "locale/iso_8859_9/X11/fonts/TrueType",
20579 + OPENWINHOMELIB "locale/iso_8859_13/X11/fonts/TrueType",
20580 + OPENWINHOMELIB "locale/iso_8859_15/X11/fonts/TrueType",
20581 + OPENWINHOMELIB "locale/ar/X11/fonts/TrueType",
20582 + OPENWINHOMELIB "locale/hi_IN.UTF-8/X11/fonts/TrueType",
20583 + OPENWINHOMELIB "locale/ja/X11/fonts/TT",
20584 + OPENWINHOMELIB "locale/ko/X11/fonts/TrueType",
20585 + OPENWINHOMELIB "locale/ko.UTF-8/X11/fonts/TrueType",
20586 + OPENWINHOMELIB "locale/KOI8-R/X11/fonts/TrueType",
20587 + OPENWINHOMELIB "locale/ru.ansi-1251/X11/fonts/TrueType",
20588 + OPENWINHOMELIB "locale/th_TH/X11/fonts/TrueType",
20589 + OPENWINHOMELIB "locale/zh_TW/X11/fonts/TrueType",
20590 + OPENWINHOMELIB "locale/zh_TW.BIG5/X11/fonts/TT",
20591 + OPENWINHOMELIB "locale/zh_HK.BIG5HK/X11/fonts/TT",
20592 + OPENWINHOMELIB "locale/zh_CN.GB18030/X11/fonts/TrueType",
20593 + OPENWINHOMELIB "locale/zh/X11/fonts/TrueType",
20594 + OPENWINHOMELIB "locale/zh.GBK/X11/fonts/TrueType",
20595 + OPENWINHOMELIB "X11/fonts/Type1",
20596 + OPENWINHOMELIB "X11/fonts/Type1/sun",
20597 + OPENWINHOMELIB "X11/fonts/Type1/sun/outline",
20598 + OPENWINHOMELIB "locale/iso_8859_2/X11/fonts/Type1",
20599 + OPENWINHOMELIB "locale/iso_8859_4/X11/fonts/Type1",
20600 + OPENWINHOMELIB "locale/iso_8859_5/X11/fonts/Type1",
20601 + OPENWINHOMELIB "locale/iso_8859_7/X11/fonts/Type1",
20602 + OPENWINHOMELIB "locale/iso_8859_8/X11/fonts/Type1",
20603 + OPENWINHOMELIB "locale/iso_8859_9/X11/fonts/Type1",
20604 + OPENWINHOMELIB "locale/iso_8859_13/X11/fonts/Type1",
20605 + OPENWINHOMELIB "locale/ar/X11/fonts/Type1",
20606 + NULL, /* terminates the list */
20609 +#elif defined( __linux__)
20610 /* All the known interesting locations we have discovered on
20611 * various flavors of Linux
20613 @@ -173,6 +223,14 @@
20614 if (strstr(x11Path[i], ".gnome") != NULL) {
20615 continue;
20617 +#ifdef __solaris__
20618 + if (strstr(x11Path[i], "/F3/") != NULL) {
20619 + continue;
20621 + if (strstr(x11Path[i], "bitmap") != NULL) {
20622 + continue;
20624 +#endif
20625 fontdirs[pos] = strdup(x11Path[i]);
20626 slen = strlen(fontdirs[pos]);
20627 if (slen > 0 && fontdirs[pos][slen-1] == '/') {
20628 @@ -322,6 +380,8 @@
20630 #if defined(__linux__)
20631 knowndirs = fullLinuxFontPath;
20632 +#elif defined(__solaris__)
20633 + knowndirs = fullSolarisFontPath;
20634 #elif defined(_AIX)
20635 knowndirs = fullAixFontPath;
20636 #endif
20637 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c jdk22u-jdk-22.0.2-ga/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c
20638 --- jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c 2024-06-04 18:47:50.000000000 +0200
20639 +++ jdk22u-jdk-22.0.2-ga/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c 2024-08-17 19:34:03.881063591 +0200
20640 @@ -402,7 +402,12 @@
20641 xrenderLibHandle = dlopen("libXrender.so", RTLD_LAZY | RTLD_GLOBAL);
20644 -#if defined(_AIX)
20645 +#if defined(__solaris__)
20646 + if (xrenderLibHandle == NULL) {
20647 + xrenderLibHandle = dlopen("libXrender.so.1",
20648 + RTLD_LAZY | RTLD_GLOBAL);
20650 +#elif defined(_AIX)
20651 if (xrenderLibHandle == NULL) {
20652 xrenderLibHandle = dlopen("libXrender.a(libXrender.so.0)",
20653 RTLD_MEMBER | RTLD_LAZY | RTLD_GLOBAL);
20654 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/unix/native/libawt_xawt/java2d/x11/XRBackendNative.c jdk22u-jdk-22.0.2-ga/src/java.desktop/unix/native/libawt_xawt/java2d/x11/XRBackendNative.c
20655 --- jdk22u-jdk-22.0.2-ga.orig/src/java.desktop/unix/native/libawt_xawt/java2d/x11/XRBackendNative.c 2024-06-04 18:47:50.000000000 +0200
20656 +++ jdk22u-jdk-22.0.2-ga/src/java.desktop/unix/native/libawt_xawt/java2d/x11/XRBackendNative.c 2024-08-17 19:34:03.881799638 +0200
20657 @@ -61,6 +61,29 @@
20659 #include <dlfcn.h>
20661 +#if defined(__solaris__)
20662 +/* Solaris 10 will not have these symbols at compile time */
20664 +typedef Picture (*XRenderCreateLinearGradientFuncType)
20665 + (Display *dpy,
20666 + const XLinearGradient *gradient,
20667 + const XFixed *stops,
20668 + const XRenderColor *colors,
20669 + int nstops);
20671 +typedef Picture (*XRenderCreateRadialGradientFuncType)
20672 + (Display *dpy,
20673 + const XRadialGradient *gradient,
20674 + const XFixed *stops,
20675 + const XRenderColor *colors,
20676 + int nstops);
20678 +static
20679 +XRenderCreateLinearGradientFuncType XRenderCreateLinearGradientFunc = NULL;
20680 +static
20681 + XRenderCreateRadialGradientFuncType XRenderCreateRadialGradientFunc = NULL;
20682 +#endif
20684 #define BUILD_TRANSFORM_MATRIX(TRANSFORM, M00, M01, M02, M10, M11, M12) \
20686 TRANSFORM.matrix[0][0] = M00; \
20687 @@ -128,6 +151,27 @@
20688 } else {
20689 available = JNI_FALSE;
20691 +#elif defined(__solaris__)
20692 + xrenderlib = dlopen("libXrender.so",RTLD_GLOBAL|RTLD_LAZY);
20693 + if (xrenderlib != NULL) {
20695 + XRenderCreateLinearGradientFunc =
20696 + (XRenderCreateLinearGradientFuncType)
20697 + dlsym(xrenderlib, "XRenderCreateLinearGradient");
20699 + XRenderCreateRadialGradientFunc =
20700 + (XRenderCreateRadialGradientFuncType)
20701 + dlsym(xrenderlib, "XRenderCreateRadialGradient");
20703 + if (XRenderCreateLinearGradientFunc == NULL ||
20704 + XRenderCreateRadialGradientFunc == NULL)
20706 + available = JNI_FALSE;
20708 + dlclose(xrenderlib);
20709 + } else {
20710 + available = JNI_FALSE;
20712 #else
20713 Dl_info info;
20714 jboolean versionInfoIsFound = JNI_FALSE;
20715 @@ -534,7 +578,13 @@
20716 colors[i].green = pixels[i*4 + 2];
20717 colors[i].blue = pixels[i*4 + 3];
20719 +#ifdef __solaris__
20720 + if (XRenderCreateLinearGradientFunc!=NULL) {
20721 + gradient = (*XRenderCreateLinearGradientFunc)(awt_display, &grad, stops, colors, numStops);
20723 +#else
20724 gradient = XRenderCreateLinearGradient(awt_display, &grad, stops, colors, numStops);
20725 +#endif
20726 free(colors);
20727 free(stops);
20729 @@ -612,7 +662,13 @@
20730 colors[i].green = pixels[i*4 + 2];
20731 colors[i].blue = pixels[i*4 + 3];
20733 +#ifdef __solaris__
20734 + if (XRenderCreateRadialGradientFunc != NULL) {
20735 + gradient = (jint) (*XRenderCreateRadialGradientFunc)(awt_display, &grad, stops, colors, numStops);
20737 +#else
20738 gradient = (jint) XRenderCreateRadialGradient(awt_display, &grad, stops, colors, numStops);
20739 +#endif
20740 free(colors);
20741 free(stops);
20743 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/SunNativeProvider.java jdk22u-jdk-22.0.2-ga/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/SunNativeProvider.java
20744 --- jdk22u-jdk-22.0.2-ga.orig/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/SunNativeProvider.java 2024-06-04 18:47:50.000000000 +0200
20745 +++ jdk22u-jdk-22.0.2-ga/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/SunNativeProvider.java 2024-08-17 19:34:03.882308041 +0200
20746 @@ -91,6 +91,9 @@
20747 = System.getProperty("sun.security.jgss.lib");
20748 if (defaultLib == null || defaultLib.trim().equals("")) {
20749 gssLibs = switch (OperatingSystem.current()) {
20750 + case SOLARIS -> new String[]{
20751 + "libgss.so",
20752 + };
20753 case LINUX -> new String[]{
20754 "libgssapi.so",
20755 "libgssapi_krb5.so",
20756 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.security.jgss/share/classes/sun/security/krb5/Config.java jdk22u-jdk-22.0.2-ga/src/java.security.jgss/share/classes/sun/security/krb5/Config.java
20757 --- jdk22u-jdk-22.0.2-ga.orig/src/java.security.jgss/share/classes/sun/security/krb5/Config.java 2024-06-04 18:47:50.000000000 +0200
20758 +++ jdk22u-jdk-22.0.2-ga/src/java.security.jgss/share/classes/sun/security/krb5/Config.java 2024-08-17 19:34:03.882940662 +0200
20759 @@ -930,6 +930,8 @@
20760 if (name == null) {
20761 name = "c:\\winnt\\krb5.ini";
20763 + } else if (OperatingSystem.isSolaris()) {
20764 + name = "/etc/krb5/krb5.conf";
20765 } else if (OperatingSystem.isMacOS()) {
20766 name = findMacosConfigFile();
20767 } else {
20768 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/DflCache.java jdk22u-jdk-22.0.2-ga/src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/DflCache.java
20769 --- jdk22u-jdk-22.0.2-ga.orig/src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/DflCache.java 2024-06-04 18:47:50.000000000 +0200
20770 +++ jdk22u-jdk-22.0.2-ga/src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/DflCache.java 2024-08-17 19:34:03.883370104 +0200
20771 @@ -107,7 +107,7 @@
20773 private static long uid;
20774 static {
20775 - // Available on Linux and Mac. Otherwise, -1 and no _euid suffix
20776 + // Available on Solaris, Linux and Mac. Otherwise, -1 and no _euid suffix
20777 uid = jdk.internal.misc.VM.geteuid();
20780 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.smartcardio/unix/classes/sun/security/smartcardio/PlatformPCSC.java jdk22u-jdk-22.0.2-ga/src/java.smartcardio/unix/classes/sun/security/smartcardio/PlatformPCSC.java
20781 --- jdk22u-jdk-22.0.2-ga.orig/src/java.smartcardio/unix/classes/sun/security/smartcardio/PlatformPCSC.java 2024-06-04 18:47:50.000000000 +0200
20782 +++ jdk22u-jdk-22.0.2-ga/src/java.smartcardio/unix/classes/sun/security/smartcardio/PlatformPCSC.java 2024-08-17 19:34:03.883826228 +0200
20783 @@ -86,8 +86,12 @@
20784 if (k != -1) {
20785 String libDir;
20786 if ("64".equals(System.getProperty("sun.arch.data.model"))) {
20787 - // assume Linux convention
20788 - libDir = "lib64";
20789 + if ("SunOS".equals(System.getProperty("os.name"))) {
20790 + libDir = "lib/64";
20791 + } else {
20792 + // assume Linux convention
20793 + libDir = "lib64";
20795 } else {
20796 // must be 32-bit
20797 libDir = "lib";
20798 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/output/WriterOutputBuffer.java jdk22u-jdk-22.0.2-ga/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/output/WriterOutputBuffer.java
20799 --- jdk22u-jdk-22.0.2-ga.orig/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/output/WriterOutputBuffer.java 2024-06-04 18:47:50.000000000 +0200
20800 +++ jdk22u-jdk-22.0.2-ga/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/output/WriterOutputBuffer.java 2024-08-17 19:34:03.884341242 +0200
20801 @@ -33,12 +33,21 @@
20802 private static final int KB = 1024;
20803 private static int BUFFER_SIZE = 4 * KB;
20805 + static {
20806 + // Set a larger buffer size for Solaris
20807 + final String osName = SecuritySupport.getSystemProperty("os.name");
20808 + if (osName.equalsIgnoreCase("solaris")) {
20809 + BUFFER_SIZE = 32 * KB;
20813 private Writer _writer;
20816 * Initializes a WriterOutputBuffer by creating an instance of a
20817 * BufferedWriter. The size of the buffer in this writer may have
20818 - * a significant impact on throughput.
20819 + * a significant impact on throughput. Solaris prefers a larger
20820 + * buffer, while Linux works better with a smaller one.
20822 public WriterOutputBuffer(Writer writer) {
20823 _writer = new BufferedWriter(writer, BUFFER_SIZE);
20824 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/jdk.attach/solaris/classes/sun/tools/attach/AttachProviderImpl.java jdk22u-jdk-22.0.2-ga/src/jdk.attach/solaris/classes/sun/tools/attach/AttachProviderImpl.java
20825 --- jdk22u-jdk-22.0.2-ga.orig/src/jdk.attach/solaris/classes/sun/tools/attach/AttachProviderImpl.java 1970-01-01 01:00:00.000000000 +0100
20826 +++ jdk22u-jdk-22.0.2-ga/src/jdk.attach/solaris/classes/sun/tools/attach/AttachProviderImpl.java 2024-08-17 19:34:03.920366721 +0200
20827 @@ -0,0 +1,79 @@
20829 + * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
20830 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
20832 + * This code is free software; you can redistribute it and/or modify it
20833 + * under the terms of the GNU General Public License version 2 only, as
20834 + * published by the Free Software Foundation. Oracle designates this
20835 + * particular file as subject to the "Classpath" exception as provided
20836 + * by Oracle in the LICENSE file that accompanied this code.
20838 + * This code is distributed in the hope that it will be useful, but WITHOUT
20839 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20840 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20841 + * version 2 for more details (a copy is included in the LICENSE file that
20842 + * accompanied this code).
20844 + * You should have received a copy of the GNU General Public License version
20845 + * 2 along with this work; if not, write to the Free Software Foundation,
20846 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20848 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20849 + * or visit www.oracle.com if you need additional information or have any
20850 + * questions.
20851 + */
20852 +package sun.tools.attach;
20854 +import com.sun.tools.attach.VirtualMachine;
20855 +import com.sun.tools.attach.VirtualMachineDescriptor;
20856 +import com.sun.tools.attach.AttachNotSupportedException;
20857 +import java.io.IOException;
20860 + * An AttachProvider implementation for Solaris that use the doors
20861 + * interface to the VM.
20862 + */
20863 +public class AttachProviderImpl extends HotSpotAttachProvider {
20865 + public AttachProviderImpl() {
20868 + public String name() {
20869 + return "sun";
20872 + public String type() {
20873 + return "doors";
20876 + public VirtualMachine attachVirtualMachine(String vmid)
20877 + throws AttachNotSupportedException, IOException
20879 + checkAttachPermission();
20881 + // AttachNotSupportedException will be thrown if the target VM can be determined
20882 + // to be not attachable.
20883 + testAttachable(vmid);
20885 + return new VirtualMachineImpl(this, vmid);
20888 + public VirtualMachine attachVirtualMachine(VirtualMachineDescriptor vmd)
20889 + throws AttachNotSupportedException, IOException
20891 + if (vmd.provider() != this) {
20892 + throw new AttachNotSupportedException("provider mismatch");
20894 + // To avoid re-checking if the VM if attachable, we check if the descriptor
20895 + // is for a hotspot VM - these descriptors are created by the listVirtualMachines
20896 + // implementation which only returns a list of attachable VMs.
20897 + if (vmd instanceof HotSpotVirtualMachineDescriptor) {
20898 + assert ((HotSpotVirtualMachineDescriptor)vmd).isAttachable();
20899 + checkAttachPermission();
20900 + return new VirtualMachineImpl(this, vmd.id());
20901 + } else {
20902 + return attachVirtualMachine(vmd.id());
20907 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/jdk.attach/solaris/classes/sun/tools/attach/VirtualMachineImpl.java jdk22u-jdk-22.0.2-ga/src/jdk.attach/solaris/classes/sun/tools/attach/VirtualMachineImpl.java
20908 --- jdk22u-jdk-22.0.2-ga.orig/src/jdk.attach/solaris/classes/sun/tools/attach/VirtualMachineImpl.java 1970-01-01 01:00:00.000000000 +0100
20909 +++ jdk22u-jdk-22.0.2-ga/src/jdk.attach/solaris/classes/sun/tools/attach/VirtualMachineImpl.java 2024-08-17 19:34:03.920719238 +0200
20910 @@ -0,0 +1,272 @@
20912 + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
20913 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
20915 + * This code is free software; you can redistribute it and/or modify it
20916 + * under the terms of the GNU General Public License version 2 only, as
20917 + * published by the Free Software Foundation. Oracle designates this
20918 + * particular file as subject to the "Classpath" exception as provided
20919 + * by Oracle in the LICENSE file that accompanied this code.
20921 + * This code is distributed in the hope that it will be useful, but WITHOUT
20922 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20923 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20924 + * version 2 for more details (a copy is included in the LICENSE file that
20925 + * accompanied this code).
20927 + * You should have received a copy of the GNU General Public License version
20928 + * 2 along with this work; if not, write to the Free Software Foundation,
20929 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20931 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20932 + * or visit www.oracle.com if you need additional information or have any
20933 + * questions.
20934 + */
20935 +package sun.tools.attach;
20937 +import com.sun.tools.attach.AttachOperationFailedException;
20938 +import com.sun.tools.attach.AgentLoadException;
20939 +import com.sun.tools.attach.AttachNotSupportedException;
20940 +import com.sun.tools.attach.spi.AttachProvider;
20942 +import java.io.InputStream;
20943 +import java.io.IOException;
20944 +import java.io.File;
20945 +import java.io.FileNotFoundException;
20948 + * Solaris implementation of HotSpotVirtualMachine.
20949 + */
20950 +public class VirtualMachineImpl extends HotSpotVirtualMachine {
20951 + // "/tmp" is used as a global well-known location for the files
20952 + // .java_pid<pid>. and .attach_pid<pid>. It is important that this
20953 + // location is the same for all processes, otherwise the tools
20954 + // will not be able to find all Hotspot processes.
20955 + // Any changes to this needs to be synchronized with HotSpot.
20956 + private static final String tmpdir = "/tmp";
20958 + // door descriptor;
20959 + private int fd = -1;
20960 + String socket_path;
20962 + /**
20963 + * Attaches to the target VM
20964 + */
20965 + VirtualMachineImpl(AttachProvider provider, String vmid)
20966 + throws AttachNotSupportedException, IOException
20968 + super(provider, vmid);
20969 + // This provider only understands process-ids (pids).
20970 + int pid;
20971 + try {
20972 + pid = Integer.parseInt(vmid);
20973 + if (pid < 1) {
20974 + throw new NumberFormatException();
20976 + } catch (NumberFormatException x) {
20977 + throw new AttachNotSupportedException("Invalid process identifier: " + vmid);
20980 + // Opens the door file to the target VM. If the file is not
20981 + // found it might mean that the attach mechanism isn't started in the
20982 + // target VM so we attempt to start it and retry.
20983 + try {
20984 + fd = openDoor(pid);
20985 + } catch (FileNotFoundException fnf1) {
20986 + File f = createAttachFile(pid);
20987 + try {
20988 + sigquit(pid);
20990 + // give the target VM time to start the attach mechanism
20991 + final int delay_step = 100;
20992 + final long timeout = attachTimeout();
20993 + long time_spend = 0;
20994 + long delay = 0;
20995 + do {
20996 + // Increase timeout on each attempt to reduce polling
20997 + delay += delay_step;
20998 + try {
20999 + Thread.sleep(delay);
21000 + } catch (InterruptedException x) { }
21001 + try {
21002 + fd = openDoor(pid);
21003 + } catch (FileNotFoundException fnf2) {
21004 + // pass
21007 + time_spend += delay;
21008 + if (time_spend > timeout/2 && fd == -1) {
21009 + // Send QUIT again to give target VM the last chance to react
21010 + sigquit(pid);
21012 + } while (time_spend <= timeout && fd == -1);
21013 + if (fd == -1) {
21014 + throw new AttachNotSupportedException(
21015 + String.format("Unable to open door %s: " +
21016 + "target process %d doesn't respond within %dms " +
21017 + "or HotSpot VM not loaded", socket_path, pid, time_spend));
21019 + } finally {
21020 + f.delete();
21023 + assert fd >= 0;
21026 + /**
21027 + * Detach from the target VM
21028 + */
21029 + public void detach() throws IOException {
21030 + synchronized (this) {
21031 + if (fd != -1) {
21032 + close(fd);
21033 + fd = -1;
21038 + /**
21039 + * Execute the given command in the target VM.
21040 + */
21041 + InputStream execute(String cmd, Object ... args) throws AgentLoadException, IOException {
21042 + assert args.length <= 3; // includes null
21044 + // first check that we are still attached
21045 + int door;
21046 + synchronized (this) {
21047 + if (fd == -1) {
21048 + throw new IOException("Detached from target VM");
21050 + door = fd;
21053 + // enqueue the command via a door call
21054 + int s = enqueue(door, cmd, args);
21055 + assert s >= 0; // valid file descriptor
21057 + // The door call returns a file descriptor (one end of a socket pair).
21058 + // Create an input stream around it.
21059 + SocketInputStream sis = new SocketInputStream(s);
21061 + // Read the command completion status
21062 + int completionStatus;
21063 + try {
21064 + completionStatus = readInt(sis);
21065 + } catch (IOException ioe) {
21066 + sis.close();
21067 + throw ioe;
21070 + // If non-0 it means an error but we need to special-case the
21071 + // "load" command to ensure that the right exception is thrown.
21072 + if (completionStatus != 0) {
21073 + // read from the stream and use that as the error message
21074 + String message = readErrorMessage(sis);
21075 + sis.close();
21076 + if (cmd.equals("load")) {
21077 + String msg = "Failed to load agent library";
21078 + if (!message.isEmpty())
21079 + msg += ": " + message;
21080 + throw new AgentLoadException(msg);
21081 + } else {
21082 + if (message.isEmpty())
21083 + message = "Command failed in target VM";
21084 + throw new AttachOperationFailedException(message);
21088 + // Return the input stream so that the command output can be read
21089 + return sis;
21092 + // InputStream over a socket
21093 + private class SocketInputStream extends InputStream {
21094 + int s;
21096 + public SocketInputStream(int s) {
21097 + this.s = s;
21100 + public synchronized int read() throws IOException {
21101 + byte b[] = new byte[1];
21102 + int n = this.read(b, 0, 1);
21103 + if (n == 1) {
21104 + return b[0] & 0xff;
21105 + } else {
21106 + return -1;
21110 + public synchronized int read(byte[] bs, int off, int len) throws IOException {
21111 + if ((off < 0) || (off > bs.length) || (len < 0) ||
21112 + ((off + len) > bs.length) || ((off + len) < 0)) {
21113 + throw new IndexOutOfBoundsException();
21114 + } else if (len == 0)
21115 + return 0;
21117 + return VirtualMachineImpl.read(s, bs, off, len);
21120 + public synchronized void close() throws IOException {
21121 + if (s != -1) {
21122 + int toClose = s;
21123 + s = -1;
21124 + VirtualMachineImpl.close(toClose);
21129 + // The door is attached to .java_pid<pid> in the temporary directory.
21130 + private int openDoor(int pid) throws IOException {
21131 + socket_path = tmpdir + "/.java_pid" + pid;
21132 + fd = open(socket_path);
21134 + // Check that the file owner/permission to avoid attaching to
21135 + // bogus process
21136 + try {
21137 + checkPermissions(socket_path);
21138 + } catch (IOException ioe) {
21139 + close(fd);
21140 + throw ioe;
21142 + return fd;
21145 + // On Solaris a simple handshake is used to start the attach mechanism
21146 + // if not already started. The client creates a .attach_pid<pid> file in the
21147 + // target VM's working directory (or temporary directory), and the SIGQUIT
21148 + // handler checks for the file.
21149 + private File createAttachFile(int pid) throws IOException {
21150 + String fn = ".attach_pid" + pid;
21151 + String path = "/proc/" + pid + "/cwd/" + fn;
21152 + File f = new File(path);
21153 + try {
21154 + f = f.getCanonicalFile();
21155 + f.createNewFile();
21156 + } catch (IOException x) {
21157 + f = new File(tmpdir, fn);
21158 + f.createNewFile();
21160 + return f;
21163 + //-- native methods
21165 + static native int open(String path) throws IOException;
21167 + static native void close(int fd) throws IOException;
21169 + static native int read(int fd, byte buf[], int off, int buflen) throws IOException;
21171 + static native void checkPermissions(String path) throws IOException;
21173 + static native void sigquit(int pid) throws IOException;
21175 + // enqueue a command (and arguments) to the given door
21176 + static native int enqueue(int fd, String cmd, Object ... args)
21177 + throws IOException;
21179 + static {
21180 + System.loadLibrary("attach");
21183 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/jdk.attach/solaris/native/libattach/VirtualMachineImpl.c jdk22u-jdk-22.0.2-ga/src/jdk.attach/solaris/native/libattach/VirtualMachineImpl.c
21184 --- jdk22u-jdk-22.0.2-ga.orig/src/jdk.attach/solaris/native/libattach/VirtualMachineImpl.c 1970-01-01 01:00:00.000000000 +0100
21185 +++ jdk22u-jdk-22.0.2-ga/src/jdk.attach/solaris/native/libattach/VirtualMachineImpl.c 2024-08-17 19:34:03.921204128 +0200
21186 @@ -0,0 +1,389 @@
21188 + * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
21189 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
21191 + * This code is free software; you can redistribute it and/or modify it
21192 + * under the terms of the GNU General Public License version 2 only, as
21193 + * published by the Free Software Foundation. Oracle designates this
21194 + * particular file as subject to the "Classpath" exception as provided
21195 + * by Oracle in the LICENSE file that accompanied this code.
21197 + * This code is distributed in the hope that it will be useful, but WITHOUT
21198 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21199 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21200 + * version 2 for more details (a copy is included in the LICENSE file that
21201 + * accompanied this code).
21203 + * You should have received a copy of the GNU General Public License version
21204 + * 2 along with this work; if not, write to the Free Software Foundation,
21205 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21207 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21208 + * or visit www.oracle.com if you need additional information or have any
21209 + * questions.
21210 + */
21212 +#include "jni_util.h"
21214 +#include <sys/stat.h>
21215 +#include <sys/types.h>
21216 +#include <door.h>
21217 +#include <errno.h>
21218 +#include <fcntl.h>
21219 +#include <limits.h>
21220 +#include <signal.h>
21221 +#include <stdlib.h>
21222 +#include <string.h>
21223 +#include <unistd.h>
21225 +#include "sun_tools_attach_VirtualMachineImpl.h"
21227 +#define ROOT_UID 0
21229 +#define RESTARTABLE(_cmd, _result) do { \
21230 + do { \
21231 + _result = _cmd; \
21232 + } while((_result == -1) && (errno == EINTR)); \
21233 +} while(0)
21236 + * Declare library specific JNI_Onload entry if static build
21237 + */
21238 +DEF_STATIC_JNI_OnLoad
21241 + * Class: sun_tools_attach_VirtualMachineImpl
21242 + * Method: open
21243 + * Signature: (Ljava/lang/String;)I
21244 + */
21245 +JNIEXPORT jint JNICALL Java_sun_tools_attach_VirtualMachineImpl_open
21246 + (JNIEnv *env, jclass cls, jstring path)
21248 + jboolean isCopy;
21249 + const char* p = GetStringPlatformChars(env, path, &isCopy);
21250 + if (p == NULL) {
21251 + return 0;
21252 + } else {
21253 + int fd;
21254 + int err = 0;
21256 + fd = open(p, O_RDWR);
21257 + if (fd == -1) {
21258 + err = errno;
21261 + if (isCopy) {
21262 + JNU_ReleaseStringPlatformChars(env, path, p);
21265 + if (fd == -1) {
21266 + if (err == ENOENT) {
21267 + JNU_ThrowByName(env, "java/io/FileNotFoundException", NULL);
21268 + } else {
21269 + char* msg = strdup(strerror(err));
21270 + JNU_ThrowIOException(env, msg);
21271 + if (msg != NULL) {
21272 + free(msg);
21276 + return fd;
21281 + * Class: sun_tools_attach_VirtualMachineImpl
21282 + * Method: checkPermissions
21283 + * Signature: (Ljava/lang/String;)V
21284 + */
21285 +JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_checkPermissions
21286 + (JNIEnv *env, jclass cls, jstring path)
21288 + jboolean isCopy;
21289 + const char* p = GetStringPlatformChars(env, path, &isCopy);
21290 + if (p != NULL) {
21291 + struct stat64 sb;
21292 + uid_t uid, gid;
21293 + int res;
21295 + memset(&sb, 0, sizeof(struct stat64));
21297 + /*
21298 + * Check that the path is owned by the effective uid/gid of this
21299 + * process. Also check that group/other access is not allowed.
21300 + */
21301 + uid = geteuid();
21302 + gid = getegid();
21304 + res = stat64(p, &sb);
21305 + if (res != 0) {
21306 + /* save errno */
21307 + res = errno;
21310 + if (res == 0) {
21311 + char msg[100];
21312 + jboolean isError = JNI_FALSE;
21313 + if (sb.st_uid != uid && uid != ROOT_UID) {
21314 + snprintf(msg, sizeof(msg),
21315 + "file should be owned by the current user (which is %d) but is owned by %d", uid, sb.st_uid);
21316 + isError = JNI_TRUE;
21317 + } else if (sb.st_gid != gid && uid != ROOT_UID) {
21318 + snprintf(msg, sizeof(msg),
21319 + "file's group should be the current group (which is %d) but the group is %d", gid, sb.st_gid);
21320 + isError = JNI_TRUE;
21321 + } else if ((sb.st_mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) != 0) {
21322 + snprintf(msg, sizeof(msg),
21323 + "file should only be readable and writable by the owner but has 0%03o access", sb.st_mode & 0777);
21324 + isError = JNI_TRUE;
21326 + if (isError) {
21327 + char buf[256];
21328 + snprintf(buf, sizeof(buf), "well-known file %s is not secure: %s", p, msg);
21329 + JNU_ThrowIOException(env, buf);
21331 + } else {
21332 + char* msg = strdup(strerror(res));
21333 + JNU_ThrowIOException(env, msg);
21334 + if (msg != NULL) {
21335 + free(msg);
21339 + if (isCopy) {
21340 + JNU_ReleaseStringPlatformChars(env, path, p);
21346 + * Class: sun_tools_attach_VirtualMachineImpl
21347 + * Method: close
21348 + * Signature: (I)V
21349 + */
21350 +JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_close
21351 + (JNIEnv *env, jclass cls, jint fd)
21353 + int ret;
21354 + RESTARTABLE(close(fd), ret);
21358 + * Class: sun_tools_attach_VirtualMachineImpl
21359 + * Method: read
21360 + * Signature: (I[BI)I
21361 + */
21362 +JNIEXPORT jint JNICALL Java_sun_tools_attach_VirtualMachineImpl_read
21363 + (JNIEnv *env, jclass cls, jint fd, jbyteArray ba, jint off, jint baLen)
21365 + unsigned char buf[128];
21366 + size_t len = sizeof(buf);
21367 + ssize_t n;
21369 + size_t remaining = (size_t)(baLen - off);
21370 + if (len > remaining) {
21371 + len = remaining;
21374 + RESTARTABLE(read(fd, buf, len), n);
21375 + if (n == -1) {
21376 + JNU_ThrowIOExceptionWithLastError(env, "read");
21377 + } else {
21378 + if (n == 0) {
21379 + n = -1; // EOF
21380 + } else {
21381 + (*env)->SetByteArrayRegion(env, ba, off, (jint)n, (jbyte *)(buf));
21384 + return n;
21388 + * Class: sun_tools_attach_VirtualMachineImpl
21389 + * Method: sigquit
21390 + * Signature: (I)V
21391 + */
21392 +JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_sigquit
21393 + (JNIEnv *env, jclass cls, jint pid)
21395 + if (kill((pid_t)pid, SIGQUIT) == -1) {
21396 + JNU_ThrowIOExceptionWithLastError(env, "kill");
21401 + * A simple table to translate some known errors into reasonable
21402 + * error messages
21403 + */
21404 +static struct {
21405 + jint err;
21406 + const char* msg;
21407 +} const error_messages[] = {
21408 + { 100, "Bad request" },
21409 + { 101, "Protocol mismatch" },
21410 + { 102, "Resource failure" },
21411 + { 103, "Internal error" },
21412 + { 104, "Permission denied" },
21416 + * Lookup the given error code and return the appropriate
21417 + * message. If not found return NULL.
21418 + */
21419 +static const char* translate_error(jint err) {
21420 + int table_size = sizeof(error_messages) / sizeof(error_messages[0]);
21421 + int i;
21423 + for (i = 0; i < table_size; i++) {
21424 + if (err == error_messages[i].err) {
21425 + return error_messages[i].msg;
21428 + return NULL;
21432 + * Current protocol version
21433 + */
21434 +static const char* PROTOCOL_VERSION = "1";
21437 + * Class: sun_tools_attach_VirtualMachineImpl
21438 + * Method: enqueue
21439 + * Signature: (JILjava/lang/String;[Ljava/lang/Object;)V
21440 + */
21441 +JNIEXPORT jint JNICALL Java_sun_tools_attach_VirtualMachineImpl_enqueue
21442 + (JNIEnv *env, jclass cls, jint fd, jstring cmd, jobjectArray args)
21444 + jint arg_count, i;
21445 + size_t size;
21446 + jboolean isCopy;
21447 + door_arg_t door_args;
21448 + char res_buffer[128];
21449 + jint result = -1;
21450 + int rc;
21451 + const char* cstr;
21452 + char* buf;
21454 + /*
21455 + * First we get the command string and create the start of the
21456 + * argument string to send to the target VM:
21457 + * <ver>\0<cmd>\0
21458 + */
21459 + cstr = JNU_GetStringPlatformChars(env, cmd, &isCopy);
21460 + if (cstr == NULL) {
21461 + return -1; /* pending exception */
21463 + size = strlen(PROTOCOL_VERSION) + strlen(cstr) + 2;
21464 + buf = (char*)malloc(size);
21465 + if (buf != NULL) {
21466 + char* pos = buf;
21467 + strcpy(buf, PROTOCOL_VERSION);
21468 + pos += strlen(PROTOCOL_VERSION)+1;
21469 + strcpy(pos, cstr);
21471 + if (isCopy) {
21472 + JNU_ReleaseStringPlatformChars(env, cmd, cstr);
21474 + if (buf == NULL) {
21475 + JNU_ThrowOutOfMemoryError(env, "malloc failed");
21476 + return -1;
21479 + /*
21480 + * Next we iterate over the arguments and extend the buffer
21481 + * to include them.
21482 + */
21483 + arg_count = (*env)->GetArrayLength(env, args);
21485 + for (i = 0; i < arg_count; i++) {
21486 + jobject obj = (*env)->GetObjectArrayElement(env, args, i);
21487 + if (obj != NULL) {
21488 + cstr = JNU_GetStringPlatformChars(env, obj, &isCopy);
21489 + if (cstr != NULL) {
21490 + size_t len = strlen(cstr);
21491 + char* newbuf = (char*)realloc(buf, size+len+1);
21492 + if (newbuf != NULL) {
21493 + buf = newbuf;
21494 + strcpy(buf+size, cstr);
21495 + size += len+1;
21497 + if (isCopy) {
21498 + JNU_ReleaseStringPlatformChars(env, obj, cstr);
21500 + if (newbuf == NULL) {
21501 + free(buf);
21502 + JNU_ThrowOutOfMemoryError(env, "realloc failed");
21503 + return -1;
21506 + } else {
21507 + char* newbuf = (char*)realloc(buf, size + 1);
21508 + if (newbuf == NULL) {
21509 + free(buf);
21510 + JNU_ThrowOutOfMemoryError(env, "realloc failed");
21511 + return -1;
21513 + buf = newbuf;
21514 + buf[size++] = 0;
21516 + if ((*env)->ExceptionOccurred(env)) {
21517 + free(buf);
21518 + return -1;
21522 + /*
21523 + * The arguments to the door function are in 'buf' so we now
21524 + * do the door call
21525 + */
21526 + door_args.data_ptr = buf;
21527 + door_args.data_size = size;
21528 + door_args.desc_ptr = NULL;
21529 + door_args.desc_num = 0;
21530 + door_args.rbuf = (char*)&res_buffer;
21531 + door_args.rsize = sizeof(res_buffer);
21533 + RESTARTABLE(door_call(fd, &door_args), rc);
21535 + /*
21536 + * door_call failed
21537 + */
21538 + if (rc == -1) {
21539 + JNU_ThrowIOExceptionWithLastError(env, "door_call");
21540 + } else {
21541 + /*
21542 + * door_call succeeded but the call didn't return the expected jint.
21543 + */
21544 + if (door_args.data_size < sizeof(jint)) {
21545 + JNU_ThrowIOException(env, "Enqueue error - reason unknown as result is truncated!");
21546 + } else {
21547 + jint* res = (jint*)(door_args.data_ptr);
21548 + if (*res != JNI_OK) {
21549 + const char* msg = translate_error(*res);
21550 + char buf[255];
21551 + if (msg == NULL) {
21552 + sprintf(buf, "Unable to enqueue command to target VM: %d", *res);
21553 + } else {
21554 + sprintf(buf, "Unable to enqueue command to target VM: %s", msg);
21556 + JNU_ThrowIOException(env, buf);
21557 + } else {
21558 + /*
21559 + * The door call should return a file descriptor to one end of
21560 + * a socket pair
21561 + */
21562 + if ((door_args.desc_ptr != NULL) &&
21563 + (door_args.desc_num == 1) &&
21564 + (door_args.desc_ptr->d_attributes & DOOR_DESCRIPTOR)) {
21565 + result = door_args.desc_ptr->d_data.d_desc.d_descriptor;
21566 + } else {
21567 + JNU_ThrowIOException(env, "Reply from enqueue missing descriptor!");
21573 + free(buf);
21574 + return result;
21576 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/jdk.charsets/share/classes/sun/nio/cs/ext/JISAutoDetect.java jdk22u-jdk-22.0.2-ga/src/jdk.charsets/share/classes/sun/nio/cs/ext/JISAutoDetect.java
21577 --- jdk22u-jdk-22.0.2-ga.orig/src/jdk.charsets/share/classes/sun/nio/cs/ext/JISAutoDetect.java 2024-06-04 18:47:50.000000000 +0200
21578 +++ jdk22u-jdk-22.0.2-ga/src/jdk.charsets/share/classes/sun/nio/cs/ext/JISAutoDetect.java 2024-08-17 19:34:03.884894868 +0200
21579 @@ -95,7 +95,7 @@
21580 private static class Decoder extends CharsetDecoder {
21582 private static final String SJISName = getSJISName();
21583 - private static final String EUCJPName = "EUC_JP";
21584 + private static final String EUCJPName = getEUCJPName();
21585 private DelegatableDecoder detectedDecoder = null;
21587 public Decoder(Charset cs) {
21588 @@ -223,11 +223,24 @@
21589 * Returned Shift_JIS Charset name is OS dependent
21591 private static String getSJISName() {
21592 - if (OperatingSystem.isWindows())
21593 + if (OperatingSystem.isSolaris())
21594 + return("PCK");
21595 + else if (OperatingSystem.isWindows())
21596 return("windows-31J");
21597 else
21598 return("Shift_JIS");
21601 + /**
21602 + * Returned EUC-JP Charset name is OS dependent
21603 + */
21605 + private static String getEUCJPName() {
21606 + if (OperatingSystem.isSolaris())
21607 + return("x-eucjp-open");
21608 + else
21609 + return("EUC_JP");
21614 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java jdk22u-jdk-22.0.2-ga/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java
21615 --- jdk22u-jdk-22.0.2-ga.orig/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java 2024-06-04 18:47:50.000000000 +0200
21616 +++ jdk22u-jdk-22.0.2-ga/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java 2024-08-17 19:34:03.885489177 +0200
21617 @@ -711,10 +711,15 @@
21618 lib = expand(lib);
21619 int i = lib.indexOf("/$ISA/");
21620 if (i != -1) {
21621 - // replace "/$ISA/" with "/"
21622 + // replace "/$ISA/" with "/amd64/" on Solaris AMD64.
21623 + // On all other platforms, just turn it into a "/"
21624 String prefix = lib.substring(0, i);
21625 String suffix = lib.substring(i + 5);
21626 - lib = prefix + suffix;
21627 + if (osName.equals("SunOS") && osArch.equals("amd64")) {
21628 + lib = prefix + "/amd64" + suffix;
21629 + } else {
21630 + lib = prefix + suffix;
21633 if (DEBUG) {
21634 System.out.println(keyword + ": " + lib);
21635 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/jdk.crypto.cryptoki/solaris/conf/security/sunpkcs11-solaris.cfg jdk22u-jdk-22.0.2-ga/src/jdk.crypto.cryptoki/solaris/conf/security/sunpkcs11-solaris.cfg
21636 --- jdk22u-jdk-22.0.2-ga.orig/src/jdk.crypto.cryptoki/solaris/conf/security/sunpkcs11-solaris.cfg 1970-01-01 01:00:00.000000000 +0100
21637 +++ jdk22u-jdk-22.0.2-ga/src/jdk.crypto.cryptoki/solaris/conf/security/sunpkcs11-solaris.cfg 2024-08-17 19:34:03.921590870 +0200
21638 @@ -0,0 +1,23 @@
21640 +# Configuration file to allow the SunPKCS11 provider to utilize
21641 +# the Solaris Cryptographic Framework, if it is available
21644 +name = Solaris
21646 +description = SunPKCS11 accessing Solaris Cryptographic Framework
21648 +library = /usr/lib/$ISA/libpkcs11.so
21650 +handleStartupErrors = ignoreAll
21652 +# Use the X9.63 encoding for EC points (do not wrap in an ASN.1 OctetString).
21653 +useEcX963Encoding = true
21655 +attributes = compatibility
21657 +disabledMechanisms = {
21658 + CKM_DSA_KEY_PAIR_GEN
21659 + SecureRandom
21662 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HotSpotSolarisVtblAccess.java jdk22u-jdk-22.0.2-ga/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HotSpotSolarisVtblAccess.java
21663 --- jdk22u-jdk-22.0.2-ga.orig/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HotSpotSolarisVtblAccess.java 1970-01-01 01:00:00.000000000 +0100
21664 +++ jdk22u-jdk-22.0.2-ga/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HotSpotSolarisVtblAccess.java 2024-08-17 19:34:03.921860675 +0200
21665 @@ -0,0 +1,65 @@
21667 + * Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
21668 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
21670 + * This code is free software; you can redistribute it and/or modify it
21671 + * under the terms of the GNU General Public License version 2 only, as
21672 + * published by the Free Software Foundation.
21674 + * This code is distributed in the hope that it will be useful, but WITHOUT
21675 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21676 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21677 + * version 2 for more details (a copy is included in the LICENSE file that
21678 + * accompanied this code).
21680 + * You should have received a copy of the GNU General Public License version
21681 + * 2 along with this work; if not, write to the Free Software Foundation,
21682 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21684 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21685 + * or visit www.oracle.com if you need additional information or have any
21686 + * questions.
21688 + */
21690 +package sun.jvm.hotspot;
21692 +import java.util.*;
21693 +import sun.jvm.hotspot.debugger.*;
21694 +import sun.jvm.hotspot.types.*;
21695 +import sun.jvm.hotspot.types.basic.*;
21697 +/** This class implements the compiler-specific access to the vtbl for
21698 + a given C++ type. */
21699 +public class HotSpotSolarisVtblAccess extends BasicVtblAccess {
21701 + public HotSpotSolarisVtblAccess(SymbolLookup symbolLookup,
21702 + String[] jvmLibNames) {
21703 + super(symbolLookup, jvmLibNames);
21706 + protected String vtblSymbolForType(Type type) {
21707 + String demangledSymbol = type.getName() + "::__vtbl";
21708 + return mangle(demangledSymbol);
21711 + //--------------------------------------------------------------------------------
21712 + // Internals only below this point
21713 + //
21715 + private String mangle(String symbol) {
21716 + String[] parts = symbol.split("::");
21717 + StringBuffer mangled = new StringBuffer("__1c");
21718 + for (int i = 0; i < parts.length; i++) {
21719 + int len = parts[i].length();
21720 + if (len >= 26) {
21721 + mangled.append((char)('a' + (len / 26)));
21722 + len = len % 26;
21724 + mangled.append((char)('A' + len));
21725 + mangled.append(parts[i]);
21727 + mangled.append("_");
21728 + return mangled.toString();
21731 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/solaris_amd64/SolarisAMD64JavaThreadPDAccess.java jdk22u-jdk-22.0.2-ga/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/solaris_amd64/SolarisAMD64JavaThreadPDAccess.java
21732 --- jdk22u-jdk-22.0.2-ga.orig/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/solaris_amd64/SolarisAMD64JavaThreadPDAccess.java 1970-01-01 01:00:00.000000000 +0100
21733 +++ jdk22u-jdk-22.0.2-ga/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/solaris_amd64/SolarisAMD64JavaThreadPDAccess.java 2024-08-17 19:34:03.922244719 +0200
21734 @@ -0,0 +1,140 @@
21736 + * Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved.
21737 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
21739 + * This code is free software; you can redistribute it and/or modify it
21740 + * under the terms of the GNU General Public License version 2 only, as
21741 + * published by the Free Software Foundation.
21743 + * This code is distributed in the hope that it will be useful, but WITHOUT
21744 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21745 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21746 + * version 2 for more details (a copy is included in the LICENSE file that
21747 + * accompanied this code).
21749 + * You should have received a copy of the GNU General Public License version
21750 + * 2 along with this work; if not, write to the Free Software Foundation,
21751 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21753 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21754 + * or visit www.oracle.com if you need additional information or have any
21755 + * questions.
21757 + */
21759 +package sun.jvm.hotspot.runtime.solaris_amd64;
21761 +import java.io.*;
21762 +import java.util.*;
21763 +import sun.jvm.hotspot.debugger.*;
21764 +import sun.jvm.hotspot.debugger.amd64.*;
21765 +import sun.jvm.hotspot.runtime.*;
21766 +import sun.jvm.hotspot.runtime.amd64.*;
21767 +import sun.jvm.hotspot.runtime.x86.*;
21768 +import sun.jvm.hotspot.types.*;
21769 +import sun.jvm.hotspot.utilities.*;
21770 +import sun.jvm.hotspot.utilities.Observable;
21771 +import sun.jvm.hotspot.utilities.Observer;
21773 +public class SolarisAMD64JavaThreadPDAccess implements JavaThreadPDAccess {
21774 + private static AddressField lastJavaFPField;
21775 + private static AddressField osThreadField;
21776 + private static AddressField baseOfStackPointerField;
21778 + // Field from OSThread
21779 + private static CIntegerField osThreadThreadIDField;
21781 + // This is currently unneeded but is being kept in case we change
21782 + // the currentFrameGuess algorithm
21783 + private static final long GUESS_SCAN_RANGE = 128 * 1024;
21786 + static {
21787 + VM.registerVMInitializedObserver(new Observer() {
21788 + public void update(Observable o, Object data) {
21789 + initialize(VM.getVM().getTypeDataBase());
21791 + });
21794 + private static synchronized void initialize(TypeDataBase db) {
21795 + Type type = db.lookupType("JavaThread");
21796 + Type anchorType = db.lookupType("JavaFrameAnchor");
21798 + lastJavaFPField = anchorType.getAddressField("_last_Java_fp");
21799 + osThreadField = type.getAddressField("_osthread");
21801 + type = db.lookupType("OSThread");
21802 + osThreadThreadIDField = type.getCIntegerField("_thread_id");
21805 + public Address getLastJavaFP(Address addr) {
21806 + return lastJavaFPField.getValue(addr.addOffsetTo(sun.jvm.hotspot.runtime.JavaThread.getAnchorField().getOffset()));
21809 + public Address getLastJavaPC(Address addr) {
21810 + return null;
21813 + public Address getBaseOfStackPointer(Address addr) {
21814 + return null;
21817 + public Frame getLastFramePD(JavaThread thread, Address addr) {
21818 + Address fp = thread.getLastJavaFP();
21819 + if (fp == null) {
21820 + return null; // no information
21822 + Address pc = thread.getLastJavaPC();
21823 + if ( pc != null ) {
21824 + return new X86Frame(thread.getLastJavaSP(), fp, pc);
21825 + } else {
21826 + return new X86Frame(thread.getLastJavaSP(), fp);
21830 + public RegisterMap newRegisterMap(JavaThread thread, boolean updateMap) {
21831 + return new X86RegisterMap(thread, updateMap);
21834 + public Frame getCurrentFrameGuess(JavaThread thread, Address addr) {
21835 + ThreadProxy t = getThreadProxy(addr);
21836 + AMD64ThreadContext context = (AMD64ThreadContext) t.getContext();
21837 + AMD64CurrentFrameGuess guesser = new AMD64CurrentFrameGuess(context, thread);
21838 + if (!guesser.run(GUESS_SCAN_RANGE)) {
21839 + return null;
21841 + if (guesser.getPC() == null) {
21842 + return new X86Frame(guesser.getSP(), guesser.getFP());
21843 + } else {
21844 + return new X86Frame(guesser.getSP(), guesser.getFP(), guesser.getPC());
21849 + public void printThreadIDOn(Address addr, PrintStream tty) {
21850 + tty.print(getThreadProxy(addr));
21854 + public void printInfoOn(Address threadAddr, PrintStream tty) {
21857 + public Address getLastSP(Address addr) {
21858 + ThreadProxy t = getThreadProxy(addr);
21859 + AMD64ThreadContext context = (AMD64ThreadContext) t.getContext();
21860 + return context.getRegisterAsAddress(AMD64ThreadContext.RSP);
21863 + public ThreadProxy getThreadProxy(Address addr) {
21864 + // Fetch the OSThread (for now and for simplicity, not making a
21865 + // separate "OSThread" class in this package)
21866 + Address osThreadAddr = osThreadField.getValue(addr);
21867 + // Get the address of the thread ID from the OSThread
21868 + Address tidAddr = osThreadAddr.addOffsetTo(osThreadThreadIDField.getOffset());
21870 + JVMDebugger debugger = VM.getVM().getDebugger();
21871 + return debugger.getThreadForIdentifierAddress(tidAddr);
21875 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/solaris_x86/SolarisX86JavaThreadPDAccess.java jdk22u-jdk-22.0.2-ga/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/solaris_x86/SolarisX86JavaThreadPDAccess.java
21876 --- jdk22u-jdk-22.0.2-ga.orig/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/solaris_x86/SolarisX86JavaThreadPDAccess.java 1970-01-01 01:00:00.000000000 +0100
21877 +++ jdk22u-jdk-22.0.2-ga/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/solaris_x86/SolarisX86JavaThreadPDAccess.java 2024-08-17 19:34:03.922627862 +0200
21878 @@ -0,0 +1,142 @@
21880 + * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
21881 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
21883 + * This code is free software; you can redistribute it and/or modify it
21884 + * under the terms of the GNU General Public License version 2 only, as
21885 + * published by the Free Software Foundation.
21887 + * This code is distributed in the hope that it will be useful, but WITHOUT
21888 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21889 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21890 + * version 2 for more details (a copy is included in the LICENSE file that
21891 + * accompanied this code).
21893 + * You should have received a copy of the GNU General Public License version
21894 + * 2 along with this work; if not, write to the Free Software Foundation,
21895 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21897 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21898 + * or visit www.oracle.com if you need additional information or have any
21899 + * questions.
21901 + */
21903 +package sun.jvm.hotspot.runtime.solaris_x86;
21905 +import java.io.*;
21906 +import java.util.*;
21907 +import sun.jvm.hotspot.debugger.*;
21908 +import sun.jvm.hotspot.debugger.x86.*;
21909 +import sun.jvm.hotspot.runtime.*;
21910 +import sun.jvm.hotspot.runtime.x86.*;
21911 +import sun.jvm.hotspot.types.*;
21912 +import sun.jvm.hotspot.utilities.*;
21913 +import sun.jvm.hotspot.utilities.Observable;
21914 +import sun.jvm.hotspot.utilities.Observer;
21916 +/** Placeholder for now to allow us to start the SA without support
21917 + for stack traces */
21919 +public class SolarisX86JavaThreadPDAccess implements JavaThreadPDAccess {
21920 + private static AddressField lastJavaFPField;
21921 + private static AddressField osThreadField;
21922 + private static AddressField baseOfStackPointerField;
21924 + // Field from OSThread
21925 + private static CIntegerField osThreadThreadIDField;
21927 + // This is currently unneeded but is being kept in case we change
21928 + // the currentFrameGuess algorithm
21929 + private static final long GUESS_SCAN_RANGE = 128 * 1024;
21932 + static {
21933 + VM.registerVMInitializedObserver(new Observer() {
21934 + public void update(Observable o, Object data) {
21935 + initialize(VM.getVM().getTypeDataBase());
21937 + });
21940 + private static synchronized void initialize(TypeDataBase db) {
21941 + Type type = db.lookupType("JavaThread");
21942 + Type anchorType = db.lookupType("JavaFrameAnchor");
21944 + lastJavaFPField = anchorType.getAddressField("_last_Java_fp");
21945 + osThreadField = type.getAddressField("_osthread");
21947 + type = db.lookupType("OSThread");
21948 + osThreadThreadIDField = type.getCIntegerField("_thread_id");
21951 + public Address getLastJavaFP(Address addr) {
21952 + return lastJavaFPField.getValue(addr.addOffsetTo(sun.jvm.hotspot.runtime.JavaThread.getAnchorField().getOffset()));
21955 + public Address getLastJavaPC(Address addr) {
21956 + return null;
21959 + public Address getBaseOfStackPointer(Address addr) {
21960 + return null;
21963 + public Frame getLastFramePD(JavaThread thread, Address addr) {
21964 + Address fp = thread.getLastJavaFP();
21965 + if (fp == null) {
21966 + return null; // no information
21968 + Address pc = thread.getLastJavaPC();
21969 + if ( pc != null ) {
21970 + return new X86Frame(thread.getLastJavaSP(), fp, pc);
21971 + } else {
21972 + return new X86Frame(thread.getLastJavaSP(), fp);
21976 + public RegisterMap newRegisterMap(JavaThread thread, boolean updateMap) {
21977 + return new X86RegisterMap(thread, updateMap);
21980 + public Frame getCurrentFrameGuess(JavaThread thread, Address addr) {
21981 + ThreadProxy t = getThreadProxy(addr);
21982 + X86ThreadContext context = (X86ThreadContext) t.getContext();
21983 + X86CurrentFrameGuess guesser = new X86CurrentFrameGuess(context, thread);
21984 + if (!guesser.run(GUESS_SCAN_RANGE)) {
21985 + return null;
21987 + if (guesser.getPC() == null) {
21988 + return new X86Frame(guesser.getSP(), guesser.getFP());
21989 + } else {
21990 + return new X86Frame(guesser.getSP(), guesser.getFP(), guesser.getPC());
21995 + public void printThreadIDOn(Address addr, PrintStream tty) {
21996 + tty.print(getThreadProxy(addr));
22000 + public void printInfoOn(Address threadAddr, PrintStream tty) {
22003 + public Address getLastSP(Address addr) {
22004 + ThreadProxy t = getThreadProxy(addr);
22005 + X86ThreadContext context = (X86ThreadContext) t.getContext();
22006 + return context.getRegisterAsAddress(X86ThreadContext.ESP);
22009 + public ThreadProxy getThreadProxy(Address addr) {
22010 + // Fetch the OSThread (for now and for simplicity, not making a
22011 + // separate "OSThread" class in this package)
22012 + Address osThreadAddr = osThreadField.getValue(addr);
22013 + // Get the address of the thread ID from the OSThread
22014 + Address tidAddr = osThreadAddr.addOffsetTo(osThreadThreadIDField.getOffset());
22016 + JVMDebugger debugger = VM.getVM().getDebugger();
22017 + return debugger.getThreadForIdentifierAddress(tidAddr);
22021 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java jdk22u-jdk-22.0.2-ga/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java
22022 --- jdk22u-jdk-22.0.2-ga.orig/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java 2024-06-04 18:47:50.000000000 +0200
22023 +++ jdk22u-jdk-22.0.2-ga/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java 2024-08-17 19:34:03.886091953 +0200
22024 @@ -28,6 +28,8 @@
22026 import sun.jvm.hotspot.debugger.*;
22027 import sun.jvm.hotspot.types.*;
22028 +import sun.jvm.hotspot.runtime.solaris_x86.SolarisX86JavaThreadPDAccess;
22029 +import sun.jvm.hotspot.runtime.solaris_amd64.SolarisAMD64JavaThreadPDAccess;
22030 import sun.jvm.hotspot.runtime.win32_x86.Win32X86JavaThreadPDAccess;
22031 import sun.jvm.hotspot.runtime.win32_amd64.Win32AMD64JavaThreadPDAccess;
22032 import sun.jvm.hotspot.runtime.win32_aarch64.Win32AARCH64JavaThreadPDAccess;
22033 @@ -97,7 +99,13 @@
22035 access = null;
22036 // FIXME: find the platform specific PD class by reflection?
22037 - if (os.equals("win32")) {
22038 + if (os.equals("solaris")) {
22039 + if (cpu.equals("x86")) {
22040 + access = new SolarisX86JavaThreadPDAccess();
22041 + } else if (cpu.equals("amd64")) {
22042 + access = new SolarisAMD64JavaThreadPDAccess();
22044 + } else if (os.equals("win32")) {
22045 if (cpu.equals("x86")) {
22046 access = new Win32X86JavaThreadPDAccess();
22047 } else if (cpu.equals("amd64")) {
22048 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java jdk22u-jdk-22.0.2-ga/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java
22049 --- jdk22u-jdk-22.0.2-ga.orig/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java 2024-06-04 18:47:50.000000000 +0200
22050 +++ jdk22u-jdk-22.0.2-ga/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java 2024-08-17 19:34:03.886563461 +0200
22051 @@ -28,10 +28,14 @@
22052 system. */
22054 public class PlatformInfo {
22055 - /* Returns "win32" if Windows; "linux" if Linux. */
22056 + /* Returns "solaris" if on Solaris; "win32" if Windows; "linux" if
22057 + Linux. Used to determine location of dbx and import module, or
22058 + possible debugger agent on win32. */
22059 public static String getOS() throws UnsupportedPlatformException {
22060 String os = System.getProperty("os.name");
22061 - if (os.equals("Linux")) {
22062 + if (os.equals("SunOS")) {
22063 + return "solaris";
22064 + } else if (os.equals("Linux")) {
22065 return "linux";
22066 } else if (os.equals("FreeBSD")) {
22067 return "bsd";
22068 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/jdk.hotspot.agent/share/native/libsaproc/ps_core_common.c jdk22u-jdk-22.0.2-ga/src/jdk.hotspot.agent/share/native/libsaproc/ps_core_common.c
22069 --- jdk22u-jdk-22.0.2-ga.orig/src/jdk.hotspot.agent/share/native/libsaproc/ps_core_common.c 2024-06-04 18:47:50.000000000 +0200
22070 +++ jdk22u-jdk-22.0.2-ga/src/jdk.hotspot.agent/share/native/libsaproc/ps_core_common.c 2024-08-17 19:34:03.887065060 +0200
22071 @@ -22,6 +22,8 @@
22075 +#include <jni.h> // just include something, or else solaris compiler will complain that this file is empty
22077 #if defined(LINUX) || defined(__APPLE__)
22078 #include <unistd.h>
22079 #include <fcntl.h>
22080 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/jdk.hotspot.agent/test/libproc/libproctest.sh jdk22u-jdk-22.0.2-ga/src/jdk.hotspot.agent/test/libproc/libproctest.sh
22081 --- jdk22u-jdk-22.0.2-ga.orig/src/jdk.hotspot.agent/test/libproc/libproctest.sh 2024-06-04 18:47:50.000000000 +0200
22082 +++ jdk22u-jdk-22.0.2-ga/src/jdk.hotspot.agent/test/libproc/libproctest.sh 2024-08-17 19:34:03.887478647 +0200
22083 @@ -59,8 +59,10 @@
22084 kill -9 $pid
22087 +OPTIONS="-Djava.library.path=$STARTDIR/../src/os/solaris/proc/`uname -p`:$STARTDIR/../solaris/`uname -p`"
22089 # run libproc client
22090 -$SA_JAVA -showversion -cp $STARTDIR/../../build/classes::$STARTDIR/../sa.jar:$STARTDIR LibprocClient x core.$pid
22091 +$SA_JAVA -showversion ${OPTIONS} -cp $STARTDIR/../../build/classes::$STARTDIR/../sa.jar:$STARTDIR LibprocClient x core.$pid
22093 # delete core
22094 rm -f core.$pid
22095 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/jdk.jdwp.agent/unix/native/libdt_socket/socket_md.c jdk22u-jdk-22.0.2-ga/src/jdk.jdwp.agent/unix/native/libdt_socket/socket_md.c
22096 --- jdk22u-jdk-22.0.2-ga.orig/src/jdk.jdwp.agent/unix/native/libdt_socket/socket_md.c 2024-06-04 18:47:50.000000000 +0200
22097 +++ jdk22u-jdk-22.0.2-ga/src/jdk.jdwp.agent/unix/native/libdt_socket/socket_md.c 2024-08-17 19:34:03.887997145 +0200
22098 @@ -33,8 +33,12 @@
22099 #include <errno.h>
22100 #include <string.h>
22101 #include <sys/time.h>
22102 +#ifdef __solaris__
22103 +#include <thread.h>
22104 +#else
22105 #include <pthread.h>
22106 #include <poll.h>
22107 +#endif
22109 #include "socket_md.h"
22110 #include "sysSocket.h"
22111 @@ -271,6 +275,35 @@
22112 return 0;
22115 +#ifdef __solaris__
22116 +int
22117 +dbgsysTlsAlloc() {
22118 + thread_key_t tk;
22119 + if (thr_keycreate(&tk, NULL)) {
22120 + perror("thr_keycreate");
22121 + exit(-1);
22123 + return (int)tk;
22126 +void
22127 +dbgsysTlsFree(int index) {
22128 + /* no-op */
22131 +void
22132 +dbgsysTlsPut(int index, void *value) {
22133 + thr_setspecific((thread_key_t)index, value) ;
22136 +void *
22137 +dbgsysTlsGet(int index) {
22138 + void* r = NULL;
22139 + thr_getspecific((thread_key_t)index, &r);
22140 + return r;
22143 +#else
22145 dbgsysTlsAlloc() {
22146 pthread_key_t key;
22147 @@ -296,6 +329,8 @@
22148 return pthread_getspecific((pthread_key_t)index);
22151 +#endif
22153 long
22154 dbgsysCurrentTimeMillis() {
22155 struct timeval t;
22156 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/jdk.management/solaris/native/libmanagement_ext/UnixOperatingSystem.c jdk22u-jdk-22.0.2-ga/src/jdk.management/solaris/native/libmanagement_ext/UnixOperatingSystem.c
22157 --- jdk22u-jdk-22.0.2-ga.orig/src/jdk.management/solaris/native/libmanagement_ext/UnixOperatingSystem.c 1970-01-01 01:00:00.000000000 +0100
22158 +++ jdk22u-jdk-22.0.2-ga/src/jdk.management/solaris/native/libmanagement_ext/UnixOperatingSystem.c 2024-08-17 19:34:03.923102258 +0200
22159 @@ -0,0 +1,254 @@
22161 + * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
22162 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
22164 + * This code is free software; you can redistribute it and/or modify it
22165 + * under the terms of the GNU General Public License version 2 only, as
22166 + * published by the Free Software Foundation. Oracle designates this
22167 + * particular file as subject to the "Classpath" exception as provided
22168 + * by Oracle in the LICENSE file that accompanied this code.
22170 + * This code is distributed in the hope that it will be useful, but WITHOUT
22171 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
22172 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22173 + * version 2 for more details (a copy is included in the LICENSE file that
22174 + * accompanied this code).
22176 + * You should have received a copy of the GNU General Public License version
22177 + * 2 along with this work; if not, write to the Free Software Foundation,
22178 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
22180 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22181 + * or visit www.oracle.com if you need additional information or have any
22182 + * questions.
22183 + */
22185 +#include <fcntl.h>
22186 +#include <kstat.h>
22187 +#include <procfs.h>
22188 +#include <unistd.h>
22189 +#include <stdlib.h>
22190 +#include <stdio.h>
22191 +#include <string.h>
22192 +#include <sys/sysinfo.h>
22193 +#include <sys/lwp.h>
22194 +#include <pthread.h>
22195 +#include <utmpx.h>
22196 +#include <dlfcn.h>
22197 +#include <sys/loadavg.h>
22198 +#include <jni.h>
22199 +#include "jvm.h"
22200 +#include "com_sun_management_internal_OperatingSystemImpl.h"
22202 +typedef struct {
22203 + kstat_t *kstat;
22204 + uint64_t last_idle;
22205 + uint64_t last_total;
22206 + double last_ratio;
22207 +} cpuload_t;
22209 +static cpuload_t *cpu_loads = NULL;
22210 +static unsigned int num_cpus;
22211 +static kstat_ctl_t *kstat_ctrl = NULL;
22213 +static void map_cpu_kstat_counters() {
22214 + kstat_t *kstat;
22215 + int i;
22217 + // Get number of CPU(s)
22218 + if ((num_cpus = sysconf(_SC_NPROCESSORS_ONLN)) == -1) {
22219 + num_cpus = 1;
22222 + // Data structure for saving CPU load
22223 + if ((cpu_loads = calloc(num_cpus,sizeof(cpuload_t))) == NULL) {
22224 + return;
22227 + // Get kstat cpu_stat counters for every CPU
22228 + // (loop over kstat to find our cpu_stat(s)
22229 + i = 0;
22230 + for (kstat = kstat_ctrl->kc_chain; kstat != NULL; kstat = kstat->ks_next) {
22231 + if (strncmp(kstat->ks_module, "cpu_stat", 8) == 0) {
22233 + if (kstat_read(kstat_ctrl, kstat, NULL) == -1) {
22234 + // Failed to initialize kstat for this CPU so ignore it
22235 + continue;
22238 + if (i == num_cpus) {
22239 + // Found more cpu_stats than reported CPUs
22240 + break;
22243 + cpu_loads[i++].kstat = kstat;
22248 +static int init_cpu_kstat_counters() {
22249 + static int initialized = 0;
22251 + // Concurrence in this method is prevented by the lock in
22252 + // the calling method get_cpu_load();
22253 + if(!initialized) {
22254 + if ((kstat_ctrl = kstat_open()) != NULL) {
22255 + map_cpu_kstat_counters();
22256 + initialized = 1;
22259 + return initialized ? 0 : -1;
22262 +static void update_cpu_kstat_counters() {
22263 + if(kstat_chain_update(kstat_ctrl) != 0) {
22264 + free(cpu_loads);
22265 + map_cpu_kstat_counters();
22269 +int read_cpustat(cpuload_t *load, cpu_stat_t *cpu_stat) {
22270 + if (load->kstat == NULL) {
22271 + // no handle.
22272 + return -1;
22274 + if (kstat_read(kstat_ctrl, load->kstat, cpu_stat) == -1) {
22275 + // disabling for now, a kstat chain update is likely to happen next time
22276 + load->kstat = NULL;
22277 + return -1;
22279 + return 0;
22282 +double get_single_cpu_load(unsigned int n) {
22283 + cpuload_t *load;
22284 + cpu_stat_t cpu_stat;
22285 + uint_t *usage;
22286 + uint64_t c_idle;
22287 + uint64_t c_total;
22288 + uint64_t d_idle;
22289 + uint64_t d_total;
22290 + int i;
22292 + if (n >= num_cpus) {
22293 + return -1.0;
22296 + load = &cpu_loads[n];
22297 + if (read_cpustat(load, &cpu_stat) < 0) {
22298 + return -1.0;
22301 + usage = cpu_stat.cpu_sysinfo.cpu;
22302 + c_idle = usage[CPU_IDLE];
22304 + for (c_total = 0, i = 0; i < CPU_STATES; i++) {
22305 + c_total += usage[i];
22308 + // Calculate diff against previous snapshot
22309 + d_idle = c_idle - load->last_idle;
22310 + d_total = c_total - load->last_total;
22312 + /** update if weve moved */
22313 + if (d_total > 0) {
22314 + // Save current values for next time around
22315 + load->last_idle = c_idle;
22316 + load->last_total = c_total;
22317 + load->last_ratio = (double) (d_total - d_idle) / d_total;
22320 + return load->last_ratio;
22323 +int get_info(const char *path, void *info, size_t s, off_t o) {
22324 + int fd;
22325 + int ret = 0;
22326 + if ((fd = open(path, O_RDONLY)) < 0) {
22327 + return -1;
22329 + if (pread(fd, info, s, o) != s) {
22330 + ret = -1;
22332 + close(fd);
22333 + return ret;
22336 +#define MIN(a, b) ((a < b) ? a : b)
22338 +static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
22340 +/**
22341 + * Return the cpu load (0-1) for proc number 'which' (or average all if which == -1)
22342 + */
22343 +double get_cpu_load(int which) {
22344 + double load =.0;
22346 + pthread_mutex_lock(&lock);
22347 + if(init_cpu_kstat_counters()==0) {
22349 + update_cpu_kstat_counters();
22351 + if (which == -1) {
22352 + unsigned int i;
22353 + double t;
22355 + for (t = .0, i = 0; i < num_cpus; i++) {
22356 + t += get_single_cpu_load(i);
22359 + // Cap total systemload to 1.0
22360 + load = MIN((t / num_cpus), 1.0);
22361 + } else {
22362 + load = MIN(get_single_cpu_load(which), 1.0);
22364 + } else {
22365 + load = -1.0;
22367 + pthread_mutex_unlock(&lock);
22369 + return load;
22372 +/**
22373 + * Return the cpu load (0-1) for the current process (i.e the JVM)
22374 + * or -1.0 if the get_info() call failed
22375 + */
22376 +double get_process_load(void) {
22377 + psinfo_t info;
22379 + // Get the percentage of "recent cpu usage" from all the lwp:s in the JVM:s
22380 + // process. This is returned as a value between 0.0 and 1.0 multiplied by 0x8000.
22381 + if (get_info("/proc/self/psinfo",&info.pr_pctcpu, sizeof(info.pr_pctcpu), offsetof(psinfo_t, pr_pctcpu)) == 0) {
22382 + return (double) info.pr_pctcpu / 0x8000;
22384 + return -1.0;
22387 +JNIEXPORT jdouble JNICALL
22388 +Java_com_sun_management_internal_OperatingSystemImpl_getCpuLoad0
22389 +(JNIEnv *env, jobject dummy)
22391 + return get_cpu_load(-1);
22394 +JNIEXPORT jdouble JNICALL
22395 +Java_com_sun_management_internal_OperatingSystemImpl_getProcessCpuLoad0
22396 +(JNIEnv *env, jobject dummy)
22398 + return get_process_load();
22401 +JNIEXPORT jdouble JNICALL
22402 +Java_com_sun_management_internal_OperatingSystemImpl_getSingleCpuLoad0
22403 +(JNIEnv *env, jobject mbean, jint cpu_number)
22405 + return -1.0;
22408 +JNIEXPORT jint JNICALL
22409 +Java_com_sun_management_internal_OperatingSystemImpl_getHostConfiguredCpuCount0
22410 +(JNIEnv *env, jobject mbean)
22412 + return -1;
22414 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/jdk.management/unix/native/libmanagement_ext/OperatingSystemImpl.c jdk22u-jdk-22.0.2-ga/src/jdk.management/unix/native/libmanagement_ext/OperatingSystemImpl.c
22415 --- jdk22u-jdk-22.0.2-ga.orig/src/jdk.management/unix/native/libmanagement_ext/OperatingSystemImpl.c 2024-06-04 18:47:50.000000000 +0200
22416 +++ jdk22u-jdk-22.0.2-ga/src/jdk.management/unix/native/libmanagement_ext/OperatingSystemImpl.c 2024-08-17 19:34:03.888580961 +0200
22417 @@ -85,7 +85,63 @@
22418 // true = get available swap in bytes
22419 // false = get total swap in bytes
22420 static jlong get_total_or_available_swap_space_size(JNIEnv* env, jboolean available) {
22421 -#if defined(__linux__)
22422 +#ifdef __solaris__
22423 + long total, avail;
22424 + int nswap, i, count;
22425 + swaptbl_t *stbl;
22426 + char *strtab;
22428 + // First get the number of swap resource entries
22429 + if ((nswap = swapctl(SC_GETNSWP, NULL)) == -1) {
22430 + throw_internal_error(env, "swapctl failed to get nswap");
22431 + return -1;
22433 + if (nswap == 0) {
22434 + return 0;
22437 + // Allocate storage for resource entries
22438 + stbl = (swaptbl_t*) malloc(nswap * sizeof(swapent_t) +
22439 + sizeof(struct swaptable));
22440 + if (stbl == NULL) {
22441 + JNU_ThrowOutOfMemoryError(env, 0);
22442 + return -1;
22445 + // Allocate storage for the table
22446 + strtab = (char*) malloc((nswap + 1) * MAXPATHLEN);
22447 + if (strtab == NULL) {
22448 + free(stbl);
22449 + JNU_ThrowOutOfMemoryError(env, 0);
22450 + return -1;
22453 + for (i = 0; i < (nswap + 1); i++) {
22454 + stbl->swt_ent[i].ste_path = strtab + (i * MAXPATHLEN);
22456 + stbl->swt_n = nswap + 1;
22458 + // Get the entries
22459 + if ((count = swapctl(SC_LIST, stbl)) < 0) {
22460 + free(stbl);
22461 + free(strtab);
22462 + throw_internal_error(env, "swapctl failed to get swap list");
22463 + return -1;
22466 + // Sum the entries to get total and free swap
22467 + total = 0;
22468 + avail = 0;
22469 + for (i = 0; i < count; i++) {
22470 + total += stbl->swt_ent[i].ste_pages;
22471 + avail += stbl->swt_ent[i].ste_free;
22474 + free(stbl);
22475 + free(strtab);
22476 + return available ? ((jlong)avail * page_size) :
22477 + ((jlong)total * page_size);
22478 +#elif defined(__linux__)
22479 int ret;
22480 jlong total = 0, avail = 0;
22482 @@ -134,7 +190,37 @@
22483 Java_com_sun_management_internal_OperatingSystemImpl_getCommittedVirtualMemorySize0
22484 (JNIEnv *env, jobject mbean)
22486 -#if defined(__APPLE__)
22487 +#ifdef __solaris__
22488 + psinfo_t psinfo;
22489 + ssize_t result;
22490 + size_t remaining;
22491 + char* addr;
22492 + int fd;
22494 + fd = open64("/proc/self/psinfo", O_RDONLY, 0);
22495 + if (fd < 0) {
22496 + throw_internal_error(env, "Unable to open /proc/self/psinfo");
22497 + return -1;
22500 + addr = (char *)&psinfo;
22501 + for (remaining = sizeof(psinfo_t); remaining > 0;) {
22502 + result = read(fd, addr, remaining);
22503 + if (result < 0) {
22504 + if (errno != EINTR) {
22505 + close(fd);
22506 + throw_internal_error(env, "Unable to read /proc/self/psinfo");
22507 + return -1;
22509 + } else {
22510 + remaining -= result;
22511 + addr += result;
22515 + close(fd);
22516 + return (jlong) psinfo.pr_size * 1024;
22517 +#elif defined(__APPLE__)
22518 struct task_basic_info t_info;
22519 mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;
22521 @@ -190,7 +276,7 @@
22522 * BSDNOTE: FreeBSD implements _SC_CLK_TCK since FreeBSD 5, so
22523 * add a magic to handle it
22525 -#if defined(_SC_CLK_TCK)
22526 +#if defined(__solaris__) || defined(_SC_CLK_TCK)
22527 clk_tck = (jlong) sysconf(_SC_CLK_TCK);
22528 #elif defined(__linux__) || defined(_ALLBSD_SOURCE)
22529 clk_tck = 100;
22530 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpNet.java jdk22u-jdk-22.0.2-ga/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpNet.java
22531 --- jdk22u-jdk-22.0.2-ga.orig/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpNet.java 2024-06-04 18:47:50.000000000 +0200
22532 +++ jdk22u-jdk-22.0.2-ga/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpNet.java 2024-08-17 19:34:03.889068394 +0200
22533 @@ -44,6 +44,12 @@
22534 /* -- Miscellaneous SCTP utilities -- */
22536 private static boolean IPv4MappedAddresses() {
22537 + if (true) {
22538 + /* FIXME - nonportable hack */
22539 + /* Solaris supports IPv4Mapped Addresses with bindx */
22540 + return true;
22541 + } /* else { //other OS/implementations */
22543 /* lksctp/linux requires Ipv4 addresses */
22544 return false;
22546 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/jdk.sctp/unix/native/libsctp/Sctp.h jdk22u-jdk-22.0.2-ga/src/jdk.sctp/unix/native/libsctp/Sctp.h
22547 --- jdk22u-jdk-22.0.2-ga.orig/src/jdk.sctp/unix/native/libsctp/Sctp.h 2024-06-04 18:47:50.000000000 +0200
22548 +++ jdk22u-jdk-22.0.2-ga/src/jdk.sctp/unix/native/libsctp/Sctp.h 2024-08-17 19:34:03.889534828 +0200
22549 @@ -26,6 +26,48 @@
22550 #ifndef SUN_NIO_CH_SCTP_H
22551 #define SUN_NIO_CH_SCTP_H
22553 +#ifdef __solaris__
22555 +#define _XPG4_2
22556 +#define __EXTENSIONS__
22557 +#include <sys/socket.h>
22558 +#include <netinet/sctp.h>
22559 +#include "jni.h"
22561 +/* Current Solaris headers don't comply with draft rfc */
22562 +#ifndef SCTP_EOF
22563 +#define SCTP_EOF MSG_EOF
22564 +#endif
22566 +#ifndef SCTP_UNORDERED
22567 +#define SCTP_UNORDERED MSG_UNORDERED
22568 +#endif
22570 +/* The current version of the socket API extension shipped with Solaris does
22571 + * not define the following options that the Java API (optionally) supports */
22572 +#ifndef SCTP_EXPLICIT_EOR
22573 +#define SCTP_EXPLICIT_EOR -1
22574 +#endif
22575 +#ifndef SCTP_FRAGMENT_INTERLEAVE
22576 +#define SCTP_FRAGMENT_INTERLEAVE -1
22577 +#endif
22578 +#ifndef SCTP_SET_PEER_PRIMARY_ADDR
22579 +#define SCTP_SET_PEER_PRIMARY_ADDR -1
22580 +#endif
22582 +/* Function types to support dynamic linking of socket API extension functions
22583 + * for SCTP. This is so that there is no linkage depandancy during build or
22584 + * runtime for libsctp.*/
22585 +typedef int sctp_getladdrs_func(int sock, sctp_assoc_t id, void **addrs);
22586 +typedef int sctp_freeladdrs_func(void* addrs);
22587 +typedef int sctp_getpaddrs_func(int sock, sctp_assoc_t id, void **addrs);
22588 +typedef int sctp_freepaddrs_func(void *addrs);
22589 +typedef int sctp_bindx_func(int sock, void *addrs, int addrcnt, int flags);
22590 +typedef int sctp_peeloff_func(int sock, sctp_assoc_t id);
22594 +#else /* __linux__ */
22595 #include <stdint.h>
22596 #include <linux/types.h>
22597 #include <sys/socket.h>
22598 @@ -278,6 +320,8 @@
22599 typedef int sctp_peeloff_func(int sock, sctp_assoc_t id);
22602 +#endif /* __linux__ */
22604 extern sctp_getladdrs_func* nio_sctp_getladdrs;
22605 extern sctp_freeladdrs_func* nio_sctp_freeladdrs;
22606 extern sctp_getpaddrs_func* nio_sctp_getpaddrs;
22607 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/jdk.sctp/unix/native/libsctp/SctpChannelImpl.c jdk22u-jdk-22.0.2-ga/src/jdk.sctp/unix/native/libsctp/SctpChannelImpl.c
22608 --- jdk22u-jdk-22.0.2-ga.orig/src/jdk.sctp/unix/native/libsctp/SctpChannelImpl.c 2024-06-04 18:47:50.000000000 +0200
22609 +++ jdk22u-jdk-22.0.2-ga/src/jdk.sctp/unix/native/libsctp/SctpChannelImpl.c 2024-08-17 19:34:03.889998429 +0200
22610 @@ -331,11 +331,10 @@
22611 break;
22612 case SCTP_ADDR_MADE_PRIM :
22613 event = sun_nio_ch_sctp_PeerAddrChange_SCTP_ADDR_MADE_PRIM;
22614 +#ifdef __linux__ /* Solaris currently doesn't support SCTP_ADDR_CONFIRMED */
22615 break;
22616 -#ifdef __linux__
22617 case SCTP_ADDR_CONFIRMED :
22618 event = sun_nio_ch_sctp_PeerAddrChange_SCTP_ADDR_CONFIRMED;
22619 - break;
22620 #endif /* __linux__ */
22623 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/jdk.sctp/unix/native/libsctp/SctpNet.c jdk22u-jdk-22.0.2-ga/src/jdk.sctp/unix/native/libsctp/SctpNet.c
22624 --- jdk22u-jdk-22.0.2-ga.orig/src/jdk.sctp/unix/native/libsctp/SctpNet.c 2024-06-04 18:47:50.000000000 +0200
22625 +++ jdk22u-jdk-22.0.2-ga/src/jdk.sctp/unix/native/libsctp/SctpNet.c 2024-08-17 19:34:03.890467296 +0200
22626 @@ -371,7 +371,11 @@
22627 int i, addrCount;
22628 jobjectArray isaa;
22630 +#ifdef __solaris__
22631 + if ((addrCount = nio_sctp_getladdrs(fd, 0, (void **)&addr_buf)) == -1) {
22632 +#else /* __linux__ */
22633 if ((addrCount = nio_sctp_getladdrs(fd, 0, (struct sockaddr **)&addr_buf)) == -1) {
22634 +#endif
22635 sctpHandleSocketError(env, errno);
22636 return NULL;
22638 @@ -416,7 +420,11 @@
22639 int i, addrCount;
22640 jobjectArray isaa;
22642 +#if defined(__solaris__)
22643 + if ((addrCount = nio_sctp_getpaddrs(fd, id, (void **)&addr_buf)) == -1) {
22644 +#else /* __linux__ */
22645 if ((addrCount = nio_sctp_getpaddrs(fd, id, (struct sockaddr **)&addr_buf)) == -1) {
22646 +#endif
22647 sctpHandleSocketError(env, errno);
22648 return NULL;
22650 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/jdk.security.auth/share/classes/com/sun/security/auth/module/Krb5LoginModule.java jdk22u-jdk-22.0.2-ga/src/jdk.security.auth/share/classes/com/sun/security/auth/module/Krb5LoginModule.java
22651 --- jdk22u-jdk-22.0.2-ga.orig/src/jdk.security.auth/share/classes/com/sun/security/auth/module/Krb5LoginModule.java 2024-06-04 18:47:50.000000000 +0200
22652 +++ jdk22u-jdk-22.0.2-ga/src/jdk.security.auth/share/classes/com/sun/security/auth/module/Krb5LoginModule.java 2024-08-17 19:34:03.891108664 +0200
22653 @@ -104,7 +104,7 @@
22654 * to false if you do not want this module to use the ticket cache.
22655 * (Default is False).
22656 * This module will search for the ticket
22657 - * cache in the following locations: On Linux
22658 + * cache in the following locations: On Solaris and Linux
22659 * it will look for the ticket cache in /tmp/krb5cc_{@code uid}
22660 * where the uid is numeric user identifier. If the ticket cache is
22661 * not available in the above location, or if we are on a
22662 diff -Nru jdk22u-jdk-22.0.2-ga.orig/src/jdk.security.auth/unix/native/libjaas/Unix.c jdk22u-jdk-22.0.2-ga/src/jdk.security.auth/unix/native/libjaas/Unix.c
22663 --- jdk22u-jdk-22.0.2-ga.orig/src/jdk.security.auth/unix/native/libjaas/Unix.c 2024-06-04 18:47:50.000000000 +0200
22664 +++ jdk22u-jdk-22.0.2-ga/src/jdk.security.auth/unix/native/libjaas/Unix.c 2024-08-17 19:34:03.891558631 +0200
22665 @@ -32,6 +32,10 @@
22666 #include <stdlib.h>
22667 #include <string.h>
22669 +/* For POSIX-compliant getpwuid_r on Solaris */
22670 +#if defined(__solaris__)
22671 +#define _POSIX_PTHREAD_SEMANTICS
22672 +#endif
22673 #include <pwd.h>