diff --git a/.hgtags b/.hgtags index 90b30b8f1df3ee985d0820096b5c19c42d77b918..684719db0b2ac8a3f0ea1c0b49ecc4e148769886 100644 --- a/.hgtags +++ b/.hgtags @@ -100,3 +100,6 @@ ac311eb325bfc763698219252bf3cee9e091f3af jdk7-b122 869190935eedee7750d955019ab2a1b80f0a13a8 jdk7-b123 1c72adc9d5f331cb882cf5354ba0dcb118a60b23 jdk7-b124 0a56bdd709d01c1663047e55201d19152ffd3d69 jdk7-b125 +8361ef97a0f90086c9048beaf7cea1a37216c4cd jdk7-b126 +29e09de1d0b4f84faea114cf10b3ec08b59acc4e jdk7-b127 +f08682e23279d6cccbdcafda1eb0647ba4900874 jdk7-b128 diff --git a/make/Makefile b/make/Makefile index 36bf631d5b807b6431bccc7e25c61cd0befb4b61..74651fca20b803e7fef15c98551392eda791f36f 100644 --- a/make/Makefile +++ b/make/Makefile @@ -100,7 +100,6 @@ CACERTS_FILE.desc = Location of certificates file DEVTOOLS_PATH.desc = Directory containing zip and unzip CUPS_HEADERS_PATH.desc = Include directory location for CUPS header files DXSDK_PATH.desc = Root directory of DirectX SDK -MSVCRT_DLL_PATH.desc = Directory containing mscvrt.dll # Make variables to print out (description and value) VARIABLE_PRINTVAL_LIST += \ @@ -133,12 +132,10 @@ VARIABLE_CHECKFIL_LIST += \ ifeq ($(PLATFORM), windows) VARIABLE_PRINTVAL_LIST += \ - DXSDK_PATH \ - MSVCRT_DLL_PATH + DXSDK_PATH VARIABLE_CHECKDIR_LIST += \ - DXSDK_PATH \ - MSVCRT_DLL_PATH + DXSDK_PATH endif diff --git a/make/com/sun/java/pack/Makefile b/make/com/sun/java/pack/Makefile index 6b5b0bfc24130e0d3440bbadfa81469c202af874..e7fe8d44b7627ee774977ba46a5665a217077fd3 100644 --- a/make/com/sun/java/pack/Makefile +++ b/make/com/sun/java/pack/Makefile @@ -155,6 +155,7 @@ ifdef MT $(MT) /manifest $(OBJDIR)/unpack200$(EXE_SUFFIX).manifest /outputresource:$(TEMPDIR)/unpack200$(EXE_SUFFIX);#1 endif $(CP) $(TEMPDIR)/unpack200$(EXE_SUFFIX) $(UNPACK_EXE) + @$(call binary_file_verification,$@) $(install-module-file) ifeq ($(PLATFORM), windows) diff --git a/make/common/Defs-linux.gmk b/make/common/Defs-linux.gmk index 6acbaa4b6860c3c8a318333b911149a22bcf87c1..4541ec8b82974534c5b926c2cb2ec3c4866af64c 100644 --- a/make/common/Defs-linux.gmk +++ b/make/common/Defs-linux.gmk @@ -74,15 +74,6 @@ SCRIPT_SUFFIX = CC_OBJECT_OUTPUT_FLAG = -o #trailing blank required! CC_PROGRAM_OUTPUT_FLAG = -o #trailing blank required! -# -# Default HPI libraries. Build will build only native, unless -# overriden at the make command line. This makes it convenient for -# people doing, say, a pthreads port -- they can create a posix -# directory here, and say "gnumake HPIS=posix" at the top -# level. -# -HPIS = native - # # Default optimization # diff --git a/make/common/Defs-solaris.gmk b/make/common/Defs-solaris.gmk index 637bff575fcde54ada9b86e46b17ae4cefaed336..50e5c4bb1def89de168d8261abb4255a29eed2e6 100644 --- a/make/common/Defs-solaris.gmk +++ b/make/common/Defs-solaris.gmk @@ -74,15 +74,6 @@ SCRIPT_SUFFIX = CC_OBJECT_OUTPUT_FLAG = -o #trailing blank required! CC_PROGRAM_OUTPUT_FLAG = -o #trailing blank required! -# -# Default HPI libraries. Build will build only native unless -# overriden at the make command line. This makes it convenient for -# people doing, say, a pthreads port -- they can create a posix -# directory here, and say "gnumake HPIS=posix" at the top -# level. -# -HPIS = native - # # Java default optimization (-x04/-O2) etc. Applies to the VM. # diff --git a/make/common/Defs-windows.gmk b/make/common/Defs-windows.gmk index 63f19d3e7946d4f6c5a3984ec3e7699b3734cbf2..7899b0e668de22375fe587effaaca0faa2114a39 100644 --- a/make/common/Defs-windows.gmk +++ b/make/common/Defs-windows.gmk @@ -43,7 +43,6 @@ FDDLIBM_SUFFIX = lib # The suffix applied to scripts (.bat for windows, nothing for unix) SCRIPT_SUFFIX = .bat -HPIS = windows # LIB_LOCATION, which for windows identifies where .exe files go, may be # set by each GNUmakefile. The default is BINDIR. ifndef LIB_LOCATION @@ -68,28 +67,27 @@ PLATFORM_INCLUDE = $(INCLUDEDIR)/$(PLATFORM_INCLUDE_NAME) # The following DLL's are considered MS runtime libraries and should # not to be REBASEd, see deploy/make/common/Release.gmk. -# msvcrt.dll, msvcrnn.dll [msvcr71 or msvcr80 or msvcr90] : Microsoft runtimes -MS_RUNTIME_LIBRARIES = msvcrt.dll +# msvcr*.dll: Microsoft runtimes ifeq ($(ARCH_DATA_MODEL), 32) ifeq ($(COMPILER_VERSION), VS2003) MSVCRNN_DLL = msvcr71.dll MSVCPNN_DLL = msvcp71.dll - MS_RUNTIME_LIBRARIES += $(MSVCRNN_DLL) + MS_RUNTIME_LIBRARIES = msvcrt.dll $(MSVCRNN_DLL) endif ifeq ($(COMPILER_VERSION), VS2005) MSVCRNN_DLL = msvcr80.dll MSVCPNN_DLL = msvcp80.dll - MS_RUNTIME_LIBRARIES += $(MSVCRNN_DLL) + MS_RUNTIME_LIBRARIES = msvcrt.dll $(MSVCRNN_DLL) endif ifeq ($(COMPILER_VERSION), VS2008) MSVCRNN_DLL = msvcr90.dll MSVCPNN_DLL = msvcp90.dll - MS_RUNTIME_LIBRARIES += $(MSVCRNN_DLL) + MS_RUNTIME_LIBRARIES = msvcrt.dll $(MSVCRNN_DLL) endif ifeq ($(COMPILER_VERSION), VS2010) MSVCRNN_DLL = msvcr100.dll MSVCPNN_DLL = msvcp100.dll - MS_RUNTIME_LIBRARIES += $(MSVCRNN_DLL) + MS_RUNTIME_LIBRARIES = $(MSVCRNN_DLL) endif endif @@ -97,12 +95,12 @@ ifeq ($(ARCH_DATA_MODEL), 64) ifeq ($(COMPILER_VERSION), VS2008) MSVCRNN_DLL = msvcr90.dll MSVCPNN_DLL = msvcp90.dll - MS_RUNTIME_LIBRARIES += $(MSVCRNN_DLL) + MS_RUNTIME_LIBRARIES = msvcrt.dll $(MSVCRNN_DLL) endif ifeq ($(COMPILER_VERSION), VS2010) MSVCRNN_DLL = msvcr100.dll MSVCPNN_DLL = msvcp100.dll - MS_RUNTIME_LIBRARIES += $(MSVCRNN_DLL) + MS_RUNTIME_LIBRARIES = $(MSVCRNN_DLL) endif endif @@ -284,7 +282,7 @@ ifeq ($(MFC_DEBUG), true) MS_RUNTIME_OPTION=-MTd else # This MS debugging flag forces a dependence on the debug - # version of the runtime library (MSVCRTD.DLL), as does -MDd. + # version of the runtime library (MSVCR*D.DLL), as does -MDd. # We cannot re-distribute this debug runtime. MS_RUNTIME_OPTION=-MDd endif diff --git a/make/common/Defs.gmk b/make/common/Defs.gmk index 29abffd261ea1aabf555ad720dd96f6740602e66..6854d4e8708907ebf37882f5fc93da66c3092dfc 100644 --- a/make/common/Defs.gmk +++ b/make/common/Defs.gmk @@ -271,10 +271,9 @@ DEMOSRCDIR = $(SHARE_SRC)/demo # An attempt is made to generate unique enough directories for the # generated files to not have name collisisons. Most build units # defines PRODUCT (except Release.gmk), but then they may or may -# not define PACKAGE, THREADIR (only HPI uses this), PROGRAM, and -# LIBRARY. This code chunk attempts to generate a unique -# OBJDIR/CLASSHDRDIR for each build unit based on which of those -# values are set within each build unit. +# not define PACKAGE, PROGRAM, and LIBRARY. This code attempts to +# generate a unique OBJDIR/CLASSHDRDIR for each build unit based +# on which of those values are set within each build unit. UNIQUE_LOCATION_STRING = tmp @@ -298,10 +297,6 @@ ifneq ($(LIBRARY),) endif endif -ifneq ($(THREADDIR),) - UNIQUE_LOCATION_STRING += /$(THREADDIR) -endif - # # Build units may or may not define MODULE. Default to "other". # diff --git a/make/common/Demo.gmk b/make/common/Demo.gmk index 0ba5bc19707a45e9584362883f67821b2fe236dc..24ee29f0ba55fe439561b0861f6eb76c57c9a245 100644 --- a/make/common/Demo.gmk +++ b/make/common/Demo.gmk @@ -73,8 +73,11 @@ DEMO_BUILD_AREA = $(DEMOCLASSDIR)/$(PRODUCT)/$(DEMONAME) # Destination "src" directory DEMO_BUILD_SRCDIR = $(DEMO_BUILD_AREA)/src -DEMO_BUILD_SRCZIP = $(DEMO_BUILD_AREA)/src.zip -DEMO_SOURCE_ZIP = $(DEMO_DESTDIR)/src.zip + +ifndef DEMO_SKIP_SRCZIP + DEMO_BUILD_SRCZIP = $(DEMO_BUILD_AREA)/src.zip + DEMO_SOURCE_ZIP = $(DEMO_DESTDIR)/src.zip +endif # Place to hold the jar image we are creating DEMO_JAR_IMAGE = $(DEMO_BUILD_AREA)/jar_image @@ -258,14 +261,16 @@ $(DEMO_JAR): \ endif -# Create a src.zip file -$(DEMO_BUILD_SRCZIP): $(DEMO_FULL_SOURCES) +ifndef DEMO_SKIP_SRCZIP + # Create a src.zip file + $(DEMO_BUILD_SRCZIP): $(DEMO_FULL_SOURCES) @$(prep-target) $(CD) $(DEMO_BUILD_AREA)/src && $(ZIPEXE) -q -r ../$(@F) . -# Install the destination src.zip file and create the src tree -$(DEMO_SOURCE_ZIP): $(DEMO_BUILD_SRCZIP) + # Install the destination src.zip file and create the src tree + $(DEMO_SOURCE_ZIP): $(DEMO_BUILD_SRCZIP) $(install-file) +endif # Native library building ifdef DEMO_LIBRARY @@ -289,6 +294,7 @@ $(DEMO_LIBRARY): $(DEMO_FULL_OBJECTS) @$(prep-target) $(LINK.demo) $(SHARED_LIBRARY_FLAG) $(CC_PROGRAM_OUTPUT_FLAG)$@ \ $(DEMO_FULL_OBJECTS) $(LDLIBS.demo) + @$(call binary_file_verification,$@) # Generation of any javah include file, make sure objects are dependent on it ifdef DEMO_NATIVECLASS @@ -362,7 +368,7 @@ clean clobber: $(RM) -r $(DEMO_BUILD_AREA) $(RM) -r $(DEMO_DESTDIR) -# This should not be needed, but some versions of GNU amke have a bug that +# This should not be needed, but some versions of GNU make have a bug that # sometimes deleted these files for some strange and unknown reason # (GNU make version 3.78.1 has the problem, GNU make version 3.80 doesn't?) .PRECIOUS: $(DEMO_FULL_SOURCES) $(DEMO_BUILD_SRCZIP) $(DEMO_SOURCE_ZIP) diff --git a/make/common/Library.gmk b/make/common/Library.gmk index c70d0c4daf70e70134decbe08be8a950b0290eee..5fbed139ce546637a529b977318ea17a4a975649 100644 --- a/make/common/Library.gmk +++ b/make/common/Library.gmk @@ -167,6 +167,7 @@ $(ACTUAL_LIBRARY):: $(OBJDIR)/$(LIBRARY).lcf $(LFLAGS) @$(OBJDIR)/$(LIBRARY).lcf \ $(OTHER_LCF) $(JAVALIB) $(LDLIBS) $(CP) $(OBJDIR)/$(@F) $@ + @$(call binary_file_verification,$@) $(install-module-file) $(CP) $(OBJDIR)/$(LIBRARY).map $(@D) $(CP) $(OBJDIR)/$(LIBRARY).pdb $(@D) @@ -233,6 +234,7 @@ ifeq ($(LIBRARY), fdlibm) $(AR) -r $@ $(FILES_o) else # LIBRARY $(LINKER) $(SHARED_LIBRARY_FLAG) -o $@ $(FILES_o) $(LDLIBS) + @$(call binary_file_verification,$@) $(install-module-file) ifeq ($(WRITE_LIBVERSION),true) $(MCS) -d -a "$(FULL_VERSION)" $@ diff --git a/make/common/Modules.gmk b/make/common/Modules.gmk index 0bca87467f03ee31bd42e18de987f8e22c75d000..9bf90db293241003f05a3363727d1c4504f3db1e 100644 --- a/make/common/Modules.gmk +++ b/make/common/Modules.gmk @@ -73,47 +73,20 @@ module-image-jdk:: initial-module-image-jdk trim-module-image-jdk process-module # # Paths to these files we need -JDK_MODULE_LICENSES = $(LICENSE_DOCLIST_JDK:%=$(JDK_MODULE_IMAGE_DIR)/%) -JDK_MODULE_64_LICENSES = $(LICENSE_DOCLIST_JDK:%=$(JDK_MODULE_IMAGE_DIR)/%64) -JDK_MODULE_DOCFILES = $(OTHER_DOCLIST_JDK:%=$(JDK_MODULE_IMAGE_DIR)/%) - -JRE_MODULE_LICENSES = $(LICENSE_DOCLIST_JRE:%=$(JRE_MODULE_IMAGE_DIR)/%) -JRE_MODULE_64_LICENSES = $(LICENSE_DOCLIST_JRE:%=$(JRE_MODULE_IMAGE_DIR)/%64) -JRE_MODULE_DOCFILES = $(OTHER_DOCLIST_JRE:%=$(JRE_MODULE_IMAGE_DIR)/%) -JRE_MODULE_DOCFILES += $(JRE_NAMECHANGE_DOCLIST:%=$(JRE_MODULE_IMAGE_DIR)/%$(TEXT_SUFFIX)) +JDK_MODULE_DOCFILES = $(IMAGE_DOCLIST_JDK:%=$(JDK_MODULE_IMAGE_DIR)/%) +JRE_MODULE_DOCFILES = $(IMAGE_DOCLIST_JRE:%=$(JRE_MODULE_IMAGE_DIR)/%) ###### RULES # JDK files $(JDK_MODULE_IMAGE_DIR)/%: $(SHARE_JDK_DOC_SRC)/% $(process-doc-file) -# Removes LICENSE_VERSION or not -ifdef LICENSE_VERSION -$(JDK_MODULE_IMAGE_DIR)/%: $(SHARE_JDK_DOC_SRC)/%$(LICENSE_VERSION) - $(process-doc-file) -$(JDK_MODULE_IMAGE_DIR)/%64: $(SHARE_JDK_DOC_SRC)/%$(LICENSE_VERSION) - $(process-doc-file) -else -$(JDK_MODULE_IMAGE_DIR)/%64: $(SHARE_JDK_DOC_SRC)/% - $(process-doc-file) -endif # JRE files $(JRE_MODULE_IMAGE_DIR)/%: $(SHARE_JRE_DOC_SRC)/% $(process-doc-file) -# Add $(TEXT_SUFFIX) suffix -ifdef TEXT_SUFFIX -$(JRE_MODULE_IMAGE_DIR)/%$(TEXT_SUFFIX): $(SHARE_JRE_DOC_SRC)/% - $(process-doc-file) -endif -# Removes LICENSE_VERSION or not -ifdef LICENSE_VERSION -$(JRE_MODULE_IMAGE_DIR)/%: $(SHARE_JRE_DOC_SRC)/%$(LICENSE_VERSION) - $(process-doc-file) -$(JRE_MODULE_IMAGE_DIR)/%64: $(SHARE_JRE_DOC_SRC)/%$(LICENSE_VERSION) - $(process-doc-file) -else -$(JRE_MODULE_IMAGE_DIR)/%64: $(SHARE_JRE_DOC_SRC)/% +ifeq ($(PLATFORM), windows) +$(JRE_MODULE_IMAGE_DIR)/README.txt: $(SHARE_JRE_DOC_SRC)/README $(process-doc-file) endif @@ -157,8 +130,7 @@ initial-module-image-jre-setup: $(MKDIR) -p $(JRE_MODULE_IMAGE_DIR) # 64-bit solaris jre image contains only the 64-bit add-on files. -initial-module-image-jre-sol64:: initial-module-image-jre-setup \ - $(JRE_MODULE_LICENSES) $(JRE_MODULE_64_LICENSES) +initial-module-image-jre-sol64:: initial-module-image-jre-setup @# Use tar instead of cp to preserve the symbolic links for dir in bin lib ; do \ ( $(CD) $(OUTPUTDIR) && \ @@ -174,7 +146,7 @@ initial-module-image-jre-sol64:: initial-module-image-jre-setup \ # Construct an initial jre image (initial jdk jre) no trimming or stripping initial-module-image-jre:: initial-module-image-jre-setup \ - $(JRE_LICENSES) $(JRE_MODULE_DOCFILES) \ + $(JRE_MODULE_DOCFILES) \ $(BUILDMETAINDEX_JARFILE) @# Copy in bin directory $(CD) $(OUTPUTDIR) && $(FIND) bin -depth | $(CPIO) -pdum $(JRE_MODULE_IMAGE_DIR) @@ -222,7 +194,7 @@ ifeq ($(PLATFORM), windows) @# Remove certain *.lib files $(CD) $(JRE_MODULE_IMAGE_DIR)/lib && \ $(RM) java.$(LIB_SUFFIX) jvm.$(LIB_SUFFIX) \ - hpi.$(LIB_SUFFIX) awt.$(LIB_SUFFIX) jawt.$(LIB_SUFFIX) + awt.$(LIB_SUFFIX) jawt.$(LIB_SUFFIX) ifeq ($(ARCH_DATA_MODEL), 32) @# The Java Kernel JRE image ships with a special VM. It is not included @# in the full JRE image, so remove it. Also, is it only for 32-bit windows. @@ -310,8 +282,7 @@ initial-module-image-jdk64-bindemos: # Solaris 64 bit image is special initial-module-image-jdk-sol64:: initial-module-image-jdk-setup \ - initial-module-image-jdk64-bindemos \ - $(JDK_MODULE_LICENSES) $(JDK_MODULARLIZED_64_LICENSES) + initial-module-image-jdk64-bindemos # DB files to add ifeq ($(OPENJDK),true) @@ -335,7 +306,7 @@ endif # Standard jdk image initial-module-image-jdk:: initial-module-image-jdk-setup \ initial-module-image-jdk-db \ - $(JDK_MODULE_LICENSES) $(JDK_MODULE_DOCFILES) + $(JDK_MODULE_DOCFILES) $(MKDIR) $(JDK_MODULE_IMAGE_DIR)/lib @# @# copy jdk modules to jdk/lib @@ -415,8 +386,7 @@ endif # !windows trim-module-image-jdk:: @# Remove tools that should not be part of SDK. for t in $(NOTJDKTOOLS); do \ - $(RM) $(JDK_MODULE_IMAGE_DIR)/bin/$${t}$(EXE_SUFFIX) \ - $(JDK_MODULE_IMAGE_DIR)/bin/*/native_threads/$${t}$(EXE_SUFFIX); \ + $(RM) $(JDK_MODULE_IMAGE_DIR)/bin/$${t}$(EXE_SUFFIX); \ done # Get list of Elf files in the jdk diff --git a/make/common/Program.gmk b/make/common/Program.gmk index 751f0fe6898e52d287c4ecfd5a1f2046e55524c2..5700e32c89d6cb533e69c5a71d9641e19f1d13df 100644 --- a/make/common/Program.gmk +++ b/make/common/Program.gmk @@ -160,6 +160,7 @@ $(OBJDIR)/$(PROGRAM)$(EXE_SUFFIX):: $(OBJDIR)/$(PROGRAM).lcf $(FILES_o) $(JLI_LC ifdef MT $(MT) /manifest $(OBJDIR)/$(PROGRAM).exe.manifest /outputresource:$@;#1 endif + @$(call binary_file_verification,$@) else # PLATFORM @@ -184,6 +185,7 @@ $(ACTUAL_PROGRAM):: $(FILES_o) @$(MKDIR) -p $(TEMPDIR) $(LINK_PRE_CMD) $(CC) $(CC_OBJECT_OUTPUT_FLAG)$@ $(LDFLAGS) \ $(FILES_o) $(THREADLIBS) $(LDLIBS) + @$(call binary_file_verification,$@) $(install-module-file) endif # PLATFORM diff --git a/make/common/Release.gmk b/make/common/Release.gmk index 834d3379875bb1fa17393ca2a05e0ffe9b5d189e..9af023f2c54139e2dab2f09709d082bc491cd35f 100644 --- a/make/common/Release.gmk +++ b/make/common/Release.gmk @@ -26,6 +26,9 @@ include $(JDK_TOPDIR)/make/docs/CORE_PKGS.gmk include $(JDK_TOPDIR)/make/docs/NON_CORE_PKGS.gmk +# What jdk version are we building +THIS_JDK_VERSION := $(JDK_MAJOR_VERSION).$(JDK_MINOR_VERSION).$(JDK_MICRO_VERSION) + # # Perform release engineering tasks. # @@ -72,14 +75,6 @@ endif JTG_DOCS = $(JDK_TOPDIR)/src/solaris/doc -#We use this for man page header -jdkversion := $(JDK_MAJOR_VERSION).$(JDK_MINOR_VERSION).$(JDK_MICRO_VERSION) - -# Text documents on windows use this suffix -ifeq ($(PLATFORM), windows) - TEXT_SUFFIX = .txt -endif - # The base names of all the license and document files for the jdk and jre # (These files get placed in the jdk and jre install images) ifdef OPENJDK @@ -87,53 +82,28 @@ ifdef OPENJDK SHARE_JDK_DOC_SRC = $(JDK_TOPDIR) SHARE_JRE_DOC_SRC = $(JDK_TOPDIR) # Same files for jdk and jre, no name changes - LICENSE_DOCLIST_JDK = LICENSE ASSEMBLY_EXCEPTION - LICENSE_DOCLIST_JRE = LICENSE ASSEMBLY_EXCEPTION - OTHER_DOCLIST_JDK = THIRD_PARTY_README - OTHER_DOCLIST_JRE = THIRD_PARTY_README + IMAGE_DOCLIST_JDK = LICENSE ASSEMBLY_EXCEPTION THIRD_PARTY_README + IMAGE_DOCLIST_JRE = LICENSE ASSEMBLY_EXCEPTION THIRD_PARTY_README else # Where to find these files SHARE_JDK_DOC_SRC = $(CLOSED_SHARE_SRC)/doc/jdk SHARE_JRE_DOC_SRC = $(CLOSED_SHARE_SRC)/doc/jre - # Select the pre-release or FCS license version based on the build milestone. - LICENSE_VERSION=.pre - ifeq ($(MILESTONE), fcs) - LICENSE_VERSION=.fcs - endif + IMAGE_DOCLIST_JDK = COPYRIGHT README.html THIRDPARTYLICENSEREADME.txt + IMAGE_DOCLIST_JRE = COPYRIGHT Welcome.html THIRDPARTYLICENSEREADME.txt ifeq ($(PLATFORM), windows) - LICENSE_DOCLIST_JDK = $(subst $(LICENSE_VERSION),,\ - $(shell $(CD) $(SHARE_JDK_DOC_SRC) && \ - $(LS) *LICENSE*$(LICENSE_VERSION))) - LICENSE_DOCLIST_JRE = $(subst $(LICENSE_VERSION),,\ - $(shell $(CD) $(SHARE_JRE_DOC_SRC) && \ - $(LS) *LICENSE*$(LICENSE_VERSION))) + IMAGE_DOCLIST_JRE += README.txt else - LICENSE_DOCLIST_JDK = $(subst $(LICENSE_VERSION),,\ - $(shell $(CD) $(SHARE_JDK_DOC_SRC) && \ - $(LS) *LICENSE*$(LICENSE_VERSION) | $(GREP) -v rtf)) - LICENSE_DOCLIST_JRE = $(subst $(LICENSE_VERSION),,\ - $(shell $(CD) $(SHARE_JRE_DOC_SRC) && \ - $(LS) *LICENSE*$(LICENSE_VERSION) | $(GREP) -v rtf)) + IMAGE_DOCLIST_JRE += README endif - OTHER_DOCLIST_JDK = COPYRIGHT README.html README_ja.html README_zh_CN.html - OTHER_DOCLIST_JRE = COPYRIGHT Welcome.html - JRE_NAMECHANGE_DOCLIST = README endif # Paths to these files we need -JDK_LICENSES = $(LICENSE_DOCLIST_JDK:%=$(JDK_IMAGE_DIR)/%) -JDK64_LICENSES = $(LICENSE_DOCLIST_JDK:%=$(JDK_IMAGE_DIR)/%64) -JDK_DOCFILES = $(OTHER_DOCLIST_JDK:%=$(JDK_IMAGE_DIR)/%) - -JRE_LICENSES = $(LICENSE_DOCLIST_JRE:%=$(JRE_IMAGE_DIR)/%) -JRE64_LICENSES = $(LICENSE_DOCLIST_JRE:%=$(JRE_IMAGE_DIR)/%64) -JRE_DOCFILES = $(OTHER_DOCLIST_JRE:%=$(JRE_IMAGE_DIR)/%) -JRE_DOCFILES += $(JRE_NAMECHANGE_DOCLIST:%=$(JRE_IMAGE_DIR)/%$(TEXT_SUFFIX)) +JDK_DOCFILES = $(IMAGE_DOCLIST_JDK:%=$(JDK_IMAGE_DIR)/%) +JRE_DOCFILES = $(IMAGE_DOCLIST_JRE:%=$(JRE_IMAGE_DIR)/%) # absolute directory names: note, these must exist prior to build # time - they are created in the main Makefile. JRE_IMAGE_BINDIR = $(JRE_IMAGE_DIR)/bin -JRE_IMAGE_THREADIR = $(JRE_IMAGE_DIR)/bin/*/native_threads MAINMANIFEST = $(JDK_TOPDIR)/make/tools/manifest.mf BEANMANIFEST = $(JDK_TOPDIR)/make/javax/swing/beaninfo/manifest @@ -214,7 +184,7 @@ for manbase in $(MANBASEDIRS:%=%/$(MAN1SUBDIR)) ; do \ $(MKDIR) -p $1/man/$${ja_dir}/man1; \ $(CAT) $${manbase}/ja/$${manpage} \ | $(NATIVE2ASCII) -encoding $(JA_SOURCE_ENCODING) \ - | $(SED) 's/@@VERSION@@/$(jdkversion)/g' \ + | $(SED) 's/@@VERSION@@/$(THIS_JDK_VERSION)/g' \ | $(NATIVE2ASCII) -reverse -encoding $${ja_encoding} \ > $1/man/$${ja_dir}/man1/$${manpage}; \ done; \ @@ -244,6 +214,7 @@ images images-clobber \ initial-image-jre initial-image-jdk \ initial-image-jre-sol64 initial-image-jdk-sol64 \ trim-image-jre trim-image-jdk \ +identify-image-jre identify-image-jdk \ process-image-jre process-image-jdk \ compare-image \ sec-files sec-files-win jgss-files :: @@ -253,11 +224,12 @@ sec-files sec-files-win jgss-files :: images:: sanity-images post-sanity-images \ $(INITIAL_IMAGE_JRE) $(INITIAL_IMAGE_JDK) \ trim-image-jre trim-image-jdk \ + identify-image-jre identify-image-jdk \ process-image-jre process-image-jdk sec-files sec-files-win jgss-files # Don't use these -image-jre:: initial-image-jre trim-image-jre process-image-jre -image-jdk:: initial-image-jdk trim-image-jdk process-image-jdk +image-jre:: initial-image-jre trim-image-jre identify-image-jre process-image-jre +image-jdk:: initial-image-jdk trim-image-jdk identify-image-jdk process-image-jdk # # Sources we ship in the SDK. @@ -504,33 +476,12 @@ endef # JDK files $(JDK_IMAGE_DIR)/%: $(SHARE_JDK_DOC_SRC)/% $(process-doc-file) -# Removes LICENSE_VERSION or not -ifdef LICENSE_VERSION -$(JDK_IMAGE_DIR)/%: $(SHARE_JDK_DOC_SRC)/%$(LICENSE_VERSION) - $(process-doc-file) -$(JDK_IMAGE_DIR)/%64: $(SHARE_JDK_DOC_SRC)/%$(LICENSE_VERSION) - $(process-doc-file) -else -$(JDK_IMAGE_DIR)/%64: $(SHARE_JDK_DOC_SRC)/% - $(process-doc-file) -endif # JRE files $(JRE_IMAGE_DIR)/%: $(SHARE_JRE_DOC_SRC)/% $(process-doc-file) -# Add $(TEXT_SUFFIX) suffix -ifdef TEXT_SUFFIX -$(JRE_IMAGE_DIR)/%$(TEXT_SUFFIX): $(SHARE_JRE_DOC_SRC)/% - $(process-doc-file) -endif -# Removes LICENSE_VERSION or not -ifdef LICENSE_VERSION -$(JRE_IMAGE_DIR)/%: $(SHARE_JRE_DOC_SRC)/%$(LICENSE_VERSION) - $(process-doc-file) -$(JRE_IMAGE_DIR)/%64: $(SHARE_JRE_DOC_SRC)/%$(LICENSE_VERSION) - $(process-doc-file) -else -$(JRE_IMAGE_DIR)/%64: $(SHARE_JRE_DOC_SRC)/% +ifeq ($(PLATFORM), windows) +$(JRE_IMAGE_DIR)/README.txt: $(SHARE_JRE_DOC_SRC)/README $(process-doc-file) endif @@ -738,8 +689,7 @@ initial-image-jre-setup: $(MKDIR) -p $(JRE_IMAGE_DIR) # 64-bit solaris jre image contains only the 64-bit add-on files. -initial-image-jre-sol64:: initial-image-jre-setup \ - $(JRE_LICENSES) $(JRE64_LICENSES) +initial-image-jre-sol64:: initial-image-jre-setup @# Use tar instead of cp to preserve the symbolic links for dir in bin lib ; do \ ( $(CD) $(OUTPUTDIR) && \ @@ -760,7 +710,7 @@ initial-image-jre-sol64:: initial-image-jre-setup \ # See "initial-image-jdk-setup" for an explanation of the rm of # drive names like C: initial-image-jre:: initial-image-jre-setup \ - $(JRE_LICENSES) $(JRE_DOCFILES) \ + $(JRE_DOCFILES) \ $(RT_JAR) $(RESOURCES_JAR) $(JSSE_JAR) \ $(BUILDMETAINDEX_JARFILE) @# Copy in bin directory @@ -802,7 +752,7 @@ ifeq ($(PLATFORM), windows) @# Remove certain *.lib files $(CD) $(JRE_IMAGE_DIR)/lib && \ $(RM) java.$(LIB_SUFFIX) jvm.$(LIB_SUFFIX) \ - hpi.$(LIB_SUFFIX) awt.$(LIB_SUFFIX) jawt.$(LIB_SUFFIX) + awt.$(LIB_SUFFIX) jawt.$(LIB_SUFFIX) ifeq ($(ARCH_DATA_MODEL), 32) @# The Java Kernel JRE image ships with a special VM. It is not included @# in the full JRE image, so remove it. Also, is it only for 32-bit windows. @@ -836,11 +786,14 @@ else # PLATFORM endif endif # PLATFORM -# Get list of all Elf files in the jre -JRE_ELF_LIST=$(TEMPDIR)/jre-elf-files.list -$(JRE_ELF_LIST): -ifneq ($(PLATFORM), windows) +# Get list of all binary (COFF or Elf) files in the jre +JRE_BIN_LIST=$(TEMPDIR)/jre-bin-files.list +$(JRE_BIN_LIST): $(RM) $@ +ifeq ($(PLATFORM), windows) + $(FIND) $(JRE_IMAGE_DIR)/bin -type f -name \*.exe \ + -o -name \*.dll | $(EGREP) -v -i "$(MSVCRNN_DLL)" > $@ +else $(FIND) $(JRE_IMAGE_DIR)/lib -type f -name \*.$(LIB_SUFFIX) >> $@ $(FILE) `$(FIND) $(JRE_IMAGE_DIR)/bin -type f -name \*$(EXE_SUFFIX)` \ | $(EGREP) 'ELF' | $(CUT) -d':' -f1 >> $@ @@ -848,9 +801,9 @@ endif # Post process the image (strips and mcs on Elf files we are shipping) # (Note the jdk WILL want the jre image before this processing) -process-image-jre:: $(JRE_ELF_LIST) +process-image-jre:: $(JRE_BIN_LIST) ifneq ($(POST_STRIP_PROCESS), ) - for f in `$(CAT) $(JRE_ELF_LIST)`; do \ + @for f in `$(CAT) $(JRE_BIN_LIST)`; do \ $(CHMOD) u+w $${f}; \ $(ECHO) $(POST_STRIP_PROCESS) $${f}; \ $(POST_STRIP_PROCESS) $${f}; \ @@ -858,14 +811,17 @@ ifneq ($(POST_STRIP_PROCESS), ) done endif ifneq ($(POST_MCS_PROCESS), ) - for f in `$(CAT) $(JRE_ELF_LIST)`; do \ + @for f in `$(CAT) $(JRE_BIN_LIST)`; do \ $(CHMOD) u+w $${f}; \ $(ECHO) $(POST_MCS_PROCESS) $${f}; \ $(POST_MCS_PROCESS) $${f}; \ $(CHMOD) go-w $${f}; \ done endif - $(RM) $(JRE_ELF_LIST) + @for f in `$(CAT) $(JRE_BIN_LIST)`; do \ + $(call binary_file_verification,$${f}); \ + done + $(RM) $(JRE_BIN_LIST) ###################################################### # JDK Image @@ -905,8 +861,7 @@ initial-image-jdk64-bindemos: # Solaris 64 bit image is special initial-image-jdk-sol64:: initial-image-jdk-setup \ - initial-image-jdk64-bindemos \ - $(JDK_LICENSES) $(JDK64_LICENSES) + initial-image-jdk64-bindemos # DB files to add ifdef OPENJDK @@ -930,7 +885,7 @@ endif # Standard jdk image initial-image-jdk:: initial-image-jdk-setup \ initial-image-jdk-db \ - $(JDK_LICENSES) $(JDK_DOCFILES) + $(JDK_DOCFILES) $(MKDIR) $(JDK_IMAGE_DIR)/lib @# @# Copy in the jars in lib that only belong in the JDK @@ -1089,14 +1044,18 @@ endif # !windows trim-image-jdk:: @# Remove tools that should not be part of SDK. for t in $(NOTJDKTOOLS); do \ - $(RM) $(JDK_IMAGE_DIR)/bin/$${t}$(EXE_SUFFIX) \ - $(JDK_IMAGE_DIR)/bin/*/native_threads/$${t}$(EXE_SUFFIX); \ + $(RM) $(JDK_IMAGE_DIR)/bin/$${t}$(EXE_SUFFIX); \ done -# Get list of Elf files in the jdk -JDK_ELF_LIST=$(TEMPDIR)/jdk-elf-files.list -$(JDK_ELF_LIST): -ifneq ($(PLATFORM), windows) +# Get list of binary (COFF or Elf) files in the jdk +JDK_BIN_LIST=$(TEMPDIR)/jdk-bin-files.list +$(JDK_BIN_LIST): +ifeq ($(PLATFORM), windows) + $(FIND) $(JDK_IMAGE_DIR)/jre/bin -type f -name \*.exe \ + -o -name \*.dll | $(EGREP) -v -i "$(MSVCRNN_DLL)" > $@ + $(FIND) $(JDK_IMAGE_DIR)/bin -type f -name \*.exe \ + -o -name \*.dll | $(EGREP) -v -i "$(MSVCRNN_DLL)" >> $@ +else $(RM) $@ $(FIND) $(JDK_IMAGE_DIR)/jre/lib -type f -name \*.$(LIB_SUFFIX) >> $@ $(FILE) `$(FIND) $(JDK_IMAGE_DIR)/jre/bin -type f -name \*$(EXE_SUFFIX)` \ @@ -1106,9 +1065,9 @@ ifneq ($(PLATFORM), windows) endif # Post process the image (strips and mcs on files we are shipping) -process-image-jdk:: $(JDK_ELF_LIST) +process-image-jdk:: $(JDK_BIN_LIST) ifneq ($(POST_STRIP_PROCESS), ) - for f in `$(CAT) $(JDK_ELF_LIST)`; do \ + @for f in `$(CAT) $(JDK_BIN_LIST)`; do \ $(CHMOD) u+w $${f}; \ $(ECHO) $(POST_STRIP_PROCESS) $${f}; \ $(POST_STRIP_PROCESS) $${f}; \ @@ -1116,14 +1075,56 @@ ifneq ($(POST_STRIP_PROCESS), ) done endif ifneq ($(POST_MCS_PROCESS), ) - for f in `$(CAT) $(JDK_ELF_LIST)`; do \ + @for f in `$(CAT) $(JDK_BIN_LIST)`; do \ $(CHMOD) u+w $${f}; \ $(ECHO) $(POST_MCS_PROCESS) $${f}; \ $(POST_MCS_PROCESS) $${f}; \ $(CHMOD) go-w $${f}; \ done endif - $(RM) $(JDK_ELF_LIST) + @for f in `$(CAT) $(JDK_BIN_LIST)`; do \ + $(call binary_file_verification,$${f}); \ + done + $(RM) $(JDK_BIN_LIST) + +################################################################### +# What did we build +################################################################### + +# The jdk text info file that lives at the root of the install image. + +JDK_INFO_FILE = $(JDK_IMAGE_DIR)/release +JRE_INFO_FILE = $(JRE_IMAGE_DIR)/release + +# Common way to emit a line into the release or info file +define info-file-item # name value +$(PRINTF) "%s=\"%s\"\n" $1 $2 >> $@ +endef + +# Values to emit +MINIMUM_OS_NAME := $(REQUIRED_OS_NAME) +MINIMUM_OS_VERSION := $(REQUIRED_OS_VERSION) +MINIMUM_OS_ARCH := $(ARCH) + +$(JDK_INFO_FILE): FRC + $(prep-target) + $(call info-file-item, "JAVA_VERSION", "$(THIS_JDK_VERSION)") + $(call info-file-item, "OS_NAME", "$(MINIMUM_OS_NAME)") + $(call info-file-item, "OS_VERSION", "$(MINIMUM_OS_VERSION)") + $(call info-file-item, "OS_ARCH", "$(MINIMUM_OS_ARCH)") + +# Create release file to identify this image +identify-image-jdk:: $(JDK_INFO_FILE) + +$(JRE_INFO_FILE): FRC + $(prep-target) + $(call info-file-item, "JAVA_VERSION", "$(THIS_JDK_VERSION)") + $(call info-file-item, "OS_NAME", "$(MINIMUM_OS_NAME)") + $(call info-file-item, "OS_VERSION", "$(MINIMUM_OS_VERSION)") + $(call info-file-item, "OS_ARCH", "$(MINIMUM_OS_ARCH)") + +# Create release file to identify this image +identify-image-jre:: $(JRE_INFO_FILE) ################################################################### # What do we compare against @@ -1278,6 +1279,7 @@ images images-clobber:: initial-image-jre-setup \ trim-image-jre trim-image-jdk \ process-image-jre process-image-jdk \ + identify-image-jre identify-image-jdk \ install-previous-jre install-previous-jdk \ compare-image-jre compare-image-jdk \ compare-image compare-image-clobber \ diff --git a/make/common/shared/Compiler-msvc.gmk b/make/common/shared/Compiler-msvc.gmk index 49a0d5fe63cace132cf940d23b8edf9fe01aa101..1b6d38d5f7f2a88c5324e8af57ac6a42b9f99f6b 100644 --- a/make/common/shared/Compiler-msvc.gmk +++ b/make/common/shared/Compiler-msvc.gmk @@ -35,6 +35,7 @@ ifeq ($(PLATFORM), windows) LIBEXE = $(COMPILER_PATH)lib LINK = $(COMPILER_PATH)link LINK32 = $(LINK) + DUMPBIN = $(COMPILER_PATH)dumpbin.exe # Fill in unknown values COMPILER_NAME=Unknown MSVC Compiler @@ -139,8 +140,8 @@ ifeq ($(PLATFORM), windows) _OTHER_TOOLS_BIN = $(WINDOWSSDKDIR)/Bin/x64 endif endif - RC = $(_OTHER_TOOLS_BIN)/rc.exe - REBASE = $(_OTHER_TOOLS_BIN)/rebase.exe + RC = $(_OTHER_TOOLS_BIN)/RC.Exe + REBASE = $(_OTHER_TOOLS_BIN)/ReBase.Exe MT = $(_OTHER_TOOLS_BIN)/mt.exe MTL = $(_OTHER_TOOLS_BIN)/midl.exe endif diff --git a/make/common/shared/Defs-control.gmk b/make/common/shared/Defs-control.gmk index 13eb20b1da474fc2fed2588de8d0302c8270c39d..288eb83e01c4e84fa91ea6999c1757b0f3338030 100644 --- a/make/common/shared/Defs-control.gmk +++ b/make/common/shared/Defs-control.gmk @@ -76,12 +76,9 @@ SRC_BUNDLEDIR = $(OUTPUTDIR)/source-bundles ABS_SRC_BUNDLEDIR = $(ABS_OUTPUTDIR)/source-bundles BIN_BUNDLEDIR = $(OUTPUTDIR)/bundles ABS_BIN_BUNDLEDIR = $(ABS_OUTPUTDIR)/bundles -JRL_BUNDLEDIR = $(OUTPUTDIR)/java.net -ABS_JRL_BUNDLEDIR = $(ABS_OUTPUTDIR)/java.net dummy := $(shell $(MKDIR) -p $(BIN_BUNDLEDIR)) dummy := $(shell $(MKDIR) -p $(SRC_BUNDLEDIR) ) -dummy := $(shell $(MKDIR) -p $(JRL_BUNDLEDIR) ) TEMP_DIR = $(OUTPUTDIR)/tmp ABS_TEMP_DIR = $(ABS_OUTPUTDIR)/tmp diff --git a/make/common/shared/Defs-linux.gmk b/make/common/shared/Defs-linux.gmk index a6be5365021f5ea89f3e4feb9bb82ff542e6f5e8..db1307056d18fc378543e43dcd68f38f095aa317 100644 --- a/make/common/shared/Defs-linux.gmk +++ b/make/common/shared/Defs-linux.gmk @@ -177,3 +177,20 @@ else endif HOTSPOT_SERVER_PATH:=$(call AltCheckValue,HOTSPOT_SERVER_PATH) +# Special define for checking the binaries + +# Macro to check it's input file for banned dependencies and verify the +# binary built properly. Relies on process exit code. +define binary_file_verification # binary_file +( \ + $(ECHO) "Checking for mapfile use in: $1" && \ + if [ "`$(NM) -D -g --defined-only $1 | $(EGREP) 'SUNWprivate'`" = "" ] ; then \ + $(ECHO) "WARNING: File was not built with a mapfile: $1"; \ + fi && \ + $(ECHO) "Library loads for: $1" && \ + $(LDD) $1 && \ + $(ECHO) "RUNPATH for: $1" && \ + ( $(READELF) -d $1 | $(EGREP) 'NEEDED|RUNPATH|RPATH' ) \ +) +endef + diff --git a/make/common/shared/Defs-solaris.gmk b/make/common/shared/Defs-solaris.gmk index 98b054ef3d48f1b163dadbfc05ff4b92a49f9179..177af974855e6c94b477fefa7b528dc851cee600 100644 --- a/make/common/shared/Defs-solaris.gmk +++ b/make/common/shared/Defs-solaris.gmk @@ -186,3 +186,20 @@ else endif HOTSPOT_SERVER_PATH:=$(call AltCheckValue,HOTSPOT_SERVER_PATH) +# Special define for checking the binaries + +# Macro to check it's input file for banned dependencies and verify the +# binary built properly. Relies on process exit code. +define binary_file_verification # binary_file +( \ + $(ECHO) "Checking for mapfile use in: $1" && \ + if [ "`$(NM) -g -D $1 | $(EGREP) -v 'UNDEF' | $(EGREP) 'SUNWprivate'`" = "" ] ; then \ + $(ECHO) "WARNING: File was not built with a mapfile: $1"; \ + fi && \ + $(ECHO) "Library loads for: $1" && \ + $(LDD) $1 && \ + $(ECHO) "RUNPATH for: $1" && \ + ( $(DUMP) -L -v $1 | $(EGREP) 'NEEDED|RUNPATH|RPATH' ) \ +) +endef + diff --git a/make/common/shared/Defs-utils.gmk b/make/common/shared/Defs-utils.gmk index 01bb982466f0604a6c849dadebeb74836a1c0cd2..bb6aa493cf5b4de957f890b1f89c0dd9f51ea1a7 100644 --- a/make/common/shared/Defs-utils.gmk +++ b/make/common/shared/Defs-utils.gmk @@ -85,6 +85,7 @@ DATE = $(UTILS_COMMAND_PATH)date DF = $(UTILS_COMMAND_PATH)df DIFF = $(UTILS_USR_BIN_PATH)diff DIRNAME = $(UTILS_USR_BIN_PATH)dirname +DUMP = $(UTILS_CCS_BIN_PATH)dump ECHO = $(UTILS_COMMAND_PATH)echo EGREP = $(UTILS_COMMAND_PATH)egrep EXPR = $(UTILS_USR_BIN_PATH)expr @@ -99,6 +100,7 @@ ID = $(UTILS_COMMAND_PATH)id ISAINFO = $(UTILS_COMMAND_PATH)isainfo KSH = $(UTILS_COMMAND_PATH)ksh LD = $(UTILS_CCS_BIN_PATH)ld +LDD = $(UTILS_USR_BIN_PATH)ldd LEX = $(UTILS_CCS_BIN_PATH)lex LN = $(UTILS_COMMAND_PATH)ln LS = $(UTILS_COMMAND_PATH)ls @@ -114,6 +116,7 @@ PKGMK = $(UTILS_COMMAND_PATH)pkgmk PRINTF = $(UTILS_USR_BIN_PATH)printf PWD = $(UTILS_COMMAND_PATH)pwd RC = $(UTILS_COMMAND_PATH)rc +READELF = $(UTILS_USR_BIN_PATH)readelf RMDIR = $(UTILS_COMMAND_PATH)rmdir RPM = $(UTILS_COMMAND_PATH)rpm RPMBUILD = $(UTILS_COMMAND_PATH)rpmbuild diff --git a/make/common/shared/Defs-versions.gmk b/make/common/shared/Defs-versions.gmk index 6784be6f04ac4d1da8424bc03ce7747c8026b961..a51cb2b75d578cc6826bb2529d828df497494294 100644 --- a/make/common/shared/Defs-versions.gmk +++ b/make/common/shared/Defs-versions.gmk @@ -127,6 +127,7 @@ endif # Solaris specific ifeq ($(PLATFORM), solaris) + REQUIRED_OS_NAME = SunOS REQUIRED_OS_VERSION = 5.10 REQUIRED_OS_VARIANT_NAME = Solaris REQUIRED_OS_VARIANT_VERSION = $(REQUIRED_OS_VERSION) @@ -148,6 +149,7 @@ endif # Linux specific ifeq ($(PLATFORM), linux) + REQUIRED_OS_NAME = Linux REQUIRED_OS_VERSION = 2.6 REQUIRED_OS_VARIANT_NAME = Fedora REQUIRED_OS_VARIANT_VERSION = 9 @@ -166,6 +168,7 @@ endif # Windows specific ifeq ($(PLATFORM), windows) + REQUIRED_OS_NAME = Windows ifeq ($(ARCH_DATA_MODEL),64) REQUIRED_OS_VERSION = 5.2 REQUIRED_OS_VARIANT_NAME = Windows2003 diff --git a/make/common/shared/Defs-windows.gmk b/make/common/shared/Defs-windows.gmk index 6a6fbffd39ac7d04eed202523fda7cb3a4bb428a..e1af407680d961b566f5f952505ee12b9a4f4074 100644 --- a/make/common/shared/Defs-windows.gmk +++ b/make/common/shared/Defs-windows.gmk @@ -288,8 +288,8 @@ ifndef VS2010_EXISTS xVS100COMNTOOLS :="$(_program_files32)/Microsoft Visual Studio 10.0/Common7/Tools/" fVS100COMNTOOLS :=$(call FullPath,$(xVS100COMNTOOLS)) else + xVS100COMNTOOLS :="$(subst \,/,$(VS100COMNTOOLS))" ifneq ($(word 2,$(VS100COMNTOOLS)),) - xVS100COMNTOOLS :="$(subst \,/,$(VS100COMNTOOLS))" fVS100COMNTOOLS :=$(call FullPath,$(xVS100COMNTOOLS)) else fVS100COMNTOOLS :=$(xVS100COMNTOOLS) @@ -551,18 +551,6 @@ ifndef ALT_BOOTDIR _BOOTDIR3 =$(SLASH_JAVA)/re/jdk/$(PREVIOUS_JDK_VERSION)/archive/fcs/binaries/$(PLATFORM)-$(ARCH) endif -# 32 bit always needs 2 runtimes, 64 bit usually does too - -# MSVCRT_DLL_PATH: location of msvcrt.dll that will be re-distributed -ifdef ALT_MSVCRT_DLL_PATH - xALT_MSVCRT_DLL_PATH :="$(subst \,/,$(ALT_MSVCRT_DLL_PATH))" - MSVCRT_DLL_PATH :=$(call FullPath,$(xALT_MSVCRT_DLL_PATH)) -else - MSVCRT_DLL_PATH :=$(call FullPath,$(_system_root)/system32/) -endif -MSVCRT_DLL_PATH:=$(call AltCheckSpaces,MSVCRT_DLL_PATH) -MSVCRT_DLL_PATH:=$(call AltCheckValue,MSVCRT_DLL_PATH) - # 32bit always needs the MSVCRNN runtime, 64bit does when using VS2008 ifeq ($(ARCH_DATA_MODEL), 32) _NEEDS_MSVCRNN = true @@ -641,15 +629,6 @@ else endif INSTALL_MSSDK:=$(call AltCheckSpaces,INSTALL_MSSDK) -# INSTALL_MSIVAL2: Installation of MsiVal2 for this platform (for install) -ifdef ALT_INSTALL_MSIVAL2 - xALT_INSTALL_MSIVAL2 :="$(subst \,/,$(ALT_INSTALL_MSIVAL2))" - INSTALL_MSIVAL2 :=$(call FullPath,$(xALT_INSTALL_MSIVAL2)) -else - INSTALL_MSIVAL2 :=$(_program_files32)/MsiVal2 -endif -INSTALL_MSIVAL2:=$(call AltCheckSpaces,INSTALL_MSIVAL2) - # WSCRIPT: path to wscript.exe (used in creating install bundles) ifdef ALT_WSCRIPT xALT_WSCRIPT :="$(subst \,/,$(ALT_WSCRIPT))" @@ -685,43 +664,6 @@ else endif CABARC:=$(call AltCheckSpaces,CABARC) -# MSIVAL2: path to msival2.exe (used in validating install msi files) -ifdef ALT_MSIVAL2 - xALT_MSIVAL2 :="$(subst \,/,$(ALT_MSIVAL2))" - MSIVAL2 =$(xALT_MSIVAL2) -else - _MSIVAL2_1 :=$(INSTALL_MSIVAL2)/msival2.exe - _MSIVAL2_2 :=$(DEVTOOLS_PATH)msival2.exe - MSIVAL2 :=$(call FileExists,$(_MSIVAL2_1),$(_MSIVAL2_2)) -endif -MSIVAL2:=$(call AltCheckSpaces,MSIVAL2) -# suppress msival2 checks, as it hangs jprt builds -ifdef SKIP_MSIVAL2 - MSIVAL2 := $(ECHO) -endif - -# LOGOCUB: path to cub file for (used in validating install msi files) -ifdef ALT_LOGOCUB - xALT_LOGOCUB :="$(subst \,/,$(ALT_LOGOCUB))" - LOGOCUB =$(xALT_LOGOCUB) -else - _LOGOCUB1 :=$(INSTALL_MSIVAL2)/logo.cub - _LOGOCUB2 :=$(DEVTOOLS_PATH)logo.cub - LOGOCUB :=$(call FileExists,$(_LOGOCUB1),$(_LOGOCUB2)) -endif -LOGOCUB:=$(call AltCheckSpaces,LOGOCUB) - -# MSITRAN: path to msitran.exe (used in creating install bundles and sponsors) -ifdef ALT_MSITRAN - xALT_MSITRAN :="$(subst \,/,$(ALT_MSITRAN))" - MSITRAN =$(xALT_MSITRAN) -else - _MSITRAN1 :=$(INSTALL_MSSDK)/Bin/msitran.exe - _MSITRAN2 :=$(DEVTOOLS_PATH)msitran.exe - MSITRAN :=$(call FileExists,$(_MSITRAN1),$(_MSITRAN2)) -endif -MSITRAN:=$(call AltCheckSpaces,MSITRAN) - # MSICERT: path to msicert.exe (used in creating install bundles) ifdef ALT_MSICERT xALT_MSICERT :="$(subst \,/,$(ALT_MSICERT))" @@ -798,3 +740,50 @@ else endif HOTSPOT_LIB_PATH:=$(call AltCheckSpaces,HOTSPOT_LIB_PATH) HOTSPOT_LIB_PATH:=$(call AltCheckValue,HOTSPOT_LIB_PATH) + +# Special define for checking the binaries + +ifeq ($(VS2010_EXISTS),true) + +# All windows dll and exe files should have been built with /NXCOMPAT +# and be setup for dynamic base addresses. +# In addition, we should not be dependent on certain dll files that +# we do not or cannot redistribute. + +# List of filenames we should NOT be dependent on +BANNED_DLLS=msvcp100[.]dll|msvcr100d[.]dll|msvcrtd[.]dll + +# Macro to check it's input file for banned dependencies and verify the +# binary was built properly. Relies on process exit code. +define binary_file_verification # binary_file +( \ + $(ECHO) "Checking for /NXCOMPAT usage in: $1" && \ + if [ "`$(DUMPBIN) /headers $1 | $(EGREP) -i 'NX compatible'`" = "" ] ; then \ + $(ECHO) "ERROR: Did not find 'NX compatible' in headers: $1" ; \ + $(DUMPBIN) /headers $1 ; \ + exit 7 ; \ + fi ; \ + $(ECHO) "Checking for /DYNAMICBASE usage in: $1" && \ + if [ "`$(DUMPBIN) /headers $1 | $(EGREP) -i 'Dynamic base'`" = "" ] ; then \ + $(ECHO) "ERROR: Did not find 'Dynamic base' in headers: $1" ; \ + $(DUMPBIN) /headers $1 ; \ + exit 8 ; \ + fi ; \ + $(ECHO) "Checking for banned dependencies in: $1" && \ + if [ "`$(DUMPBIN) /dependents $1 | $(EGREP) -i '$(BANNED_DLLS)'`" != "" ] ; then \ + $(ECHO) "ERROR: Found us of $(BANNED_DLLS)"; \ + $(DUMPBIN) /dependents $1 ; \ + exit 9 ; \ + fi ; \ +) +endef + +else + +# Macro to check it's input file for banned dependencies and verify the +# binary was built properly. Relies on process exit code. +define binary_file_verification # binary_file +endef + +endif + diff --git a/make/common/shared/Sanity-Settings.gmk b/make/common/shared/Sanity-Settings.gmk index 7e77e11aeb05fba41a6a511caeed3263f6c66254..ce89bd960921c032c84beb96cfe7fd47a3ce22c8 100644 --- a/make/common/shared/Sanity-Settings.gmk +++ b/make/common/shared/Sanity-Settings.gmk @@ -96,7 +96,6 @@ ifeq ($(PLATFORM),solaris) endif endif ifeq ($(PLATFORM),windows) - ALL_SETTINGS+=$(call addAltSetting,MSVCRT_DLL_PATH) ifneq ($(MSVCRNN_DLL),) ALL_SETTINGS+=$(call addAltSetting,MSVCRNN_DLL_PATH) endif @@ -117,6 +116,9 @@ ALL_SETTINGS+=$(call addRequiredVersionSetting,ZIP_VER) ALL_SETTINGS+=$(call addRequiredVersionSetting,UNZIP_VER) ifeq ($(PLATFORM),windows) ALL_SETTINGS+=$(call addRequiredVersionSetting,LINK_VER) + ALL_SETTINGS+=$(call addRequiredSetting,CC) + ALL_SETTINGS+=$(call addRequiredSetting,LINK) + ALL_SETTINGS+=$(call addRequiredSetting,DUMPBIN) endif ALL_SETTINGS+=$(call addRequiredVersionSetting,ANT_VER) ALL_SETTINGS+=$(call addRequiredSetting,TEMPDIR) @@ -226,13 +228,13 @@ ifeq ($(PLATFORM),windows) ALL_SETTINGS+=$(call addAltSetting,DXSDK_INCLUDE_PATH) ALL_SETTINGS+=$(call addAltSetting,DXSDK_LIB_PATH) ALL_SETTINGS+=$(call addAltSetting,WINDOWSSDKDIR) + ALL_SETTINGS+=$(call addRequiredSetting,RC) + ALL_SETTINGS+=$(call addRequiredSetting,REBASE) ifndef OPENJDK ALL_SETTINGS+=$(call addAltSetting,DEPLOY_MSSDK) ALL_SETTINGS+=$(call addAltSetting,INSTALL_MSSDK) ALL_SETTINGS+=$(call addAltSetting,WSCRIPT) ALL_SETTINGS+=$(call addAltSetting,MSICERT) - ALL_SETTINGS+=$(call addAltSetting,MSITRAN) - ALL_SETTINGS+=$(call addAltSetting,MSIVAL2) endif endif ALL_SETTINGS+=$(call addAltSetting,CACERTS_FILE) diff --git a/make/common/shared/Sanity.gmk b/make/common/shared/Sanity.gmk index b17690ca4c237e75c396008f05ac22cfb9f3e8cc..0cf3433f9dcfba22c80073b6df276068c86f3caf 100644 --- a/make/common/shared/Sanity.gmk +++ b/make/common/shared/Sanity.gmk @@ -879,13 +879,6 @@ sane-devtools_path: ###################################################### sane-msvcrt_path: ifeq ($(PLATFORM), windows) - @if [ ! -r "$(MSVCRT_DLL_PATH)/msvcrt.dll" ]; then \ - $(ECHO) "ERROR: You do not have access to msvcrt.dll. \n" \ - " Please check your access to \n" \ - " $(MSVCRT_DLL_PATH) \n" \ - " and/or check your value of ALT_MSVCRT_DLL_PATH. \n" \ - "" >> $(ERROR_FILE) ; \ - fi ifneq ($(MSVCRNN_DLL),) @if [ ! -r "$(MSVCRNN_DLL_PATH)/$(MSVCRNN_DLL)" ]; then \ $(ECHO) "ERROR: You do not have access to $(MSVCRNN_DLL). \n" \ @@ -1018,6 +1011,22 @@ ifeq ($(PLATFORM), windows) " and/or check your value of ALT_MSDEVTOOLS_PATH. \n" \ "" >> $(ERROR_FILE) ; \ fi + else + ifeq ($(wildcard $(REBASE)),) + @$(ECHO) "ERROR: Cannot find the REBASE utility from path: $(REBASE)\n" \ + " This is normally obtained from the WINDOWSSDKDIR." \ + "" >> $(ERROR_FILE) + endif + ifeq ($(wildcard $(RC)),) + @$(ECHO) "ERROR: Cannot find the RC utility from path: $(RC)\n" \ + " This is normally obtained from the WINDOWSSDKDIR." \ + "" >> $(ERROR_FILE) + endif + ifeq ($(wildcard $(DUMPBIN)),) + @$(ECHO) "ERROR: Cannot find the DUMPBIN utility from path: $(DUMPBIN)\n" \ + " This is normally obtained from the WINDOWSSDKDIR." \ + "" >> $(ERROR_FILE) + endif endif endif @@ -1459,25 +1468,6 @@ ifeq ($(PLATFORM), windows) fi endif -###################################################### -# Check for existence of INSTALL_MSIVAL2 on windows -###################################################### -sane-install-msival2_path: -ifeq ($(PLATFORM), windows) - @if [ -z "$(INSTALL_MSIVAL2)" ]; then \ - $(ECHO) "WARNING: Your INSTALL_MSIVAL2 setting is empty.\n" \ - " It is recommended to set ALT_INSTALL_MSIVAL2.\n" \ - "" >> $(WARNING_FILE) ; \ - fi - @if [ ! -r "$(INSTALL_MSIVAL2)" ]; then \ - $(ECHO) "ERROR: You do not have a valid INSTALL_MSIVAL2 setting. \n" \ - " Please check your access to \n" \ - " $(INSTALL_MSIVAL2) \n" \ - " and/or check your value of ALT_INSTALL_MSIVAL2. \n" \ - "" >> $(ERROR_FILE) ; \ - fi -endif - ###################################################### # Check the GNU C++ compiler for OJI plugin ###################################################### diff --git a/make/java/Makefile b/make/java/Makefile index 3a697d2ff862e1164b9ceeecdf03658dbf3d8f42..f988fe95d07c6ce9d08bbbc92527e554701f37b9 100644 --- a/make/java/Makefile +++ b/make/java/Makefile @@ -34,7 +34,7 @@ include $(BUILDDIR)/common/Defs.gmk # # The order of subdirs here is important # -SUBDIRS += hpi version jvm redist verify fdlibm java sun_nio jli main zip +SUBDIRS += version jvm redist verify fdlibm java sun_nio jli main zip # Others # Note: java_crw_demo java_hprof_demo are demos but must be delivered built in sdk diff --git a/make/java/fdlibm/Makefile b/make/java/fdlibm/Makefile index 584f67e2dc92ac9d284da20ce6d0364da8d23d54..c4778af3e93e4da70bb8470f54880383b6406f87 100644 --- a/make/java/fdlibm/Makefile +++ b/make/java/fdlibm/Makefile @@ -24,7 +24,7 @@ # # -# Makefile for native threads HPI. +# Makefile for fdlibm # # Note: # The fdlibm libraries are built using special rules in Library.gmk. diff --git a/make/java/hpi/hpi_common.gmk b/make/java/hpi/hpi_common.gmk deleted file mode 100644 index df5796f10e2802cdba27b75bc38d4223ac6209ed..0000000000000000000000000000000000000000 --- a/make/java/hpi/hpi_common.gmk +++ /dev/null @@ -1,90 +0,0 @@ -# -# Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -# -# Shared files between the different threads types on Solaris. Be -# careful when including this, you must get your variables right. -# - -# -# Common files on Solaris. -# -ifneq ($(PLATFORM), windows) -FILES_c += \ - interrupt.c \ - linker_md.c \ - memory_md.c \ - system_md.c \ - hpi.c -endif - -# -# Include paths can also be shared. -# -ifneq ($(PLATFORM), windows) -OTHER_INCLUDES += \ - -I$(PLATFORM_SRC)/hpi/$(THREADDIR)/include \ - -I$(PLATFORM_SRC)/hpi/include \ - -I$(PLATFORM_SRC)/hpi/export \ - -I$(SHARE_SRC)/hpi/include \ - -I$(SHARE_SRC)/hpi/export -else -OTHER_INCLUDES += \ - -I$(PLATFORM_SRC)/hpi/include \ - -I$(PLATFORM_SRC)/hpi/export \ - -I$(SHARE_SRC)/hpi/include \ - -I$(SHARE_SRC)/hpi/export -endif - -# -# Add to the default C and assembly file search paths. Clear any initial -# vpath settings to ensure that we don't look in unexpected places for HPI -# files. -# -vpath %.c -vpath %.c $(PLATFORM_SRC)/hpi/$(THREADDIR)/src -vpath %.c $(PLATFORM_SRC)/hpi/src -vpath %.c $(SHARE_SRC)/hpi/src - -vpath %.s -vpath %.s $(PLATFORM_SRC)/hpi/$(THREADDIR)/src -vpath %.s $(PLATFORM_SRC)/hpi/src - -# -# By default leave out locking statistics -# -ifneq ($(PLATFORM), windows) -LOCKSTATS = false -ifeq ($(LOCKSTATS), true) - CFLAGS_COMMON += -DLOCKSTATS -endif -endif - -# -# Things that must be linked in. -# -ifneq ($(PLATFORM), windows) -OTHER_LDLIBS += $(LIBSOCKET) $(LIBNSL) $(LIBM) -ldl -endif diff --git a/make/java/hpi/native/Makefile b/make/java/hpi/native/Makefile deleted file mode 100644 index 2655e8248f843c98a5af69ad169d3a70e9ea2a6e..0000000000000000000000000000000000000000 --- a/make/java/hpi/native/Makefile +++ /dev/null @@ -1,93 +0,0 @@ -# -# Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -# -# Makefile for native threads HPI. -# - -BUILDDIR = ../../.. -MODULE = base -LIBRARY = hpi -PRODUCT = java -THREADDIR = native_threads -LIB_LOCATION = $(LIBDIR)/$(LIBARCH)/$(THREADDIR) -include $(BUILDDIR)/common/Defs.gmk - -# -# Native threads specific C and .s files. -# -FILES_c = \ - monitor_md.c \ - threads_md.c \ - condvar_md.c \ - interrupt_md.c \ - mutex_md.c \ - sys_api_td.c \ - threads_$(PLATFORM).c - -# -# Other files/flags shared between the HPIs. -# -include $(BUILDDIR)/java/hpi/hpi_common.gmk - -# -# Rules for the .so file. -# -ifeq ($(PLATFORM), solaris) - ifneq ($(ARCH), amd64) - FILES_reorder += reorder-$(ARCH) - endif -endif -include $(BUILDDIR)/common/Mapfile-vers.gmk -include $(BUILDDIR)/common/Library.gmk - -# -# HPI flags for native threads. -# -OTHER_CPPFLAGS += -D_REENTRANT -DNATIVE - -ifeq ($(USE_PTHREADS),true) -OTHER_CPPFLAGS += -DUSE_PTHREADS -ifeq ($(MOOT_PRIORITIES),true) -OTHER_CPPFLAGS += -DMOOT_PRIORITIES -endif -LIBPOSIX4 = -lposix4 -OTHER_LDLIBS += -lpthread $(LIBPOSIX4) -endif - -HAVE_GETHRVTIME=true -ifeq ($(HAVE_GETHRVTIME),true) -OTHER_CPPFLAGS += -DHAVE_GETHRVTIME -endif - -HAVE_FILIOH=true -ifeq ($(HAVE_FILIOH),true) -OTHER_CPPFLAGS += -DHAVE_FILIOH -endif - -ifeq ($(NO_INTERRUPTIBLE_IO),true) -OTHER_CPPFLAGS += -DNO_INTERRUPTIBLE_IO -endif - diff --git a/make/java/hpi/native/reorder-i586 b/make/java/hpi/native/reorder-i586 deleted file mode 100644 index 69c4ced4a6c1d9e743b30e0e946b7f99c766b09b..0000000000000000000000000000000000000000 --- a/make/java/hpi/native/reorder-i586 +++ /dev/null @@ -1,27 +0,0 @@ -data = R0x2000; -text = LOAD ?RXO; -# Test Null -text: .text%_init; -text: .text%checkForCorrectLibthread: OUTPUTDIR/tmp/java/hpi/native_threads/obj/threads_solaris.o; -text: .text%init64IO: OUTPUTDIR/tmp/java/hpi/native_threads/obj/system_md.o; -text: .text%DLL_Initialize; -text: .text%GetInterface: OUTPUTDIR/tmp/java/hpi/native_threads/obj/hpi.o; -text: .text%sysBuildLibName; -text: .text%sysLoadLibrary; -text: .text%sysFindLibraryEntry; -text: .text%sysNativePath; -text: .text%sysOpen; -text: .text%sysSeek; -text: .text%lseek64_w; -# Test Exit -# Test Hello -# Test Sleep -# Test IntToString -# Test LoadToolkit -text: .text%sysAvailable; -text: .text%sysFfileMode; -text: .text%sysGetLastErrorString; -# Test LoadFrame -# Test LoadJFrame -# Test JHello -# SwingSet diff --git a/make/java/hpi/native/reorder-sparc b/make/java/hpi/native/reorder-sparc deleted file mode 100644 index 4a180d9cbfe2fea14b2d6dca35ceaea56df779ba..0000000000000000000000000000000000000000 --- a/make/java/hpi/native/reorder-sparc +++ /dev/null @@ -1,26 +0,0 @@ -data = R0x2000; -text = LOAD ?RXO; -# Test Null -text: .text%checkForCorrectLibthread: OUTPUTDIR/tmp/java/hpi/native_threads/obj/threads_solaris.o; -text: .text%init64IO: OUTPUTDIR/tmp/java/hpi/native_threads/obj/system_md.o; -text: .text%DLL_Initialize; -text: .text%GetInterface: OUTPUTDIR/tmp/java/hpi/native_threads/obj/hpi.o; -text: .text%sysBuildLibName; -text: .text%sysLoadLibrary; -text: .text%sysFindLibraryEntry; -text: .text%sysNativePath; -text: .text%sysOpen; -text: .text%sysFfileMode; -text: .text%sysSeek; -text: .text%lseek64_w; -text: .text%sysAvailable; -# Test Exit -# Test Hello -# Test Sleep -# Test IntToString -# Test LoadToolkit -text: .text%sysGetLastErrorString; -# Test LoadFrame -# Test LoadJFrame -# Test JHello -# SwingSet diff --git a/make/java/hpi/native/reorder-sparcv9 b/make/java/hpi/native/reorder-sparcv9 deleted file mode 100644 index 6ac7b06a0bcc2dd262f684ce8a696f2a15774c8e..0000000000000000000000000000000000000000 --- a/make/java/hpi/native/reorder-sparcv9 +++ /dev/null @@ -1,26 +0,0 @@ -data = R0x2000; -text = LOAD ?RXO; -# Test Null -text: .text%checkForCorrectLibthread: OUTPUTDIR/tmp/java/hpi/native_threads/obj64/threads_solaris.o; -text: .text%init64IO: OUTPUTDIR/tmp/java/hpi/native_threads/obj64/system_md.o; -text: .text%DLL_Initialize; -text: .text%GetInterface: OUTPUTDIR/tmp/java/hpi/native_threads/obj64/hpi.o; -text: .text%sysBuildLibName; -text: .text%sysLoadLibrary; -text: .text%sysFindLibraryEntry; -text: .text%sysNativePath; -text: .text%sysOpen; -text: .text%sysFfileMode; -text: .text%sysSeek; -text: .text%lseek64_w; -text: .text%sysAvailable; -# Test Exit -# Test Hello -# Test Sleep -# Test IntToString -# Test LoadToolkit -text: .text%sysGetLastErrorString; -# Test LoadFrame -# Test LoadJFrame -# Test JHello -# SwingSet diff --git a/make/java/hpi/windows/Makefile b/make/java/hpi/windows/Makefile deleted file mode 100644 index bf6f818fdf421eb354a512ee9b18e2e94444aa84..0000000000000000000000000000000000000000 --- a/make/java/hpi/windows/Makefile +++ /dev/null @@ -1,69 +0,0 @@ -# -# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -# -# Makefile for Windows HPI DLL -# -BUILDDIR = ../../.. -MODULE = base -LIBRARY = hpi -PRODUCT = java -THREADDIR = windows_threads -LIB_LOCATION = $(BINDIR) - -include $(BUILDDIR)/common/Defs.gmk - -# windows compiler flags -ifeq ($(PLATFORM),windows) - CPPFLAGS_DBG += -DLOGGING -endif - -FILES_c = \ - linker_md.c \ - memory_md.c \ - monitor_md.c \ - path_md.c \ - socket_md.c \ - sys_api_md.c \ - system_md.c \ - threads_md.c \ - hpi.c # trailing blank required! - -JVMLIB = -JAVALIB = -OTHER_LCF = -export:DLL_Initialize -EXTRA_LIBS = - - -# -# Other files/flags shared between the HPIs. -# -include $(BUILDDIR)/java/hpi/hpi_common.gmk - -# -# Rules for the .so file. -# -include $(BUILDDIR)/common/Library.gmk - diff --git a/make/java/management/mapfile-vers b/make/java/management/mapfile-vers index a9d931d78bcf79e2c98dfa67783e3b1f146d1d2b..d84f061a1750b1c3f5b68590b4f2be23e7e9093d 100644 --- a/make/java/management/mapfile-vers +++ b/make/java/management/mapfile-vers @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -70,14 +70,18 @@ SUNWprivate_1.1 { Java_sun_management_ThreadImpl_dumpThreads0; Java_sun_management_ThreadImpl_findDeadlockedThreads0; Java_sun_management_ThreadImpl_findMonitorDeadlockedThreads0; - Java_sun_management_ThreadImpl_getThreadInfo0; + Java_sun_management_ThreadImpl_getThreadInfo1; Java_sun_management_ThreadImpl_getThreads; Java_sun_management_ThreadImpl_getThreadTotalCpuTime0; + Java_sun_management_ThreadImpl_getThreadTotalCpuTime1; Java_sun_management_ThreadImpl_getThreadUserCpuTime0; + Java_sun_management_ThreadImpl_getThreadUserCpuTime1; + Java_sun_management_ThreadImpl_getThreadAllocatedMemory1; Java_sun_management_ThreadImpl_resetContentionTimes0; Java_sun_management_ThreadImpl_resetPeakThreadCount0; Java_sun_management_ThreadImpl_setThreadContentionMonitoringEnabled0; Java_sun_management_ThreadImpl_setThreadCpuTimeEnabled0; + Java_sun_management_ThreadImpl_setThreadAllocatedMemoryEnabled0; Java_sun_management_VMManagementImpl_getAvailableProcessors; Java_sun_management_VMManagementImpl_getClassInitializationTime; Java_sun_management_VMManagementImpl_getClassLoadingTime; @@ -106,6 +110,7 @@ SUNWprivate_1.1 { Java_sun_management_VMManagementImpl_initOptionalSupportFields; Java_sun_management_VMManagementImpl_isThreadContentionMonitoringEnabled; Java_sun_management_VMManagementImpl_isThreadCpuTimeEnabled; + Java_sun_management_VMManagementImpl_isThreadAllocatedMemoryEnabled; JNI_OnLoad; local: *; diff --git a/make/java/nio/Makefile b/make/java/nio/Makefile index c0a03c23d421516a914c977f6869d3a2997fe1bc..af84a82b8ac72daf09ce39c02720dcbbdeb0d8a5 100644 --- a/make/java/nio/Makefile +++ b/make/java/nio/Makefile @@ -296,7 +296,7 @@ ifeq ($(PLATFORM), linux) OTHER_LDLIBS += -L$(LIBDIR)/$(LIBARCH) -ljava -lnet -lpthread -ldl endif ifeq ($(PLATFORM), solaris) -OTHER_LDLIBS += $(JVMLIB) $(LIBSOCKET) -lposix4 -ldl \ +OTHER_LDLIBS += $(JVMLIB) $(LIBSOCKET) -lposix4 -ldl -lsendfile \ -L$(LIBDIR)/$(LIBARCH) -ljava -lnet endif # PLATFORM diff --git a/make/java/redist/Makefile b/make/java/redist/Makefile index 9f4d420aa426d6773e8c4ce7a3f2ec62c2118f2f..ad37a7b3401b4aa3fce4692647ec54e9593714b1 100644 --- a/make/java/redist/Makefile +++ b/make/java/redist/Makefile @@ -93,10 +93,6 @@ ifeq ($(PLATFORM), windows) IMPORT_LIST += $(MS_RUNTIME_LIBRARIES:%=$(BINDIR)/%) -# NOTE: These might actually come from BUILDDIR, depends on the settings. -$(BINDIR)/msvcrt.dll: $(MSVCRT_DLL_PATH)/msvcrt.dll - $(install-import-file) - $(call chmod-file, a+x) $(BINDIR)/$(MSVCRNN_DLL): $(MSVCRNN_DLL_PATH)/$(MSVCRNN_DLL) $(install-import-file) $(call chmod-file, a+x) @@ -223,12 +219,15 @@ endif # PLATFORM $(LIB_LOCATION)/$(CLIENT_LOCATION)/$(JVM_NAME): $(HOTSPOT_CLIENT_PATH)/$(JVM_NAME) $(install-import-file) + @$(call binary_file_verification,$@) $(LIB_LOCATION)/$(KERNEL_LOCATION)/$(JVM_NAME): $(HOTSPOT_KERNEL_PATH)/$(JVM_NAME) $(install-file) + @$(call binary_file_verification,$@) $(LIB_LOCATION)/$(LIBJSIG_NAME): $(HOTSPOT_IMPORT_PATH)/$(ARCH_VM_SUBDIR)/$(LIBJSIG_NAME) $(install-import-file) + @$(call binary_file_verification,$@) $(LIB_LOCATION)/$(CLIENT_LOCATION)/$(LIBJSIG_NAME) \ $(LIB_LOCATION)/$(SERVER_LOCATION)/$(LIBJSIG_NAME): @@ -237,30 +236,39 @@ $(LIB_LOCATION)/$(SERVER_LOCATION)/$(LIBJSIG_NAME): $(LIB_LOCATION)/$(CLIENT_LOCATION)/$(JVMDB_NAME): $(HOTSPOT_CLIENT_PATH)/$(JVMDB_NAME) $(install-import-file) + @$(call binary_file_verification,$@) $(LIB_LOCATION)/$(CLIENT_LOCATION)/64/$(JVMDB_NAME): $(HOTSPOT_CLIENT_PATH)/64/$(JVMDB_NAME) $(install-import-file) + @$(call binary_file_verification,$@) $(LIB_LOCATION)/$(SERVER_LOCATION)/$(JVMDB_NAME): $(HOTSPOT_SERVER_PATH)/$(JVMDB_NAME) $(install-import-file) + @$(call binary_file_verification,$@) $(LIB_LOCATION)/$(SERVER_LOCATION)/64/$(JVMDB_NAME): $(HOTSPOT_SERVER_PATH)/64/$(JVMDB_NAME) $(install-import-file) + @$(call binary_file_verification,$@) $(LIB_LOCATION)/$(CLIENT_LOCATION)/$(JVMDTRACE_NAME): $(HOTSPOT_CLIENT_PATH)/$(JVMDTRACE_NAME) $(install-import-file) + @$(call binary_file_verification,$@) $(LIB_LOCATION)/$(CLIENT_LOCATION)/64/$(JVMDTRACE_NAME): $(HOTSPOT_CLIENT_PATH)/64/$(JVMDTRACE_NAME) $(install-import-file) + @$(call binary_file_verification,$@) $(LIB_LOCATION)/$(SERVER_LOCATION)/$(JVMDTRACE_NAME): $(HOTSPOT_SERVER_PATH)/$(JVMDTRACE_NAME) $(install-import-file) + @$(call binary_file_verification,$@) $(LIB_LOCATION)/$(SERVER_LOCATION)/64/$(JVMDTRACE_NAME): $(HOTSPOT_SERVER_PATH)/64/$(JVMDTRACE_NAME) $(install-import-file) + @$(call binary_file_verification,$@) $(LIB_LOCATION)/$(SERVER_LOCATION)/$(JVM_NAME): $(HOTSPOT_SERVER_PATH)/$(JVM_NAME) $(install-import-file) + @$(call binary_file_verification,$@) $(LIB_LOCATION)/$(SERVER_LOCATION)/Xusage.txt : $(HOTSPOT_SERVER_PATH)/Xusage.txt $(install-import-file) diff --git a/make/jdk_generic_profile.sh b/make/jdk_generic_profile.sh index a498c46680f7082d75121c40a10e6f310e5971b7..9d7ead8b8656e665cda339fbb16cc27dbee74a78 100644 --- a/make/jdk_generic_profile.sh +++ b/make/jdk_generic_profile.sh @@ -50,7 +50,7 @@ # # Assumes basic unix utilities are in the PATH already (uname, hostname, etc.). # -# On Windows, assumes PROCESSOR_IDENTIFIER, VS71COMNTOOLS, +# On Windows, assumes PROCESSOR_IDENTIFIER, VS100COMNTOOLS, # SYSTEMROOT (or SystemRoot), COMPUTERNAME (or hostname works), and # USERNAME is defined in the environment. # This profile does not rely on using vcvars32.bat and 64bit Setup.bat. @@ -81,8 +81,7 @@ # Windows Only: # ALT_UNIXCOMMAND_PATH # ALT_DXSDK_PATH -# ALT_MSVCRT_DLL_PATH -# ALT_MSVCR71_DLL_PATH +# ALT_MSVCRNN_DLL_PATH # ############################################################################# # @@ -213,78 +212,17 @@ else # Compiler setup (nasty part) # NOTE: You can use vcvars32.bat to set PATH, LIB, and INCLUDE. # NOTE: CYGWIN has a link.exe too, make sure the compilers are first - if [ "${windows_arch}" = i586 ] ; then - # 32bit Windows compiler settings - # VisualStudio .NET 2003 VC++ 7.1 (VS71COMNTOOLS should be defined) - vs_root=$(${cygpath} "${VS71COMNTOOLS}/../..") - # Fill in PATH, LIB, and INCLUDE (unset all others to make sure) - vc7_root="${vs_root}/Vc7" - compiler_path="${vc7_root}/bin" - platform_sdk="${vc7_root}/PlatformSDK" - - # LIB and INCLUDE must use ; as a separator - include4sdk="${vc7_root}/atlmfc/include" - include4sdk="${include4sdk};${vc7_root}/include" - include4sdk="${include4sdk};${platform_sdk}/include/prerelease" - include4sdk="${include4sdk};${platform_sdk}/include" - include4sdk="${include4sdk};${vs_root}/SDK/v1.1/include" - lib4sdk="${lib4sdk};${vc7_root}/lib" - lib4sdk="${lib4sdk};${platform_sdk}/lib/prerelease" - lib4sdk="${lib4sdk};${platform_sdk}/lib" - lib4sdk="${lib4sdk};${vs_root}/SDK/v1.1/lib" - # Search path and DLL locating path - # WARNING: CYGWIN has a link.exe too, make sure compilers are first - path4sdk="${vs_root}/Common7/Tools/bin;${path4sdk}" - path4sdk="${vs_root}/SDK/v1.1/bin;${path4sdk}" - path4sdk="${vs_root}/Common7/Tools;${path4sdk}" - path4sdk="${vs_root}/Common7/Tools/bin/prerelease;${path4sdk}" - path4sdk="${vs_root}/Common7/IDE;${path4sdk}" - path4sdk="${compiler_path};${path4sdk}" - elif [ "${windows_arch}" = amd64 ] ; then - # AMD64 64bit Windows compiler settings - if [ "${ALT_DEPLOY_MSSDK}" != "" ] ; then - platform_sdk=${ALT_DEPLOY_MSSDK} - else - platform_sdk=$(${cygpath} "C:/Program Files/Microsoft Platform SDK/") - fi - if [ "${ALT_COMPILER_PATH}" != "" ] ; then - compiler_path=${ALT_COMPILER_PATH} - if [ "${ALT_DEPLOY_MSSDK}" = "" ] ; then - platform_sdk=${ALT_COMPILER_PATH}/../../../.. - fi - else - compiler_path="${platform_sdk}/Bin/win64/x86/AMD64" - fi - # LIB and INCLUDE must use ; as a separator - include4sdk="${platform_sdk}/Include" - include4sdk="${include4sdk};${platform_sdk}/Include/crt/sys" - include4sdk="${include4sdk};${platform_sdk}/Include/mfc" - include4sdk="${include4sdk};${platform_sdk}/Include/atl" - include4sdk="${include4sdk};${platform_sdk}/Include/crt" - lib4sdk="${platform_sdk}/Lib/AMD64" - lib4sdk="${lib4sdk};${platform_sdk}/Lib/AMD64/atlmfc" - # Search path and DLL locating path - # WARNING: CYGWIN has a link.exe too, make sure compilers are first - path4sdk="${platform_sdk}/bin;${path4sdk}" - path4sdk="${compiler_path};${path4sdk}" + + # Use supplied vsvars.sh + repo=`hg root` + if [ -f "${repo}/make/scripts/vsvars.sh" ] ; then + eval `sh ${repo}/make/scripts/vsvars.sh -v10` + elif [ -f "${repo}/../make/scripts/vsvars.sh" ] ; then + eval `sh ${repo}/../make/scripts/vsvars.sh -v10` + else + echo "WARNING: No make/scripts/vsvars.sh file found" fi - # Export LIB and INCLUDE - unset lib - unset Lib - LIB="${lib4sdk}" - export LIB - unset include - unset Include - INCLUDE="${include4sdk}" - export INCLUDE - # Turn all \\ into /, remove duplicates and trailing / - slash_path="$(echo ${path4sdk} | sed -e 's@\\\\@/@g' -e 's@//@/@g' -e 's@/$@@' -e 's@/;@;@g')" - path4sdk="${slash_path}" - - # Convert path4sdk to cygwin style - path4sdk="$(/usr/bin/cygpath -p ${path4sdk})" - fi # Get the previous JDK to be used to bootstrap the build diff --git a/make/mkdemo/jfc/Makefile b/make/mkdemo/jfc/Makefile index 35ab79b70c90f72bc429e7145e61c8d1e2ff2a28..decfac45061388c2deee0d5eda7ac230fbee6c46 100644 --- a/make/mkdemo/jfc/Makefile +++ b/make/mkdemo/jfc/Makefile @@ -43,7 +43,7 @@ SUBDIRS = \ # Some demos aren't currently included in OpenJDK ifndef OPENJDK - SUBDIRS += Java2D SwingSet2 Stylepad + SUBDIRS += Java2D SwingSet2 SwingSet3 Stylepad endif include $(BUILDDIR)/common/Subdirs.gmk diff --git a/make/java/hpi/Makefile b/make/mkdemo/jfc/SwingSet3/Makefile similarity index 73% rename from make/java/hpi/Makefile rename to make/mkdemo/jfc/SwingSet3/Makefile index 3d3688a99703891fecce60a44661c41487dac2fe..9b9fddacaf58f932fb986a0e55c3150b31ad7647 100644 --- a/make/java/hpi/Makefile +++ b/make/mkdemo/jfc/SwingSet3/Makefile @@ -1,5 +1,5 @@ # -# Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -24,18 +24,20 @@ # # -# Build HPI (Host Porting Interface) libraries +# Makefile to build the SwingSet3 demo. # -BUILDDIR = ../.. +BUILDDIR = ../../.. +PRODUCT = demo/jfc +DEMONAME = SwingSet3 include $(BUILDDIR)/common/Defs.gmk +DEMO_ROOT = $(CLOSED_SRC)/share/demo/jfc/$(DEMONAME) +DEMO_DESTDIR = $(DEMODIR)/jfc/$(DEMONAME) +DEMO_TOPFILES = ./readme.html ./swingset3.png +DEMO_SKIP_SRCZIP = true + # -# Build specified the HPI implementations +# Demo jar building rules. # -SUBDIRS = $(HPIS) -include $(BUILDDIR)/common/Subdirs.gmk - -all build clean clobber:: - $(SUBDIRS-loop) - +include $(BUILDDIR)/common/Demo.gmk diff --git a/make/sun/jpeg/Makefile b/make/sun/jpeg/Makefile index b669ad48de2ddad4aa71f81e996b6330b4f11dae..b16ebea9f0f5710b39212a426ffe70c73a817a26 100644 --- a/make/sun/jpeg/Makefile +++ b/make/sun/jpeg/Makefile @@ -65,6 +65,19 @@ ifeq ($(PLATFORM), solaris) FILES_reorder += reorder-$(ARCH) endif endif + +ifeq ($(PLATFORM), linux) + + # Suppress gcc warnings like "variable might be clobbered by 'longjmp' + # or 'vfork'": this warning indicates that some variable is placed to + # a register by optimized compiler and it's value might be lost on longjmp(). + # Recommended way to avoid such warning is to declare the variable as + # volatile to prevent the optimization. However, this approach does not + # work because we have to declare all variables as volatile in result. + + OTHER_CFLAGS += -Wno-clobbered +endif + include $(BUILDDIR)/common/Mapfile-vers.gmk include $(BUILDDIR)/common/Library.gmk diff --git a/make/sun/jpeg/reorder-i586 b/make/sun/jpeg/reorder-i586 index 3fe7ea991bf11eb315f54ca3cf2fc39da81a9993..47e18ca44d1312806dcd981257ba282b0e05b225 100644 --- a/make/sun/jpeg/reorder-i586 +++ b/make/sun/jpeg/reorder-i586 @@ -22,7 +22,7 @@ text: .text%jIMReader; text: .text%alloc_small: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jmemmgr.o; text: .text%reset_marker_reader: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; text: .text%jIInCtlr; -text: .text%GET_ARRAYS: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jpegdecoder.o; +# text: .text%GET_ARRAYS: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jpegdecoder.o; text: .text%jReadHeader; text: .text%jConsumeInput; text: .text%reset_input_controller: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdinput.o; @@ -30,36 +30,36 @@ text: .text%reset_error_mgr: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jerror.o; text: .text%sun_jpeg_init_source; text: .text%consume_markers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdinput.o; text: .text%read_markers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; -text: .text%first_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; +# text: .text%first_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; text: .text%sun_jpeg_fill_input_buffer; -text: .text%RELEASE_ARRAYS: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jpegdecoder.o; -text: .text%get_soi: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; +# text: .text%RELEASE_ARRAYS: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jpegdecoder.o; +# text: .text%get_soi: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; text: .text%emit_message: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jerror.o; -text: .text%next_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; +# text: .text%next_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; text: .text%get_interesting_appn: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; -text: .text%examine_app0: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; +# text: .text%examine_app0: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; text: .text%skip_variable: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; text: .text%sun_jpeg_skip_input_data; -text: .text%examine_app14: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; +# text: .text%examine_app14: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; text: .text%get_dqt: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; text: .text%jAlcQTable; text: .text%get_sof: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; -text: .text%get_dri: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; +# text: .text%get_dri: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; text: .text%get_dht: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; text: .text%jAlcHTable; text: .text%get_sos: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; -text: .text%initial_setup: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdinput.o; +# text: .text%initial_setup: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdinput.o; text: .text%jDivRound; -text: .text%default_decompress_parms: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdapimin.o; +# text: .text%default_decompress_parms: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdapimin.o; text: .text%jHasMultScn; text: .text%jStrtDecompress; text: .text%jIDMaster; -text: .text%master_selection: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o; +# text: .text%master_selection: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o; text: .text%jCalcDimensions; -text: .text%use_merged_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o; -text: .text%prepare_range_limit_table: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o; +# text: .text%use_merged_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o; +# text: .text%prepare_range_limit_table: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o; text: .text%jIDColor; -text: .text%build_ycc_rgb_table: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcolor.o; +# text: .text%build_ycc_rgb_table: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcolor.o; text: .text%jIUpsampler; text: .text%jRound; text: .text%alloc_sarray: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jmemmgr.o; @@ -70,16 +70,16 @@ text: .text%jIIDCT; text: .text%jIHDecoder; text: .text%jIDCoefC; text: .text%jIDMainC; -text: .text%alloc_funny_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o; +# text: .text%alloc_funny_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o; text: .text%realize_virt_arrays: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jmemmgr.o; text: .text%start_input_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdinput.o; -text: .text%per_scan_setup: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdinput.o; -text: .text%latch_quant_tables: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdinput.o; +# text: .text%per_scan_setup: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdinput.o; +# text: .text%latch_quant_tables: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdinput.o; text: .text%start_pass_huff_decoder: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdhuff.o; text: .text%jMkDDerived; text: .text%start_input_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcoefct.o; -text: .text%start_iMCU_row: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcoefct.o; -text: .text%output_pass_setup: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdapistd.o; +# text: .text%start_iMCU_row: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcoefct.o; +# text: .text%output_pass_setup: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdapistd.o; text: .text%prepare_for_output_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o; text: .text%start_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jddctmgr.o; text: .text%start_output_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcoefct.o; @@ -87,7 +87,7 @@ text: .text%start_pass_dcolor: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcolor.o; text: .text%start_pass_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdsample.o; text: .text%start_pass_dpost: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdpostct.o; text: .text%start_pass_main: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o; -text: .text%make_funny_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o; +# text: .text%make_funny_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o; text: .text%jReadScanlines; text: .text%process_data_context_main: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o; text: .text%decompress_onepass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcoefct.o; @@ -100,11 +100,11 @@ text: .text%sep_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdsample.o; text: .text%fullsize_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdsample.o; text: .text%h2v2_fancy_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdsample.o; text: .text%ycc_rgb_convert: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcolor.o; -text: .text%set_wraparound_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o; -text: .text%process_restart: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdhuff.o; +# text: .text%set_wraparound_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o; +# text: .text%process_restart: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdhuff.o; text: .text%read_restart_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; text: .text%finish_input_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdinput.o; -text: .text%set_bottom_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o; +# text: .text%set_bottom_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o; text: .text%jFinDecompress; text: .text%finish_output_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o; text: .text%sun_jpeg_term_source; diff --git a/make/sun/jpeg/reorder-sparc b/make/sun/jpeg/reorder-sparc index 3fe7ea991bf11eb315f54ca3cf2fc39da81a9993..a7b21edca43392fcfb464088ed452e0f17df6988 100644 --- a/make/sun/jpeg/reorder-sparc +++ b/make/sun/jpeg/reorder-sparc @@ -30,10 +30,10 @@ text: .text%reset_error_mgr: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jerror.o; text: .text%sun_jpeg_init_source; text: .text%consume_markers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdinput.o; text: .text%read_markers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; -text: .text%first_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; +# text: .text%first_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; text: .text%sun_jpeg_fill_input_buffer; text: .text%RELEASE_ARRAYS: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jpegdecoder.o; -text: .text%get_soi: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; +# text: .text%get_soi: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; text: .text%emit_message: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jerror.o; text: .text%next_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; text: .text%get_interesting_appn: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; @@ -44,7 +44,7 @@ text: .text%examine_app14: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; text: .text%get_dqt: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; text: .text%jAlcQTable; text: .text%get_sof: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; -text: .text%get_dri: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; +# text: .text%get_dri: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; text: .text%get_dht: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; text: .text%jAlcHTable; text: .text%get_sos: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; @@ -56,10 +56,10 @@ text: .text%jStrtDecompress; text: .text%jIDMaster; text: .text%master_selection: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o; text: .text%jCalcDimensions; -text: .text%use_merged_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o; -text: .text%prepare_range_limit_table: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o; +# text: .text%use_merged_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o; +# text: .text%prepare_range_limit_table: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o; text: .text%jIDColor; -text: .text%build_ycc_rgb_table: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcolor.o; +# text: .text%build_ycc_rgb_table: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcolor.o; text: .text%jIUpsampler; text: .text%jRound; text: .text%alloc_sarray: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jmemmgr.o; @@ -78,7 +78,7 @@ text: .text%latch_quant_tables: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdinput.o; text: .text%start_pass_huff_decoder: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdhuff.o; text: .text%jMkDDerived; text: .text%start_input_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcoefct.o; -text: .text%start_iMCU_row: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcoefct.o; +# text: .text%start_iMCU_row: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcoefct.o; text: .text%output_pass_setup: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdapistd.o; text: .text%prepare_for_output_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o; text: .text%start_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jddctmgr.o; @@ -100,11 +100,11 @@ text: .text%sep_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdsample.o; text: .text%fullsize_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdsample.o; text: .text%h2v2_fancy_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdsample.o; text: .text%ycc_rgb_convert: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcolor.o; -text: .text%set_wraparound_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o; -text: .text%process_restart: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdhuff.o; +# text: .text%set_wraparound_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o; +#text: .text%process_restart: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdhuff.o; text: .text%read_restart_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; text: .text%finish_input_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdinput.o; -text: .text%set_bottom_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o; +# text: .text%set_bottom_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o; text: .text%jFinDecompress; text: .text%finish_output_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o; text: .text%sun_jpeg_term_source; diff --git a/make/sun/jpeg/reorder-sparcv9 b/make/sun/jpeg/reorder-sparcv9 index e5447a4f56f002b6e5ba0884f4e071afb69c863e..3af1a21eb8024ce5f5e1eac38a8857ad51f761ec 100644 --- a/make/sun/jpeg/reorder-sparcv9 +++ b/make/sun/jpeg/reorder-sparcv9 @@ -30,10 +30,10 @@ text: .text%reset_error_mgr: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jerror.o; text: .text%sun_jpeg_init_source; text: .text%consume_markers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdinput.o; text: .text%read_markers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o; -text: .text%first_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o; +# text: .text%first_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o; text: .text%sun_jpeg_fill_input_buffer; text: .text%RELEASE_ARRAYS: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jpegdecoder.o; -text: .text%get_soi: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o; +# text: .text%get_soi: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o; text: .text%emit_message: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jerror.o; text: .text%next_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o; text: .text%get_interesting_appn: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o; @@ -44,7 +44,7 @@ text: .text%examine_app14: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o; text: .text%get_dqt: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o; text: .text%jAlcQTable; text: .text%get_sof: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o; -text: .text%get_dri: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o; +# text: .text%get_dri: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o; text: .text%get_dht: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o; text: .text%jAlcHTable; text: .text%get_sos: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o; @@ -56,10 +56,10 @@ text: .text%jStrtDecompress; text: .text%jIDMaster; text: .text%master_selection: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmaster.o; text: .text%jCalcDimensions; -text: .text%use_merged_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmaster.o; -text: .text%prepare_range_limit_table: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmaster.o; +# text: .text%use_merged_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmaster.o; +# text: .text%prepare_range_limit_table: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmaster.o; text: .text%jIDColor; -text: .text%build_ycc_rgb_table: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdcolor.o; +# text: .text%build_ycc_rgb_table: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdcolor.o; text: .text%jIUpsampler; text: .text%jRound; text: .text%alloc_sarray: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jmemmgr.o; @@ -78,7 +78,7 @@ text: .text%latch_quant_tables: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdinput.o; text: .text%start_pass_huff_decoder: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdhuff.o; text: .text%jMkDDerived; text: .text%start_input_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdcoefct.o; -text: .text%start_iMCU_row: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdcoefct.o; +# text: .text%start_iMCU_row: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdcoefct.o; text: .text%output_pass_setup: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdapistd.o; text: .text%prepare_for_output_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmaster.o; text: .text%start_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jddctmgr.o; @@ -100,11 +100,11 @@ text: .text%sep_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdsample.o; text: .text%fullsize_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdsample.o; text: .text%h2v2_fancy_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdsample.o; text: .text%ycc_rgb_convert: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdcolor.o; -text: .text%set_wraparound_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmainct.o; +# text: .text%set_wraparound_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmainct.o; text: .text%process_restart: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdhuff.o; text: .text%read_restart_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o; text: .text%finish_input_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdinput.o; -text: .text%set_bottom_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmainct.o; +# text: .text%set_bottom_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmainct.o; text: .text%jFinDecompress; text: .text%finish_output_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmaster.o; text: .text%sun_jpeg_term_source; diff --git a/make/sun/net/FILES_java.gmk b/make/sun/net/FILES_java.gmk index 23c94b42ab03411a346e211d8a5cb4888d5f4cbe..576159c4799c835652c0e6b9b71bb47dcd18449c 100644 --- a/make/sun/net/FILES_java.gmk +++ b/make/sun/net/FILES_java.gmk @@ -33,6 +33,7 @@ FILES_java = \ sun/net/ProgressEvent.java \ sun/net/ProgressListener.java \ sun/net/ProgressMeteringPolicy.java \ + sun/net/SocksProxy.java \ sun/net/TelnetInputStream.java \ sun/net/TelnetOutputStream.java \ sun/net/TelnetProtocolException.java \ diff --git a/make/tools/reorder/Makefile b/make/tools/reorder/Makefile index 69178f11ce729fa389657b4531dc5623736fc5ca..39439667530d1fece4e7603b0ec0ae79dc74df5d 100644 --- a/make/tools/reorder/Makefile +++ b/make/tools/reorder/Makefile @@ -85,7 +85,6 @@ reorder.jar : $(REORDER_JAR) libs.reorder : ifeq ($(PLATFORM), solaris) $(MAKE) LIBBLDDIR=java/zip LIBTMPDIR=sun/java.util.zip/zip reorder.lib - $(MAKE) LIBBLDDIR=java/hpi/native LIBTMPDIR=java/hpi/native_threads reorder.lib $(MAKE) LIBBLDDIR=java/java LIBTMPDIR=java/java.lang/java reorder.lib $(MAKE) LIBBLDDIR=java/nio LIBTMPDIR=java/java.nio/nio reorder.lib $(MAKE) LIBBLDDIR=sun/font LIBTMPDIR=sun/sun.awt.font/fontmanager reorder.lib @@ -96,7 +95,6 @@ endif libs.copy: ifeq ($(PLATFORM), solaris) $(CP) $(OUTDIR)/reorder_java_zip-$(ARCH) ../../java/zip/reorder-$(ARCH) - $(CP) $(OUTDIR)/reorder_java_hpi_native-$(ARCH) ../../java/hpi/native/reorder-$(ARCH) $(CP) $(OUTDIR)/reorder_java_java-$(ARCH) ../../java/java/reorder-$(ARCH) $(CP) $(OUTDIR)/reorder_sun_font-$(ARCH) ../../sun/font/reorder-$(ARCH) $(CP) $(OUTDIR)/reorder_sun_jpeg-$(ARCH) ../../sun/jpeg/reorder-$(ARCH) diff --git a/src/share/back/debugInit.c b/src/share/back/debugInit.c index e09971b0a06d574a82f16a05ad1b349708ed5fad..39c6ad53fba0566d4ca51ae6d472fe3749043eb5 100644 --- a/src/share/back/debugInit.c +++ b/src/share/back/debugInit.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -133,27 +133,60 @@ set_event_notification(jvmtiEventMode mode, EventIndex ei) return error; } +typedef struct { + int major; + int minor; +} version_type; + +typedef struct { + version_type runtime; + version_type compiletime; +} compatible_versions_type; + +/* + * List of explicitly compatible JVMTI versions, specified as + * { runtime version, compile-time version } pairs. -1 is a wildcard. + */ +static int nof_compatible_versions = 3; +static compatible_versions_type compatible_versions_list[] = { + /* + * FIXUP: Allow version 0 to be compatible with anything + * Special check for FCS of 1.0. + */ + { { 0, -1 }, { -1, -1 } }, + { { -1, -1 }, { 0, -1 } }, + /* + * 1.2 is runtime compatible with 1.1 -- just make sure to check the + * version before using any new 1.2 features + */ + { { 1, 1 }, { 1, 2 } } +}; + + /* Logic to determine JVMTI version compatibility */ static jboolean compatible_versions(jint major_runtime, jint minor_runtime, jint major_compiletime, jint minor_compiletime) { -#if 1 /* FIXUP: We allow version 0 to be compatible with anything */ - /* Special check for FCS of 1.0. */ - if ( major_runtime == 0 || major_compiletime == 0 ) { - return JNI_TRUE; - } -#endif - /* Runtime major version must match. */ - if ( major_runtime != major_compiletime ) { - return JNI_FALSE; - } - /* Runtime minor version must be >= the version compiled with. */ - if ( minor_runtime < minor_compiletime ) { - return JNI_FALSE; + /* + * First check to see if versions are explicitly compatible via the + * list specified above. + */ + int i; + for (i = 0; i < nof_compatible_versions; ++i) { + version_type runtime = compatible_versions_list[i].runtime; + version_type comptime = compatible_versions_list[i].compiletime; + + if ((major_runtime == runtime.major || runtime.major == -1) && + (minor_runtime == runtime.minor || runtime.minor == -1) && + (major_compiletime == comptime.major || comptime.major == -1) && + (minor_compiletime == comptime.minor || comptime.minor == -1)) { + return JNI_TRUE; + } } - /* Assumed compatible */ - return JNI_TRUE; + + return major_runtime == major_compiletime && + minor_runtime >= minor_compiletime; } /* OnLoad startup: diff --git a/src/share/back/eventFilter.c b/src/share/back/eventFilter.c index b0c2bd19b981a790bbee6b1079c213734be747bb..3d816d37019d369e2eba19b0c6a224306ba2cc82 100644 --- a/src/share/back/eventFilter.c +++ b/src/share/back/eventFilter.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +39,7 @@ #include "stepControl.h" #include "threadControl.h" #include "SDE.h" +#include "jvmti.h" typedef struct ClassFilter { jclass clazz; @@ -275,6 +276,24 @@ patternStringMatch(char *classname, const char *pattern) } } +static jboolean isVersionGte12x() { + jint version; + jvmtiError err = + JVMTI_FUNC_PTR(gdata->jvmti,GetVersionNumber)(gdata->jvmti, &version); + + if (err == JVMTI_ERROR_NONE) { + jint major, minor; + + major = (version & JVMTI_VERSION_MASK_MAJOR) + >> JVMTI_VERSION_SHIFT_MAJOR; + minor = (version & JVMTI_VERSION_MASK_MINOR) + >> JVMTI_VERSION_SHIFT_MINOR; + return (major > 1 || major == 1 && minor >= 2); + } else { + return JNI_FALSE; + } +} + /* Return the object instance in which the event occurred */ /* Return NULL if static or if an error occurs */ static jobject @@ -286,6 +305,14 @@ eventInstance(EventInfo *evinfo) jint modifiers = 0; jvmtiError error; + static jboolean got_version = JNI_FALSE; + static jboolean is_version_gte_12x = JNI_FALSE; + + if (!got_version) { + is_version_gte_12x = isVersionGte12x(); + got_version = JNI_TRUE; + } + switch (evinfo->ei) { case EI_SINGLE_STEP: case EI_BREAKPOINT: @@ -314,11 +341,18 @@ eventInstance(EventInfo *evinfo) /* fail if error or static (0x8) */ if (error == JVMTI_ERROR_NONE && thread!=NULL && (modifiers & 0x8) == 0) { FrameNumber fnum = 0; - /* get slot zero object "this" */ - error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalObject) - (gdata->jvmti, thread, fnum, 0, &object); - if (error != JVMTI_ERROR_NONE) + if (is_version_gte_12x) { + /* Use new 1.2.x function, GetLocalInstance */ + error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalInstance) + (gdata->jvmti, thread, fnum, &object); + } else { + /* get slot zero object "this" */ + error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalObject) + (gdata->jvmti, thread, fnum, 0, &object); + } + if (error != JVMTI_ERROR_NONE) { object = NULL; + } } return object; diff --git a/src/share/bin/java.c b/src/share/bin/java.c index 2d1149cd9204e3ffd21e304d5dd3c087f0b6e9f6..c2a6ab99249a05a53e044c0bf7a1a337950e8915 100644 --- a/src/share/bin/java.c +++ b/src/share/bin/java.c @@ -94,15 +94,15 @@ static int numOptions, maxOptions; * Prototypes for functions internal to launcher. */ static void SetClassPath(const char *s); -static void SetModulesBootClassPath(const char *s); static void SelectVersion(int argc, char **argv, char **main_class); -static jboolean ParseArguments(int *pargc, char ***pargv, char **pjarfile, - char **pclassname, int *pret, const char *jvmpath); +static jboolean ParseArguments(int *pargc, char ***pargv, + int *pmode, char **pwhat, + int *pret, const char *jrepath); static jboolean InitializeJVM(JavaVM **pvm, JNIEnv **penv, InvocationFunctions *ifn); static jstring NewPlatformString(JNIEnv *env, char *s); static jobjectArray NewPlatformStringArray(JNIEnv *env, char **strv, int strc); -static jclass LoadMainClass(JNIEnv *env, jboolean isJar, char *name); +static jclass LoadMainClass(JNIEnv *env, int mode, char *name); static void TranslateApplicationArgs(int jargc, const char **jargv, int *pargc, char ***pargv); static jboolean AddApplicationOptions(int cpathc, const char **cpathv); @@ -158,18 +158,27 @@ static jboolean IsWildCardEnabled(); * Running Java code in primordial thread caused many problems. We will * create a new thread to invoke JVM. See 6316197 for more information. */ -static jlong threadStackSize = 0; /* stack size of the new thread */ +static jlong threadStackSize = 0; /* stack size of the new thread */ static jlong maxHeapSize = 0; /* max heap size */ static jlong initialHeapSize = 0; /* inital heap size */ int JNICALL JavaMain(void * args); /* entry point */ +enum LaunchMode { // cf. sun.launcher.LauncherHelper + LM_UNKNOWN = 0, + LM_CLASS, + LM_JAR +}; + +static const char *launchModeNames[] + = { "Unknown", "Main class", "JAR file" }; + typedef struct { - int argc; - char ** argv; - char * jarfile; - char * classname; - InvocationFunctions ifn; + int argc; + char **argv; + int mode; + char *what; + InvocationFunctions ifn; } JavaMainArgs; /* @@ -189,8 +198,8 @@ JLI_Launch(int argc, char ** argv, /* main argc, argc */ jint ergo /* ergonomics class policy */ ) { - char *jarfile = 0; - char *classname = 0; + int mode = LM_UNKNOWN; + char *what = NULL; char *cpath = 0; char *main_class = NULL; int ret; @@ -277,24 +286,21 @@ JLI_Launch(int argc, char ** argv, /* main argc, argc */ SetClassPath(cpath); } - /* - * Parse command line options; if the return value of - * ParseArguments is false, the program should exit. + /* Parse command line options; if the return value of + * ParseArguments is false, the program should exit. */ - if (!ParseArguments(&argc, &argv, &jarfile, &classname, &ret, jvmpath)) { + if (!ParseArguments(&argc, &argv, &mode, &what, &ret, jrepath)) + { return(ret); } - /* Set bootclasspath for modules */ - SetModulesBootClassPath(jrepath); - /* Override class path if -jar flag was specified */ - if (jarfile != 0) { - SetClassPath(jarfile); + if (mode == LM_JAR) { + SetClassPath(what); /* Override class path */ } /* set the -Dsun.java.command pseudo property */ - SetJavaCommandLineProp(classname, jarfile, argc, argv); + SetJavaCommandLineProp(what, argc, argv); /* Set the -Dsun.java.launcher pseudo property */ SetJavaLauncherProp(); @@ -305,7 +311,7 @@ JLI_Launch(int argc, char ** argv, /* main argc, argc */ /* Show the splash screen if needed */ ShowSplashScreen(); - return ContinueInNewThread(&ifn, argc, argv, jarfile, classname, ret); + return ContinueInNewThread(&ifn, argc, argv, mode, what, ret); } /* @@ -353,13 +359,13 @@ JavaMain(void * _args) JavaMainArgs *args = (JavaMainArgs *)_args; int argc = args->argc; char **argv = args->argv; - char *jarfile = args->jarfile; - char *classname = args->classname; + int mode = args->mode; + char *what = args->what; InvocationFunctions ifn = args->ifn; JavaVM *vm = 0; JNIEnv *env = 0; - jclass mainClass; + jclass mainClass = NULL; jmethodID mainID; jobjectArray mainArgs; int ret = 0; @@ -385,7 +391,7 @@ JavaMain(void * _args) CHECK_EXCEPTION_LEAVE(1); } /* If the user specified neither a class name nor a JAR file */ - if (printXUsage || printUsage || (jarfile == 0 && classname == 0)) { + if (printXUsage || printUsage || what == 0 || mode == LM_UNKNOWN) { PrintUsage(env, printXUsage); CHECK_EXCEPTION_LEAVE(1); LEAVE(); @@ -399,11 +405,11 @@ JavaMain(void * _args) (long)(jint)Counter2Micros(end-start)); } - /* At this stage, argc/argv have the applications' arguments */ + /* At this stage, argc/argv have the application's arguments */ if (JLI_IsTraceLauncher()){ int i; - printf("Main-Class is '%s'\n", classname ? classname : ""); - printf("Apps' argc is %d\n", argc); + printf("%s is '%s'\n", launchModeNames[mode], what); + printf("App's argc is %d\n", argc); for (i=0; i < argc; i++) { printf(" argv[%2d] = '%s'\n", i, argv[i]); } @@ -431,11 +437,7 @@ JavaMain(void * _args) * 2) Remove the vestages of maintaining main_class through * the environment (and remove these comments). */ - if (jarfile != 0) { - mainClass = LoadMainClass(env, JNI_TRUE, jarfile); - } else { - mainClass = LoadMainClass(env, JNI_FALSE, classname); - } + mainClass = LoadMainClass(env, mode, what); CHECK_EXCEPTION_NULL_LEAVE(mainClass); /* @@ -697,7 +699,7 @@ AddOption(char *str, void *info) if (JLI_StrCCmp(str, "-Xms") == 0) { jlong tmp; if (parse_size(str + 4, &tmp)) { - initialHeapSize = tmp; + initialHeapSize = tmp; } } } @@ -718,44 +720,6 @@ SetClassPath(const char *s) JLI_MemFree((char *) s); } -/* - * Set the bootclasspath for modules. - * A temporary workaround until jigsaw is integrated into JDK 7. - */ -static void -SetModulesBootClassPath(const char *jrepath) -{ - char *def, *s; - char pathname[MAXPATHLEN]; - const char separator[] = { FILE_SEPARATOR, '\0' }; - const char *orig = jrepath; - static const char format[] = "-Xbootclasspath/p:%s"; - struct stat statbuf; - - /* return if jre/lib/rt.jar exists */ - JLI_Snprintf(pathname, sizeof(pathname), "%s%slib%srt.jar", jrepath, separator, separator); - if (stat(pathname, &statbuf) == 0) { - return; - } - - /* return if jre/classes exists */ - JLI_Snprintf(pathname, sizeof(pathname), "%s%sclasses", jrepath, separator); - if (stat(pathname, &statbuf) == 0) { - return; - } - - /* modularized jre */ - JLI_Snprintf(pathname, sizeof(pathname), "%s%slib%s*", jrepath, separator, separator); - s = (char *) JLI_WildcardExpandClasspath(pathname); - def = JLI_MemAlloc(sizeof(format) - - 2 /* strlen("%s") */ - + JLI_StrLen(s)); - sprintf(def, format, s); - AddOption(def, NULL); - if (s != orig) - JLI_MemFree((char *) s); -} - /* * The SelectVersion() routine ensures that an appropriate version of * the JRE is running. The specification for the appropriate version @@ -1000,16 +964,17 @@ SelectVersion(int argc, char **argv, char **main_class) /* * Parses command line arguments. Returns JNI_FALSE if launcher * should exit without starting vm, returns JNI_TRUE if vm needs - * to be started to process given options. *pret (the launcher + * to be started to process given options. *pret (the launcher * process return value) is set to 0 for a normal exit. */ static jboolean -ParseArguments(int *pargc, char ***pargv, char **pjarfile, - char **pclassname, int *pret, const char *jvmpath) +ParseArguments(int *pargc, char ***pargv, + int *pmode, char **pwhat, + int *pret, const char *jrepath) { int argc = *pargc; char **argv = *pargv; - jboolean jarflag = JNI_FALSE; + int mode = LM_UNKNOWN; char *arg; *pret = 0; @@ -1019,10 +984,11 @@ ParseArguments(int *pargc, char ***pargv, char **pjarfile, if (JLI_StrCmp(arg, "-classpath") == 0 || JLI_StrCmp(arg, "-cp") == 0) { ARG_CHECK (argc, ARG_ERROR1, arg); SetClassPath(*argv); + mode = LM_CLASS; argv++; --argc; } else if (JLI_StrCmp(arg, "-jar") == 0) { ARG_CHECK (argc, ARG_ERROR2, arg); - jarflag = JNI_TRUE; + mode = LM_JAR; } else if (JLI_StrCmp(arg, "-help") == 0 || JLI_StrCmp(arg, "-h") == 0 || JLI_StrCmp(arg, "-?") == 0) { @@ -1102,19 +1068,24 @@ ParseArguments(int *pargc, char ***pargv, char **pjarfile, } if (--argc >= 0) { - if (jarflag) { - *pjarfile = *argv++; - *pclassname = NULL; - } else { - *pjarfile = NULL; - *pclassname = *argv++; - } - *pargc = argc; - *pargv = argv; + *pwhat = *argv++; } - if (*pjarfile == NULL && *pclassname == NULL) { + + if (*pwhat == NULL) { *pret = 1; + } else if (mode == LM_UNKNOWN) { + /* default to LM_CLASS if -jar and -cp option are + * not specified */ + mode = LM_CLASS; + } + + if (argc >= 0) { + *pargc = argc; + *pargv = argv; } + + *pmode = mode; + return JNI_TRUE; } @@ -1263,7 +1234,7 @@ NewPlatformStringArray(JNIEnv *env, char **strv, int strc) * call it for more details refer to the java implementation. */ static jclass -LoadMainClass(JNIEnv *env, jboolean isJar, char *name) +LoadMainClass(JNIEnv *env, int mode, char *name) { jclass cls; jmethodID mid; @@ -1276,9 +1247,9 @@ LoadMainClass(JNIEnv *env, jboolean isJar, char *name) } NULL_CHECK0(cls = FindBootStrapClass(env, "sun/launcher/LauncherHelper")); NULL_CHECK0(mid = (*env)->GetStaticMethodID(env, cls, "checkAndLoadMain", - "(ZZLjava/lang/String;)Ljava/lang/Object;")); + "(ZILjava/lang/String;)Ljava/lang/Class;")); str = (*env)->NewStringUTF(env, name); - result = (*env)->CallStaticObjectMethod(env, cls, mid, JNI_TRUE, isJar, str); + result = (*env)->CallStaticObjectMethod(env, cls, mid, JNI_TRUE, mode, str); if (JLI_IsTraceLauncher()) { end = CounterGet(); @@ -1424,8 +1395,7 @@ AddApplicationOptions(int cpathc, const char **cpathv) * property is not exported by HotSpot to the Java layer. */ void -SetJavaCommandLineProp(char *classname, char *jarfile, - int argc, char **argv) +SetJavaCommandLineProp(char *what, int argc, char **argv) { int i = 0; @@ -1433,22 +1403,17 @@ SetJavaCommandLineProp(char *classname, char *jarfile, char* javaCommand = NULL; char* dashDstr = "-Dsun.java.command="; - if (classname == NULL && jarfile == NULL) { + if (what == NULL) { /* unexpected, one of these should be set. just return without * setting the property */ return; } - /* if the class name is not set, then use the jarfile name */ - if (classname == NULL) { - classname = jarfile; - } - /* determine the amount of memory to allocate assuming * the individual components will be space separated */ - len = JLI_StrLen(classname); + len = JLI_StrLen(what); for (i = 0; i < argc; i++) { len += JLI_StrLen(argv[i]) + 1; } @@ -1459,7 +1424,7 @@ SetJavaCommandLineProp(char *classname, char *jarfile, /* build the -D string */ *javaCommand = '\0'; JLI_StrCat(javaCommand, dashDstr); - JLI_StrCat(javaCommand, classname); + JLI_StrCat(javaCommand, what); for (i = 0; i < argc; i++) { /* the components of the string are space separated. In @@ -1479,7 +1444,8 @@ SetJavaCommandLineProp(char *classname, char *jarfile, * JVM would like to know if it's created by a standard Sun launcher, or by * user native application, the following property indicates the former. */ -void SetJavaLauncherProp() { +void +SetJavaLauncherProp() { AddOption("-Dsun.java.launcher=SUN_STANDARD", NULL); } @@ -1913,8 +1879,8 @@ IsWildCardEnabled() } static int -ContinueInNewThread(InvocationFunctions* ifn, int argc, - char **argv, char *jarfile, char *classname, int ret) +ContinueInNewThread(InvocationFunctions* ifn, int argc, char **argv, + int mode, char *what, int ret) { /* @@ -1938,8 +1904,8 @@ ContinueInNewThread(InvocationFunctions* ifn, int argc, args.argc = argc; args.argv = argv; - args.jarfile = jarfile; - args.classname = classname; + args.mode = mode; + args.what = what; args.ifn = *ifn; rslt = ContinueInNewThread0(JavaMain, threadStackSize, (void*)&args); diff --git a/src/share/bin/java.h b/src/share/bin/java.h index 7c78643dc397e785b8a2fa833cca335b3c0a2345..7aba5ce096a9f5643c35e3ac773781d98a4e07b3 100644 --- a/src/share/bin/java.h +++ b/src/share/bin/java.h @@ -153,7 +153,7 @@ int ContinueInNewThread0(int (JNICALL *continuation)(void *), /* sun.java.launcher.* platform properties. */ void SetJavaLauncherPlatformProps(void); -void SetJavaCommandLineProp(char* classname, char* jarfile, int argc, char** argv); +void SetJavaCommandLineProp(char* what, int argc, char** argv); void SetJavaLauncherProp(void); /* @@ -178,8 +178,9 @@ jint GetErgoPolicy(); jboolean ServerClassMachine(); -static int ContinueInNewThread(InvocationFunctions* ifn, int argc, char** argv, - char* jarfile, char* classname, int ret); +static int ContinueInNewThread(InvocationFunctions* ifn, + int argc, char** argv, + int mode, char *what, int ret); /* * Initialize platform specific settings diff --git a/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java b/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java index 3a154a088b96467c34921bc06a8e2304fd6bcda4..473d51108c0bf875c06fb19dcc32671774508822 100644 --- a/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java +++ b/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java @@ -1704,7 +1704,7 @@ class BandStructure { for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) { assert(attrIndexLimit[i] == 0); attrIndexLimit[i] = 32; // just for the sake of predefs. - attrDefs.set(i, new ArrayList<>(Collections.nCopies( + attrDefs.set(i, new ArrayList(Collections.nCopies( attrIndexLimit[i], (Attribute.Layout)null))); } diff --git a/src/share/classes/com/sun/management/ThreadMXBean.java b/src/share/classes/com/sun/management/ThreadMXBean.java new file mode 100644 index 0000000000000000000000000000000000000000..f5a9a5b9a0d199a2caa4f84dae597c559a91b29c --- /dev/null +++ b/src/share/classes/com/sun/management/ThreadMXBean.java @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.management; + +import java.util.Map; + +/** + * Platform-specific management interface for the thread system + * of the Java virtual machine. + *

+ * This platform extension is only available to a thread + * implementation that supports this extension. + * + * @author Paul Hohensee + * @since 6u25 + */ + +public interface ThreadMXBean extends java.lang.management.ThreadMXBean { + /** + * Returns the total CPU time for each thread whose ID is + * in the input array {@code ids} in nanoseconds. + * The returned values are of nanoseconds precision but + * not necessarily nanoseconds accuracy. + *

+ * This method is equivalent to calling the + * {@link ThreadMXBean#getThreadCpuTime(long)} + * method for each thread ID in the input array {@code ids} and setting the + * returned value in the corresponding element of the returned array. + * + * @param ids an array of thread IDs. + * @return an array of long values, each of which is the amount of CPU + * time the thread whose ID is in the corresponding element of the input + * array of IDs has used, + * if the thread of a specified ID exists, the thread is alive, + * and CPU time measurement is enabled; + * {@code -1} otherwise. + * + * @throws NullPointerException if {@code ids} is {@code null} + * @throws IllegalArgumentException if any element in the input array + * {@code ids} is {@code <=} {@code 0}. + * @throws java.lang.UnsupportedOperationException if the Java + * virtual machine implementation does not support CPU time + * measurement. + * + * @see ThreadMXBean#getThreadCpuTime(long) + * @see #getThreadUserTime + * @see ThreadMXBean#isThreadCpuTimeSupported + * @see ThreadMXBean#isThreadCpuTimeEnabled + * @see ThreadMXBean#setThreadCpuTimeEnabled + */ + public long[] getThreadCpuTime(long[] ids); + + /** + * Returns the CPU time that each thread whose ID is in the input array + * {@code ids} has executed in user mode in nanoseconds. + * The returned values are of nanoseconds precision but + * not necessarily nanoseconds accuracy. + *

+ * This method is equivalent to calling the + * {@link ThreadMXBean#getThreadUserTime(long)} + * method for each thread ID in the input array {@code ids} and setting the + * returned value in the corresponding element of the returned array. + * + * @param ids an array of thread IDs. + * @return an array of long values, each of which is the amount of user + * mode CPU time the thread whose ID is in the corresponding element of + * the input array of IDs has used, + * if the thread of a specified ID exists, the thread is alive, + * and CPU time measurement is enabled; + * {@code -1} otherwise. + * + * @throws NullPointerException if {@code ids} is {@code null} + * @throws IllegalArgumentException if any element in the input array + * {@code ids} is {@code <=} {@code 0}. + * @throws java.lang.UnsupportedOperationException if the Java + * virtual machine implementation does not support CPU time + * measurement. + * + * @see ThreadMXBean#getThreadUserTime(long) + * @see #getThreadCpuTime + * @see ThreadMXBean#isThreadCpuTimeSupported + * @see ThreadMXBean#isThreadCpuTimeEnabled + * @see ThreadMXBean#setThreadCpuTimeEnabled + */ + public long[] getThreadUserTime(long[] ids); + + /** + * Returns an approximation of the total amount of memory, in bytes, + * allocated in heap memory for the thread of the specified ID. + * The returned value is an approximation because some Java virtual machine + * implementations may use object allocation mechanisms that result in a + * delay between the time an object is allocated and the time its size is + * recorded. + *

+ * If the thread of the specified ID is not alive or does not exist, + * this method returns {@code -1}. If thread memory allocation measurement + * is disabled, this method returns {@code -1}. + * A thread is alive if it has been started and has not yet died. + *

+ * If thread memory allocation measurement is enabled after the thread has + * started, the Java virtual machine implementation may choose any time up + * to and including the time that the capability is enabled as the point + * where thread memory allocation measurement starts. + * + * @param id the thread ID of a thread + * @return an approximation of the total memory allocated, in bytes, in + * heap memory for a thread of the specified ID + * if the thread of the specified ID exists, the thread is alive, + * and thread memory allocation measurement is enabled; + * {@code -1} otherwise. + * + * @throws IllegalArgumentException if {@code id} {@code <=} {@code 0}. + * @throws java.lang.UnsupportedOperationException if the Java virtual + * machine implementation does not support thread memory allocation + * measurement. + * + * @see #isThreadAllocatedMemorySupported + * @see #isThreadAllocatedMemoryEnabled + * @see #setThreadAllocatedMemoryEnabled + */ + public long getThreadAllocatedBytes(long id); + + /** + * Returns an approximation of the total amount of memory, in bytes, + * allocated in heap memory for each thread whose ID is in the input + * array {@code ids}. + * The returned values are approximations because some Java virtual machine + * implementations may use object allocation mechanisms that result in a + * delay between the time an object is allocated and the time its size is + * recorded. + *

+ * This method is equivalent to calling the + * {@link #getThreadAllocatedBytes(long)} + * method for each thread ID in the input array {@code ids} and setting the + * returned value in the corresponding element of the returned array. + * + * @param ids an array of thread IDs. + * @return an array of long values, each of which is an approximation of + * the total memory allocated, in bytes, in heap memory for the thread + * whose ID is in the corresponding element of the input array of IDs. + * + * @throws NullPointerException if {@code ids} is {@code null} + * @throws IllegalArgumentException if any element in the input array + * {@code ids} is {@code <=} {@code 0}. + * @throws java.lang.UnsupportedOperationException if the Java virtual + * machine implementation does not support thread memory allocation + * measurement. + * + * @see #getThreadAllocatedBytes(long) + * @see #isThreadAllocatedMemorySupported + * @see #isThreadAllocatedMemoryEnabled + * @see #setThreadAllocatedMemoryEnabled + */ + public long[] getThreadAllocatedBytes(long[] ids); + + /** + * Tests if the Java virtual machine implementation supports thread memory + * allocation measurement. + * + * @return + * {@code true} + * if the Java virtual machine implementation supports thread memory + * allocation measurement; + * {@code false} otherwise. + */ + public boolean isThreadAllocatedMemorySupported(); + + /** + * Tests if thread memory allocation measurement is enabled. + * + * @return {@code true} if thread memory allocation measurement is enabled; + * {@code false} otherwise. + * + * @throws java.lang.UnsupportedOperationException if the Java virtual + * machine does not support thread memory allocation measurement. + * + * @see #isThreadAllocatedMemorySupported + */ + public boolean isThreadAllocatedMemoryEnabled(); + + /** + * Enables or disables thread memory allocation measurement. The default + * is platform dependent. + * + * @param enable {@code true} to enable; + * {@code false} to disable. + * + * @throws java.lang.UnsupportedOperationException if the Java virtual + * machine does not support thread memory allocation measurement. + * + * @throws java.lang.SecurityException if a security manager + * exists and the caller does not have + * ManagementPermission("control"). + * + * @see #isThreadAllocatedMemorySupported + */ + public void setThreadAllocatedMemoryEnabled(boolean enable); +} diff --git a/src/share/classes/com/sun/script/javascript/RhinoScriptEngine.java b/src/share/classes/com/sun/script/javascript/RhinoScriptEngine.java index 4c21fdb0c801b6f8b3ad55be31ebceb17f84b6eb..6688ec65ab24c4117178e9d81a2f58c5bf29be2c 100644 --- a/src/share/classes/com/sun/script/javascript/RhinoScriptEngine.java +++ b/src/share/classes/com/sun/script/javascript/RhinoScriptEngine.java @@ -223,7 +223,9 @@ public final class RhinoScriptEngine extends AbstractScriptEngine } catch (RhinoException re) { if (DEBUG) re.printStackTrace(); int line = (line = re.lineNumber()) == 0 ? -1 : line; - throw new ScriptException(re.toString(), re.sourceName(), line); + ScriptException se = new ScriptException(re.toString(), re.sourceName(), line); + se.initCause(re); + throw se; } finally { cx.exit(); } @@ -257,6 +259,8 @@ public final class RhinoScriptEngine extends AbstractScriptEngine " str = 'null'; \n" + " } \n" + " var out = context.getWriter(); \n" + + " if (!(out instanceof java.io.PrintWriter))\n" + + " out = new java.io.PrintWriter(out); \n" + " out.print(String(str)); \n" + " if (newline) out.print('\\n'); \n" + " out.flush(); \n" + diff --git a/src/share/classes/com/sun/security/auth/PolicyFile.java b/src/share/classes/com/sun/security/auth/PolicyFile.java index fa9caf79e53501cb486d731895ede0e905a01770..2005f044052ec36971fcb1ce13b84108c855111a 100644 --- a/src/share/classes/com/sun/security/auth/PolicyFile.java +++ b/src/share/classes/com/sun/security/auth/PolicyFile.java @@ -1180,7 +1180,7 @@ public class PolicyFile extends javax.security.auth.Policy { // Done return certs; - ArrayList userCertList = new ArrayList(); + ArrayList userCertList = new ArrayList<>(); i = 0; while (i < certs.length) { userCertList.add(certs[i]); diff --git a/src/share/classes/com/sun/security/auth/callback/DialogCallbackHandler.java b/src/share/classes/com/sun/security/auth/callback/DialogCallbackHandler.java index 63212fafb87bea15c6c010e2e9da6d488554a89b..5f2171904178d448cb49cae6e9108591bd949297 100644 --- a/src/share/classes/com/sun/security/auth/callback/DialogCallbackHandler.java +++ b/src/share/classes/com/sun/security/auth/callback/DialogCallbackHandler.java @@ -99,10 +99,10 @@ public class DialogCallbackHandler implements CallbackHandler { throws UnsupportedCallbackException { /* Collect messages to display in the dialog */ - final List messages = new ArrayList(3); + final List messages = new ArrayList<>(3); /* Collection actions to perform if the user clicks OK */ - final List okActions = new ArrayList(2); + final List okActions = new ArrayList<>(2); ConfirmationInfo confirmation = new ConfirmationInfo(); diff --git a/src/share/classes/com/sun/security/auth/login/ConfigFile.java b/src/share/classes/com/sun/security/auth/login/ConfigFile.java index ad186566fee5d16f13c063c4b273104f5ab33e55..b3689ff21a017537c6af1870b3306b045d346ab0 100644 --- a/src/share/classes/com/sun/security/auth/login/ConfigFile.java +++ b/src/share/classes/com/sun/security/auth/login/ConfigFile.java @@ -152,7 +152,7 @@ public class ConfigFile extends javax.security.auth.login.Configuration { // new configuration HashMap> newConfig = - new HashMap>(); + new HashMap<>(); if (url != null) { @@ -392,8 +392,7 @@ public class ConfigFile extends javax.security.auth.login.Configuration { String moduleClass; String sflag; AppConfigurationEntry.LoginModuleControlFlag controlFlag; - LinkedList configEntries = - new LinkedList(); + LinkedList configEntries = new LinkedList<>(); // application name appName = st.sval; @@ -433,7 +432,7 @@ public class ConfigFile extends javax.security.auth.login.Configuration { } // get the args - HashMap options = new HashMap(); + HashMap options = new HashMap<>(); String key; String value; while (peek(";") == false) { diff --git a/src/share/classes/com/sun/security/auth/module/JndiLoginModule.java b/src/share/classes/com/sun/security/auth/module/JndiLoginModule.java index 59a19849df426db4cfc2ac903f0128ceeec2f742..cede6b640621002d90dfa3180742834396ece7d1 100644 --- a/src/share/classes/com/sun/security/auth/module/JndiLoginModule.java +++ b/src/share/classes/com/sun/security/auth/module/JndiLoginModule.java @@ -184,7 +184,7 @@ public class JndiLoginModule implements LoginModule { private UnixNumericUserPrincipal UIDPrincipal; private UnixNumericGroupPrincipal GIDPrincipal; private LinkedList supplementaryGroups = - new LinkedList(); + new LinkedList<>(); // initial state private Subject subject; diff --git a/src/share/classes/com/sun/security/auth/module/KeyStoreLoginModule.java b/src/share/classes/com/sun/security/auth/module/KeyStoreLoginModule.java index ff6185e3877d6f58dae127552d2ed9b8b125402f..f2199ed890cc2c8ae7b8c329e7bfe9e37a40d9b9 100644 --- a/src/share/classes/com/sun/security/auth/module/KeyStoreLoginModule.java +++ b/src/share/classes/com/sun/security/auth/module/KeyStoreLoginModule.java @@ -658,8 +658,7 @@ public class KeyStoreLoginModule implements LoginModule { throw new FailedLoginException( "Unable to find X.509 certificate chain in keystore"); } else { - LinkedList certList = - new LinkedList(); + LinkedList certList = new LinkedList<>(); for (int i=0; i < fromKeyStore.length; i++) { certList.add(fromKeyStore[i]); } diff --git a/src/share/classes/com/sun/security/auth/module/SolarisLoginModule.java b/src/share/classes/com/sun/security/auth/module/SolarisLoginModule.java index 2767b9a4a22e8b10d573a74aea5f13c35f9e92f9..cca9be6564d5f31ab9d27af20ad60c17188e9a69 100644 --- a/src/share/classes/com/sun/security/auth/module/SolarisLoginModule.java +++ b/src/share/classes/com/sun/security/auth/module/SolarisLoginModule.java @@ -76,7 +76,7 @@ public class SolarisLoginModule implements LoginModule { private SolarisNumericUserPrincipal UIDPrincipal; private SolarisNumericGroupPrincipal GIDPrincipal; private LinkedList supplementaryGroups = - new LinkedList(); + new LinkedList<>(); /** * Initialize this LoginModule. diff --git a/src/share/classes/com/sun/security/auth/module/UnixLoginModule.java b/src/share/classes/com/sun/security/auth/module/UnixLoginModule.java index a29153fb6a95d499d0009fb3c2d36e570f0f69e0..6f9a443f30acfcdfac6a39f962a1ade0d6749fc4 100644 --- a/src/share/classes/com/sun/security/auth/module/UnixLoginModule.java +++ b/src/share/classes/com/sun/security/auth/module/UnixLoginModule.java @@ -70,7 +70,7 @@ public class UnixLoginModule implements LoginModule { private UnixNumericUserPrincipal UIDPrincipal; private UnixNumericGroupPrincipal GIDPrincipal; private LinkedList supplementaryGroups = - new LinkedList(); + new LinkedList<>(); /** * Initialize this LoginModule. diff --git a/src/share/classes/java/io/ObjectStreamClass.java b/src/share/classes/java/io/ObjectStreamClass.java index 2d3e2055860e85acd39ca45cbdad646b2b4544ac..74608db0c1cfac18e664579d0d789124acf5ece1 100644 --- a/src/share/classes/java/io/ObjectStreamClass.java +++ b/src/share/classes/java/io/ObjectStreamClass.java @@ -329,7 +329,7 @@ public class ObjectStreamClass implements Serializable { entry = th; } if (future.set(entry)) { - Caches.localDescs.put(key, new SoftReference<>(entry)); + Caches.localDescs.put(key, new SoftReference(entry)); } else { // nested lookup call already set future entry = future.get(); @@ -2118,7 +2118,7 @@ public class ObjectStreamClass implements Serializable { entry = th; } future.set(entry); - Caches.reflectors.put(key, new SoftReference<>(entry)); + Caches.reflectors.put(key, new SoftReference(entry)); } if (entry instanceof FieldReflector) { diff --git a/src/share/classes/java/io/PrintStream.java b/src/share/classes/java/io/PrintStream.java index 2f4168aaf78d158a05f84468a601aa5417910181..9ed3ff6f910d1fc64fca37b39cc0de2368b68920 100644 --- a/src/share/classes/java/io/PrintStream.java +++ b/src/share/classes/java/io/PrintStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,9 @@ package java.io; import java.util.Formatter; import java.util.Locale; - +import java.nio.charset.Charset; +import java.nio.charset.IllegalCharsetNameException; +import java.nio.charset.UnsupportedCharsetException; /** * A PrintStream adds functionality to another output stream, @@ -56,7 +58,7 @@ public class PrintStream extends FilterOutputStream implements Appendable, Closeable { - private boolean autoFlush = false; + private final boolean autoFlush; private boolean trouble = false; private Formatter formatter; @@ -68,36 +70,69 @@ public class PrintStream extends FilterOutputStream private OutputStreamWriter charOut; /** - * Creates a new print stream. This stream will not flush automatically. - * - * @param out The output stream to which values and objects will be - * printed - * - * @see java.io.PrintWriter#PrintWriter(java.io.OutputStream) + * nonNull is explicitly declared here so as not to create an extra + * dependency on java.util.Objects.nonNull. PrintStream is loaded + * early during system initialization. */ - public PrintStream(OutputStream out) { - this(out, false); + private static T nonNull(T obj, String message) { + if (obj == null) + throw new NullPointerException(message); + return obj; } - /* Initialization is factored into a private constructor (note the swapped - * parameters so that this one isn't confused with the public one) and a - * separate init method so that the following two public constructors can - * share code. We use a separate init method so that the constructor that - * takes an encoding will throw an NPE for a null stream before it throws - * an UnsupportedEncodingException for an unsupported encoding. + /** + * Returns a charset object for the given charset name. + * @throws NullPointerException is csn is null + * @throws UnsupportedEncodingException if the charset is not supported */ - - private PrintStream(boolean autoFlush, OutputStream out) + private static Charset toCharset(String csn) + throws UnsupportedEncodingException { + nonNull(csn, "charsetName"); + try { + return Charset.forName(csn); + } catch (IllegalCharsetNameException|UnsupportedCharsetException unused) { + // UnsupportedEncodingException should be thrown + throw new UnsupportedEncodingException(csn); + } + } + + /* Private constructors */ + private PrintStream(boolean autoFlush, OutputStream out) { + super(out); + this.autoFlush = autoFlush; + this.charOut = new OutputStreamWriter(this); + this.textOut = new BufferedWriter(charOut); + } + + private PrintStream(boolean autoFlush, OutputStream out, Charset charset) { super(out); - if (out == null) - throw new NullPointerException("Null output stream"); this.autoFlush = autoFlush; + this.charOut = new OutputStreamWriter(this, charset); + this.textOut = new BufferedWriter(charOut); } - private void init(OutputStreamWriter osw) { - this.charOut = osw; - this.textOut = new BufferedWriter(osw); + /* Variant of the private constructor so that the given charset name + * can be verified before evaluating the OutputStream argument. Used + * by constructors creating a FileOutputStream that also take a + * charset name. + */ + private PrintStream(boolean autoFlush, Charset charset, OutputStream out) + throws UnsupportedEncodingException + { + this(autoFlush, out, charset); + } + + /** + * Creates a new print stream. This stream will not flush automatically. + * + * @param out The output stream to which values and objects will be + * printed + * + * @see java.io.PrintWriter#PrintWriter(java.io.OutputStream) + */ + public PrintStream(OutputStream out) { + this(out, false); } /** @@ -113,8 +148,7 @@ public class PrintStream extends FilterOutputStream * @see java.io.PrintWriter#PrintWriter(java.io.OutputStream, boolean) */ public PrintStream(OutputStream out, boolean autoFlush) { - this(autoFlush, out); - init(new OutputStreamWriter(this)); + this(autoFlush, nonNull(out, "Null output stream")); } /** @@ -138,8 +172,9 @@ public class PrintStream extends FilterOutputStream public PrintStream(OutputStream out, boolean autoFlush, String encoding) throws UnsupportedEncodingException { - this(autoFlush, out); - init(new OutputStreamWriter(this, encoding)); + this(autoFlush, + nonNull(out, "Null output stream"), + toCharset(encoding)); } /** @@ -171,7 +206,6 @@ public class PrintStream extends FilterOutputStream */ public PrintStream(String fileName) throws FileNotFoundException { this(false, new FileOutputStream(fileName)); - init(new OutputStreamWriter(this)); } /** @@ -210,8 +244,8 @@ public class PrintStream extends FilterOutputStream public PrintStream(String fileName, String csn) throws FileNotFoundException, UnsupportedEncodingException { - this(false, new FileOutputStream(fileName)); - init(new OutputStreamWriter(this, csn)); + // ensure charset is checked before the file is opened + this(false, toCharset(csn), new FileOutputStream(fileName)); } /** @@ -243,7 +277,6 @@ public class PrintStream extends FilterOutputStream */ public PrintStream(File file) throws FileNotFoundException { this(false, new FileOutputStream(file)); - init(new OutputStreamWriter(this)); } /** @@ -282,8 +315,8 @@ public class PrintStream extends FilterOutputStream public PrintStream(File file, String csn) throws FileNotFoundException, UnsupportedEncodingException { - this(false, new FileOutputStream(file)); - init(new OutputStreamWriter(this, csn)); + // ensure charset is checked before the file is opened + this(false, toCharset(csn), new FileOutputStream(file)); } /** Check to make sure that the stream has not been closed */ diff --git a/src/share/classes/java/io/PrintWriter.java b/src/share/classes/java/io/PrintWriter.java index afce0f89d4d32b3adabb1794a43bd200912bc3b9..16044567065b4433e3e245ce572e9dd169bfc10f 100644 --- a/src/share/classes/java/io/PrintWriter.java +++ b/src/share/classes/java/io/PrintWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,12 @@ package java.io; +import java.util.Objects; import java.util.Formatter; import java.util.Locale; +import java.nio.charset.Charset; +import java.nio.charset.IllegalCharsetNameException; +import java.nio.charset.UnsupportedCharsetException; /** * Prints formatted representations of objects to a text-output stream. This @@ -59,7 +63,7 @@ public class PrintWriter extends Writer { */ protected Writer out; - private boolean autoFlush = false; + private final boolean autoFlush; private boolean trouble = false; private Formatter formatter; private PrintStream psOut = null; @@ -68,7 +72,24 @@ public class PrintWriter extends Writer { * Line separator string. This is the value of the line.separator * property at the moment that the stream was created. */ - private String lineSeparator; + private final String lineSeparator; + + /** + * Returns a charset object for the given charset name. + * @throws NullPointerException is csn is null + * @throws UnsupportedEncodingException if the charset is not supported + */ + private static Charset toCharset(String csn) + throws UnsupportedEncodingException + { + Objects.nonNull(csn, "charsetName"); + try { + return Charset.forName(csn); + } catch (IllegalCharsetNameException|UnsupportedCharsetException unused) { + // UnsupportedEncodingException should be thrown + throw new UnsupportedEncodingException(csn); + } + } /** * Creates a new PrintWriter, without automatic line flushing. @@ -164,6 +185,14 @@ public class PrintWriter extends Writer { false); } + /* Private constructor */ + private PrintWriter(Charset charset, File file) + throws FileNotFoundException + { + this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), charset)), + false); + } + /** * Creates a new PrintWriter, without automatic line flushing, with the * specified file name and charset. This convenience constructor creates @@ -200,8 +229,7 @@ public class PrintWriter extends Writer { public PrintWriter(String fileName, String csn) throws FileNotFoundException, UnsupportedEncodingException { - this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName), csn)), - false); + this(toCharset(csn), new File(fileName)); } /** @@ -272,8 +300,7 @@ public class PrintWriter extends Writer { public PrintWriter(File file, String csn) throws FileNotFoundException, UnsupportedEncodingException { - this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), csn)), - false); + this(toCharset(csn), file); } /** Checks to make sure that the stream has not been closed */ diff --git a/src/share/classes/java/lang/AutoCloseable.java b/src/share/classes/java/lang/AutoCloseable.java index a44f5840cd723e055488d757a55849c59980fbc9..f18de8cd5fbb04d64fb47e30094b0807c413f1c8 100644 --- a/src/share/classes/java/lang/AutoCloseable.java +++ b/src/share/classes/java/lang/AutoCloseable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,7 +33,7 @@ package java.lang; */ public interface AutoCloseable { /** - * Close this resource, relinquishing any underlying resources. + * Closes this resource, relinquishing any underlying resources. * This method is invoked automatically by the {@code * try}-with-resources statement. * @@ -48,6 +48,10 @@ public interface AutoCloseable { * visible side effect, unlike {@code Closeable.close} which is * required to have no effect if called more than once. * + * However, while not required to be idempotent, implementers of + * this interface are strongly encouraged to make their {@code + * close} methods idempotent. + * * @throws Exception if this resource cannot be closed */ void close() throws Exception; diff --git a/src/share/classes/java/lang/StringCoding.java b/src/share/classes/java/lang/StringCoding.java index 42849479fcca6407e3449b31e66dace41006f683..4043d5d2a89722bde29f8da3355f7374fc8f3e83 100644 --- a/src/share/classes/java/lang/StringCoding.java +++ b/src/share/classes/java/lang/StringCoding.java @@ -67,7 +67,7 @@ class StringCoding { } private static void set(ThreadLocal> tl, T ob) { - tl.set(new SoftReference<>(ob)); + tl.set(new SoftReference(ob)); } // Trim the given byte array to the given length diff --git a/src/share/classes/java/lang/Throwable.java b/src/share/classes/java/lang/Throwable.java index 22400baeb9b1fd6b398af2162d1fe9da5ff3c755..c77868e366e37cc82529a59799699fb5e295d8ef 100644 --- a/src/share/classes/java/lang/Throwable.java +++ b/src/share/classes/java/lang/Throwable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -809,7 +809,7 @@ public class Throwable implements Serializable { native StackTraceElement getStackTraceElement(int index); /** - * Read a {@code Throwable} from a stream, enforcing + * Reads a {@code Throwable} from a stream, enforcing * well-formedness constraints on fields. Null entries and * self-pointers are not allowed in the list of {@code * suppressedExceptions}. Null entries are not allowed for stack @@ -865,9 +865,10 @@ public class Throwable implements Serializable { } /** - * Adds the specified exception to the list of exceptions that - * were suppressed, typically by the {@code try}-with-resources - * statement, in order to deliver this exception. + * Appends the specified exception to the exceptions that were + * suppressed in order to deliver this exception. This method is + * typically called (automatically and implicitly) by the {@code + * try}-with-resources statement. * * If the first exception to be suppressed is {@code null}, that * indicates suppressed exception information will not be diff --git a/src/share/classes/java/net/InetAddress.java b/src/share/classes/java/net/InetAddress.java index 889cc6dd770f10f99048a04b2f7794c15af5cde2..926ef861a5ed3bc00f16291537d09fc1db4c90c5 100644 --- a/src/share/classes/java/net/InetAddress.java +++ b/src/share/classes/java/net/InetAddress.java @@ -677,8 +677,7 @@ class InetAddress implements java.io.Serializable { static InetAddressImpl impl; - private static HashMap lookupTable - = new HashMap(); + private static final HashMap lookupTable = new HashMap<>(); /** * Represents a cache entry @@ -737,7 +736,7 @@ class InetAddress implements java.io.Serializable { // As we iterate in insertion order we can // terminate when a non-expired entry is found. - LinkedList expired = new LinkedList(); + LinkedList expired = new LinkedList<>(); long now = System.currentTimeMillis(); for (String key : cache.keySet()) { CacheEntry entry = cache.get(key); @@ -1227,43 +1226,45 @@ class InetAddress implements java.io.Serializable { // lookupTable and return null so the // following code would do a lookup itself. if ((addresses = checkLookupTable(host)) == null) { - // This is the first thread which looks up the addresses - // this host or the cache entry for this host has been - // expired so this thread should do the lookup. - for (NameService nameService : nameServices) { - try { - /* - * Do not put the call to lookup() inside the - * constructor. if you do you will still be - * allocating space when the lookup fails. - */ - - addresses = nameService.lookupAllHostAddr(host); - success = true; - break; - } catch (UnknownHostException uhe) { - if (host.equalsIgnoreCase("localhost")) { - InetAddress[] local = new InetAddress[] { impl.loopbackAddress() }; - addresses = local; + try { + // This is the first thread which looks up the addresses + // this host or the cache entry for this host has been + // expired so this thread should do the lookup. + for (NameService nameService : nameServices) { + try { + /* + * Do not put the call to lookup() inside the + * constructor. if you do you will still be + * allocating space when the lookup fails. + */ + + addresses = nameService.lookupAllHostAddr(host); success = true; break; - } - else { - addresses = unknown_array; - success = false; - ex = uhe; + } catch (UnknownHostException uhe) { + if (host.equalsIgnoreCase("localhost")) { + InetAddress[] local = new InetAddress[] { impl.loopbackAddress() }; + addresses = local; + success = true; + break; + } + else { + addresses = unknown_array; + success = false; + ex = uhe; + } } } - } - // Cache the addresses. - cacheAddresses(host, addresses, success); - // Delete the host from the lookupTable, and - // notify all threads waiting for the monitor - // for lookupTable. - updateLookupTable(host); - if (!success && ex != null) - throw ex; + // Cache the addresses. + cacheAddresses(host, addresses, success); + if (!success && ex != null) + throw ex; + } finally { + // Delete host from the lookupTable and notify + // all threads waiting on the lookupTable monitor. + updateLookupTable(host); + } } return addresses; @@ -1271,16 +1272,13 @@ class InetAddress implements java.io.Serializable { private static InetAddress[] checkLookupTable(String host) { - // make sure addresses is null. - InetAddress[] addresses = null; - synchronized (lookupTable) { // If the host isn't in the lookupTable, add it in the // lookuptable and return null. The caller should do // the lookup. if (lookupTable.containsKey(host) == false) { lookupTable.put(host, null); - return addresses; + return null; } // If the host is in the lookupTable, it means that another @@ -1298,10 +1296,11 @@ class InetAddress implements java.io.Serializable { // the host. This thread should retry to get the addresses // from the addressCache. If it doesn't get the addresses from // the cache, it will try to look up the addresses itself. - addresses = getCachedAddresses(host); + InetAddress[] addresses = getCachedAddresses(host); if (addresses == null) { synchronized (lookupTable) { lookupTable.put(host, null); + return null; } } diff --git a/src/share/classes/java/net/NetworkInterface.java b/src/share/classes/java/net/NetworkInterface.java index 9c8b9ece275b4a7c849f713ae493e0a1d0bb304b..1a0fab28cfa157eb927d9e415ebfa57b2c47e50c 100644 --- a/src/share/classes/java/net/NetworkInterface.java +++ b/src/share/classes/java/net/NetworkInterface.java @@ -493,55 +493,44 @@ public final class NetworkInterface { * @see java.net.InetAddress#getAddress() */ public boolean equals(Object obj) { - if ((obj == null) || !(obj instanceof NetworkInterface)) { + if (!(obj instanceof NetworkInterface)) { return false; } - NetworkInterface netIF = (NetworkInterface)obj; - if (name != null ) { - if (netIF.getName() != null) { - if (!name.equals(netIF.getName())) { - return false; - } - } else { + NetworkInterface that = (NetworkInterface)obj; + if (this.name != null ) { + if (!this.name.equals(that.name)) { return false; } } else { - if (netIF.getName() != null) { + if (that.name != null) { return false; } } - Enumeration newAddrs = netIF.getInetAddresses(); - int i = 0; - for (i = 0; newAddrs.hasMoreElements();newAddrs.nextElement(), i++); - if (addrs == null) { - if (i != 0) { - return false; - } - } else { - /* - * Compare number of addresses (in the checked subset) - */ - int count = 0; - Enumeration e = getInetAddresses(); - for (; e.hasMoreElements(); count++) { - e.nextElement(); - } - if (i != count) { - return false; - } + + if (this.addrs == null) { + return that.addrs == null; + } else if (that.addrs == null) { + return false; + } + + /* Both addrs not null. Compare number of addresses */ + + if (this.addrs.length != that.addrs.length) { + return false; } - newAddrs = netIF.getInetAddresses(); - for (; newAddrs.hasMoreElements();) { - boolean equal = false; - Enumeration thisAddrs = getInetAddresses(); - InetAddress newAddr = (InetAddress)newAddrs.nextElement(); - for (; thisAddrs.hasMoreElements();) { - InetAddress thisAddr = (InetAddress)thisAddrs.nextElement(); - if (thisAddr.equals(newAddr)) { - equal = true; + + InetAddress[] thatAddrs = that.addrs; + int count = thatAddrs.length; + + for (int i=0; i addrs = getInetAddresses(); - while (addrs.hasMoreElements()) { - count += addrs.nextElement().hashCode(); - } - return count; + return name == null? 0: name.hashCode(); } public String toString() { diff --git a/src/share/classes/java/net/SocksSocketImpl.java b/src/share/classes/java/net/SocksSocketImpl.java index 99161753cda064fcb22cd10b214e5d69fbabda71..4fb61efe633cb6f82b99f9bf742ee7d2a2ac4eec 100644 --- a/src/share/classes/java/net/SocksSocketImpl.java +++ b/src/share/classes/java/net/SocksSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ import java.io.OutputStream; import java.io.BufferedOutputStream; import java.security.AccessController; import java.security.PrivilegedExceptionAction; +import sun.net.SocksProxy; import sun.net.www.ParseUtil; /* import org.ietf.jgss.*; */ @@ -397,6 +398,11 @@ class SocksSocketImpl extends PlainSocketImpl implements SocksConsts { // Use getHostString() to avoid reverse lookups server = ((InetSocketAddress) p.address()).getHostString(); serverPort = ((InetSocketAddress) p.address()).getPort(); + if (p instanceof SocksProxy) { + if (((SocksProxy)p).protocolVersion() == 4) { + useV4 = true; + } + } // Connects to the SOCKS server try { @@ -700,6 +706,11 @@ class SocksSocketImpl extends PlainSocketImpl implements SocksConsts { // Use getHostString() to avoid reverse lookups server = ((InetSocketAddress) p.address()).getHostString(); serverPort = ((InetSocketAddress) p.address()).getPort(); + if (p instanceof SocksProxy) { + if (((SocksProxy)p).protocolVersion() == 4) { + useV4 = true; + } + } // Connects to the SOCKS server try { diff --git a/src/share/classes/java/net/URLClassLoader.java b/src/share/classes/java/net/URLClassLoader.java index 00b8abc76ddc7b00bf5595498f6650396b9d94b9..70dc45585fb58a3c075ee9859d439306be7ef272 100644 --- a/src/share/classes/java/net/URLClassLoader.java +++ b/src/share/classes/java/net/URLClassLoader.java @@ -27,19 +27,15 @@ package java.net; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.io.File; -import java.io.FilePermission; -import java.io.InputStream; -import java.io.IOException; -import java.io.Closeable; +import java.lang.ref.*; +import java.io.*; import java.net.URL; import java.net.URLConnection; import java.net.URLStreamHandlerFactory; import java.util.Enumeration; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.StringTokenizer; +import java.util.*; import java.util.jar.Manifest; +import java.util.jar.JarFile; import java.util.jar.Attributes; import java.util.jar.Attributes.Name; import java.security.CodeSigner; @@ -194,6 +190,65 @@ public class URLClassLoader extends SecureClassLoader implements Closeable { acc = AccessController.getContext(); } + /* A map (used as a set) to keep track of closeable local resources + * (either JarFiles or FileInputStreams). We don't care about + * Http resources since they don't need to be closed. + * + * If the resource is coming from a jar file + * we keep a (weak) reference to the JarFile object which can + * be closed if URLClassLoader.close() called. Due to jar file + * caching there will typically be only one JarFile object + * per underlying jar file. + * + * For file resources, which is probably a less common situation + * we have to keep a weak reference to each stream. + */ + + private WeakHashMap + closeables = new WeakHashMap<>(); + + /** + * Returns an input stream for reading the specified resource. + * If this loader is closed, then any resources opened by this method + * will be closed. + * + *

The search order is described in the documentation for {@link + * #getResource(String)}.

+ * + * @param name + * The resource name + * + * @return An input stream for reading the resource, or null + * if the resource could not be found + * + * @since 1.7 + */ + public InputStream getResourceAsStream(String name) { + URL url = getResource(name); + try { + if (url == null) { + return null; + } + URLConnection urlc = url.openConnection(); + InputStream is = urlc.getInputStream(); + if (urlc instanceof JarURLConnection) { + JarURLConnection juc = (JarURLConnection)urlc; + JarFile jar = juc.getJarFile(); + synchronized (closeables) { + if (!closeables.containsKey(jar)) { + closeables.put(jar, null); + } + } + } else if (urlc instanceof sun.net.www.protocol.file.FileURLConnection) { + synchronized (closeables) { + closeables.put(is, null); + } + } + return is; + } catch (IOException e) { + return null; + } + } /** * Closes this URLClassLoader, so that it can no longer be used to load @@ -202,8 +257,8 @@ public class URLClassLoader extends SecureClassLoader implements Closeable { * delegation hierarchy are still accessible. Also, any classes or resources * that are already loaded, are still accessible. *

- * In the case of jar: and file: URLs, it also closes any class files, - * or JAR files that were opened by it. If another thread is loading a + * In the case of jar: and file: URLs, it also closes any files + * that were opened by it. If another thread is loading a * class when the {@code close} method is invoked, then the result of * that load is undefined. *

@@ -213,10 +268,10 @@ public class URLClassLoader extends SecureClassLoader implements Closeable { * loader has no effect. *

* @throws IOException if closing any file opened by this class loader - * resulted in an IOException. Any such exceptions are caught, and a - * single IOException is thrown after the last file has been closed. - * If only one exception was thrown, it will be set as the cause - * of this IOException. + * resulted in an IOException. Any such exceptions are caught internally. + * If only one is caught, then it is re-thrown. If more than one exception + * is caught, then the second and following exceptions are added + * as suppressed exceptions of the first one caught, which is then re-thrown. * * @throws SecurityException if a security manager is set, and it denies * {@link RuntimePermission}("closeClassLoader") @@ -229,21 +284,33 @@ public class URLClassLoader extends SecureClassLoader implements Closeable { security.checkPermission(new RuntimePermission("closeClassLoader")); } List errors = ucp.closeLoaders(); + + // now close any remaining streams. + + synchronized (closeables) { + Set keys = closeables.keySet(); + for (Closeable c : keys) { + try { + c.close(); + } catch (IOException ioex) { + errors.add(ioex); + } + } + closeables.clear(); + } + if (errors.isEmpty()) { return; } - if (errors.size() == 1) { - throw new IOException ( - "Error closing URLClassLoader resource", - errors.get(0) - ); - } - // Several exceptions. So, just combine the error messages - String errormsg = "Error closing resources: "; + + IOException firstex = errors.remove(0); + + // Suppress any remaining exceptions + for (IOException error: errors) { - errormsg = errormsg + "[" + error.toString() + "] "; + firstex.addSuppressed(error); } - throw new IOException (errormsg); + throw firstex; } /** diff --git a/src/share/classes/java/net/doc-files/net-properties.html b/src/share/classes/java/net/doc-files/net-properties.html index fffdfebc4312328a11232c58eca72a31ebba3028..ae39fec8e8b1e707f32b369af47008ed8b87f2a1 100644 --- a/src/share/classes/java/net/doc-files/net-properties.html +++ b/src/share/classes/java/net/doc-files/net-properties.html @@ -127,10 +127,15 @@ of proxies.

are specified. If SOCKS is supported by a Java SE implementation, the following properties will be used:

    -
  • socksProxyHost (default: <non>)
    +

  • socksProxyHost (default: <none>)
    The hostname, or address, of the proxy server.

  • socksProxyPort (default: 1080)
    The port number of the proxy server.

    +
  • socksProxyVersion (default: 5)
    + The version of the SOCKS protocol supported by the server. The + default is 5 indicating SOCKS V5, alternatively + 4 can be specified for SOCKS V4. Setting the property + to values other than these leads to unspecified behavior.

  • java.net.socks.username (default: <none>)
    Username to use if the SOCKSv5 server asks for authentication and no java.net.Authenticator instance was found.

    diff --git a/src/share/classes/java/security/AccessControlContext.java b/src/share/classes/java/security/AccessControlContext.java index d4f167b6480d8d2fcae4d5de6b22d3fe7f128f37..e80953b66963e300945ad3853b0a332ca470b059 100644 --- a/src/share/classes/java/security/AccessControlContext.java +++ b/src/share/classes/java/security/AccessControlContext.java @@ -121,7 +121,7 @@ public final class AccessControlContext { this.context = null; } } else { - List v = new ArrayList(context.length); + List v = new ArrayList<>(context.length); for (int i =0; i< context.length; i++) { if ((context[i] != null) && (!v.contains(context[i]))) v.add(context[i]); diff --git a/src/share/classes/java/security/BasicPermission.java b/src/share/classes/java/security/BasicPermission.java index 7f3b9479d1f3e47869ff811dc627353b98d2dc0d..f22e4c755d2a50af184c400ac7ace4343bfd0d9e 100644 --- a/src/share/classes/java/security/BasicPermission.java +++ b/src/share/classes/java/security/BasicPermission.java @@ -515,7 +515,7 @@ implements java.io.Serializable // Copy perms into a Hashtable Hashtable permissions = - new Hashtable(perms.size()*2); + new Hashtable<>(perms.size()*2); synchronized (this) { permissions.putAll(perms); diff --git a/src/share/classes/java/security/CodeSource.java b/src/share/classes/java/security/CodeSource.java index d762b2dda4087c969edabca4ae4f2fc44c6abef4..5ec8cebc028e31e464a250a999ca2ace21ba7df9 100644 --- a/src/share/classes/java/security/CodeSource.java +++ b/src/share/classes/java/security/CodeSource.java @@ -188,7 +188,7 @@ public class CodeSource implements java.io.Serializable { } else if (signers != null) { // Convert the code signers to certs ArrayList certChains = - new ArrayList(); + new ArrayList<>(); for (int i = 0; i < signers.length; i++) { certChains.addAll( signers[i].getSignerCertPath().getCertificates()); @@ -606,10 +606,10 @@ public class CodeSource implements java.io.Serializable { // Iterate through all the certificates int i = 0; - List signers = new ArrayList(); + List signers = new ArrayList<>(); while (i < certs.length) { List certChain = - new ArrayList(); + new ArrayList<>(); certChain.add(certs[i++]); // first cert is an end-entity cert int j = i; diff --git a/src/share/classes/java/security/Permissions.java b/src/share/classes/java/security/Permissions.java index 3f41ac408cf48a9df35f752d416b6037a2fb980f..e480db0fda8ceba0b3c796d80e399877126ba2ea 100644 --- a/src/share/classes/java/security/Permissions.java +++ b/src/share/classes/java/security/Permissions.java @@ -362,7 +362,7 @@ implements Serializable // Copy perms into a Hashtable Hashtable, PermissionCollection> perms = - new Hashtable, PermissionCollection>(permsMap.size()*2); // no sync; estimate + new Hashtable<>(permsMap.size()*2); // no sync; estimate synchronized (this) { perms.putAll(permsMap); } @@ -567,7 +567,7 @@ implements Serializable // Copy perms into a Hashtable Hashtable perms = - new Hashtable(permsMap.size()*2); + new Hashtable<>(permsMap.size()*2); synchronized (this) { perms.putAll(permsMap); } diff --git a/src/share/classes/java/security/ProtectionDomain.java b/src/share/classes/java/security/ProtectionDomain.java index 6079436a585788606776936b73008a792863093f..43a39028e3df5cc0f2df2a2153095c783ada5113 100644 --- a/src/share/classes/java/security/ProtectionDomain.java +++ b/src/share/classes/java/security/ProtectionDomain.java @@ -336,8 +336,8 @@ public class ProtectionDomain { int swag = 32; int vcap = 8; Enumeration e; - List pdVector = new ArrayList(vcap); - List plVector = new ArrayList(swag); + List pdVector = new ArrayList<>(vcap); + List plVector = new ArrayList<>(swag); // // Build a vector of domain permissions for subsequent merge diff --git a/src/share/classes/java/security/Provider.java b/src/share/classes/java/security/Provider.java index 11dc07ae4f0f9ebfb01f3cbcef9d514192174934..e13303526d3606d2c3f7992dbd435bcc9f0eb4d2 100644 --- a/src/share/classes/java/security/Provider.java +++ b/src/share/classes/java/security/Provider.java @@ -437,7 +437,7 @@ public abstract class Provider extends Properties { private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { - Map copy = new HashMap(); + Map copy = new HashMap<>(); for (Map.Entry entry : super.entrySet()) { copy.put(entry.getKey(), entry.getValue()); } @@ -719,7 +719,7 @@ public abstract class Provider extends Properties { } if (serviceSet == null) { ensureLegacyParsed(); - Set set = new LinkedHashSet(); + Set set = new LinkedHashSet<>(); if (serviceMap != null) { set.addAll(serviceMap.values()); } @@ -1395,7 +1395,7 @@ public abstract class Provider extends Properties { if (s != null) { String[] classNames = s.split("\\|"); List classList = - new ArrayList(classNames.length); + new ArrayList<>(classNames.length); for (String className : classNames) { Class clazz = getKeyClass(className); if (clazz != null) { diff --git a/src/share/classes/java/security/SecureClassLoader.java b/src/share/classes/java/security/SecureClassLoader.java index 3d53dffe1e7f67f6fd7f75807df52e9452c64c02..4f774ca8f7dbdf5a40403b8498d9c388c10da095 100644 --- a/src/share/classes/java/security/SecureClassLoader.java +++ b/src/share/classes/java/security/SecureClassLoader.java @@ -50,7 +50,7 @@ public class SecureClassLoader extends ClassLoader { // HashMap that maps CodeSource to ProtectionDomain // @GuardedBy("pdcache") private final HashMap pdcache = - new HashMap(11); + new HashMap<>(11); private static final Debug debug = Debug.getInstance("scl"); diff --git a/src/share/classes/java/security/Security.java b/src/share/classes/java/security/Security.java index 28bc22e58ab071fe5f1468720bd6f78c85eb7c71..55816d9aefdfa9fb04ec24b65cb160442ef4f5ca 100644 --- a/src/share/classes/java/security/Security.java +++ b/src/share/classes/java/security/Security.java @@ -545,8 +545,7 @@ public final class Security { value = filter.substring(index + 1); } - Hashtable hashtableFilter = - new Hashtable(1); + Hashtable hashtableFilter = new Hashtable<>(1); hashtableFilter.put(key, value); return (getProviders(hashtableFilter)); @@ -606,7 +605,7 @@ public final class Security { // Then only return those providers who satisfy the selection criteria. Provider[] allProviders = Security.getProviders(); Set keySet = filter.keySet(); - LinkedHashSet candidates = new LinkedHashSet(5); + LinkedHashSet candidates = new LinkedHashSet<>(5); // Returns all installed providers // if the selection criteria is null. @@ -660,8 +659,7 @@ public final class Security { } // Map containing cached Spi Class objects of the specified type - private static final Map spiMap = - new ConcurrentHashMap(); + private static final Map spiMap = new ConcurrentHashMap<>(); /** * Return the Class object for the given engine type @@ -885,7 +883,7 @@ public final class Security { String attrName, String filterValue, Provider[] allProviders) { - LinkedHashSet candidates = new LinkedHashSet(5); + LinkedHashSet candidates = new LinkedHashSet<>(5); for (int i = 0; i < allProviders.length; i++) { if (isCriterionSatisfied(allProviders[i], serviceName, algName, @@ -1082,7 +1080,7 @@ public final class Security { return Collections.EMPTY_SET; } - HashSet result = new HashSet(); + HashSet result = new HashSet<>(); Provider[] providers = Security.getProviders(); for (int i = 0; i < providers.length; i++) { diff --git a/src/share/classes/java/security/UnresolvedPermission.java b/src/share/classes/java/security/UnresolvedPermission.java index eeeccebca88a929c89953b935c739e1f5162c60e..9e4e1aed053a827e15ce53d46dfcbcd04b055de0 100644 --- a/src/share/classes/java/security/UnresolvedPermission.java +++ b/src/share/classes/java/security/UnresolvedPermission.java @@ -198,7 +198,7 @@ implements java.io.Serializable if (this.certs == null) { // extract the signer certs ArrayList signerCerts = - new ArrayList(); + new ArrayList<>(); i = 0; while (i < certs.length) { signerCerts.add(certs[i]); diff --git a/src/share/classes/java/security/UnresolvedPermissionCollection.java b/src/share/classes/java/security/UnresolvedPermissionCollection.java index c186596ee314e065c97a81c2e601f3b760ece012..01cf9f7edef418168a82afd5f26d1e087169d926 100644 --- a/src/share/classes/java/security/UnresolvedPermissionCollection.java +++ b/src/share/classes/java/security/UnresolvedPermissionCollection.java @@ -119,7 +119,7 @@ implements java.io.Serializable public Enumeration elements() { List results = - new ArrayList(); // where results are stored + new ArrayList<>(); // where results are stored // Get iterator of Map values (which are lists of permissions) synchronized (this) { @@ -161,7 +161,7 @@ implements java.io.Serializable // Copy perms into a Hashtable Hashtable> permissions = - new Hashtable>(perms.size()*2); + new Hashtable<>(perms.size()*2); // Convert each entry (List) into a Vector synchronized (this) { @@ -169,8 +169,7 @@ implements java.io.Serializable for (Map.Entry> e : set) { // Convert list into Vector List list = e.getValue(); - Vector vec = - new Vector(list.size()); + Vector vec = new Vector<>(list.size()); synchronized (list) { vec.addAll(list); } @@ -207,8 +206,7 @@ implements java.io.Serializable for (Map.Entry> e : set) { // Convert Vector into ArrayList Vector vec = e.getValue(); - List list = - new ArrayList(vec.size()); + List list = new ArrayList<>(vec.size()); list.addAll(vec); // Add to Hashtable being serialized diff --git a/src/share/classes/java/sql/Timestamp.java b/src/share/classes/java/sql/Timestamp.java index 411c04eb19e2749136c937323644fddcffc092af..f92a89a87789103f1f0bad6254582b5e25071b29 100644 --- a/src/share/classes/java/sql/Timestamp.java +++ b/src/share/classes/java/sql/Timestamp.java @@ -473,7 +473,9 @@ public class Timestamp extends java.util.Date { * @since 1.4 */ public int compareTo(Timestamp ts) { - int i = super.compareTo(ts); + long thisTime = this.getTime(); + long anotherTime = ts.getTime(); + int i = (thisTime ts.nanos) { return 1; diff --git a/src/share/classes/java/util/Collections.java b/src/share/classes/java/util/Collections.java index 08f8adbe5b283ff450c28f13aea03ea0d0d0f5e7..bfd5a8711d6a24168d182c3c8472dd2716fbbdf5 100644 --- a/src/share/classes/java/util/Collections.java +++ b/src/share/classes/java/util/Collections.java @@ -1452,10 +1452,10 @@ public class Collections { * when o is a Map.Entry, and calls o.setValue. */ public boolean containsAll(Collection coll) { - Iterator it = coll.iterator(); - while (it.hasNext()) - if (!contains(it.next())) // Invokes safe contains() above + for (Object e : coll) { + if (!contains(e)) // Invokes safe contains() above return false; + } return true; } public boolean equals(Object o) { @@ -3713,45 +3713,91 @@ public class Collections { } /** - * Returns true if the two specified collections have no + * Returns {@code true} if the two specified collections have no * elements in common. * *

    Care must be exercised if this method is used on collections that - * do not comply with the general contract for Collection. + * do not comply with the general contract for {@code Collection}. * Implementations may elect to iterate over either collection and test * for containment in the other collection (or to perform any equivalent * computation). If either collection uses a nonstandard equality test - * (as does a {@link SortedSet} whose ordering is not compatible with - * equals, or the key set of an {@link IdentityHashMap}), both + * (as does a {@link SortedSet} whose ordering is not compatible with + * equals, or the key set of an {@link IdentityHashMap}), both * collections must use the same nonstandard equality test, or the * result of this method is undefined. * + *

    Care must also be exercised when using collections that have + * restrictions on the elements that they may contain. Collection + * implementations are allowed to throw exceptions for any operation + * involving elements they deem ineligible. For absolute safety the + * specified collections should contain only elements which are + * eligible elements for both collections. + * *

    Note that it is permissible to pass the same collection in both - * parameters, in which case the method will return true if and only if - * the collection is empty. + * parameters, in which case the method will return {@code true} if and + * only if the collection is empty. * * @param c1 a collection * @param c2 a collection - * @throws NullPointerException if either collection is null + * @return {@code true} if the two specified collections have no + * elements in common. + * @throws NullPointerException if either collection is {@code null}. + * @throws NullPointerException if one collection contains a {@code null} + * element and {@code null} is not an eligible element for the other collection. + * (optional) + * @throws ClassCastException if one collection contains an element that is + * of a type which is ineligible for the other collection. (optional) * @since 1.5 */ public static boolean disjoint(Collection c1, Collection c2) { - /* - * We're going to iterate through c1 and test for inclusion in c2. - * If c1 is a Set and c2 isn't, swap the collections. Otherwise, - * place the shorter collection in c1. Hopefully this heuristic - * will minimize the cost of the operation. - */ - if ((c1 instanceof Set) && !(c2 instanceof Set) || - (c1.size() > c2.size())) { - Collection tmp = c1; - c1 = c2; - c2 = tmp; + // The collection to be used for contains(). Preference is given to + // the collection who's contains() has lower O() complexity. + Collection contains = c2; + // The collection to be iterated. If the collections' contains() impl + // are of different O() complexity, the collection with slower + // contains() will be used for iteration. For collections who's + // contains() are of the same complexity then best performance is + // achieved by iterating the smaller collection. + Collection iterate = c1; + + // Performance optimization cases. The heuristics: + // 1. Generally iterate over c1. + // 2. If c1 is a Set then iterate over c2. + // 3. If either collection is empty then result is always true. + // 4. Iterate over the smaller Collection. + if (c1 instanceof Set) { + // Use c1 for contains as a Set's contains() is expected to perform + // better than O(N/2) + iterate = c2; + contains = c1; + } else if (!(c2 instanceof Set)) { + // Both are mere Collections. Iterate over smaller collection. + // Example: If c1 contains 3 elements and c2 contains 50 elements and + // assuming contains() requires ceiling(N/2) comparisons then + // checking for all c1 elements in c2 would require 75 comparisons + // (3 * ceiling(50/2)) vs. checking all c2 elements in c1 requiring + // 100 comparisons (50 * ceiling(3/2)). + int c1size = c1.size(); + int c2size = c2.size(); + if (c1size == 0 || c2size == 0) { + // At least one collection is empty. Nothing will match. + return true; + } + + if (c1size > c2size) { + iterate = c2; + contains = c1; + } } - for (Object e : c1) - if (c2.contains(e)) + for (Object e : iterate) { + if (contains.contains(e)) { + // Found a common element. Collections are not disjoint. return false; + } + } + + // No common elements were found. return true; } diff --git a/src/share/classes/java/util/Formatter.java b/src/share/classes/java/util/Formatter.java index 316135ed0fa44911c9f938a10d60991adc46dc29..6c9ead3b7f03ef29cfbf3a0bcb32a1bd5e8bd4da 100644 --- a/src/share/classes/java/util/Formatter.java +++ b/src/share/classes/java/util/Formatter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,6 +41,8 @@ import java.math.BigInteger; import java.math.MathContext; import java.math.RoundingMode; import java.nio.charset.Charset; +import java.nio.charset.IllegalCharsetNameException; +import java.nio.charset.UnsupportedCharsetException; import java.text.DateFormatSymbols; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; @@ -1838,22 +1840,53 @@ import sun.misc.FormattedFloatingDecimal; */ public final class Formatter implements Closeable, Flushable { private Appendable a; - private Locale l; + private final Locale l; private IOException lastException; - private char zero = '0'; + private final char zero; private static double scaleUp; // 1 (sign) + 19 (max # sig digits) + 1 ('.') + 1 ('e') + 1 (sign) // + 3 (max # exp digits) + 4 (error) = 30 private static final int MAX_FD_CHARS = 30; - // Initialize internal data. - private void init(Appendable a, Locale l) { + /** + * Returns a charset object for the given charset name. + * @throws NullPointerException is csn is null + * @throws UnsupportedEncodingException if the charset is not supported + */ + private static Charset toCharset(String csn) + throws UnsupportedEncodingException + { + Objects.nonNull(csn, "charsetName"); + try { + return Charset.forName(csn); + } catch (IllegalCharsetNameException|UnsupportedCharsetException unused) { + // UnsupportedEncodingException should be thrown + throw new UnsupportedEncodingException(csn); + } + } + + private static final Appendable nonNullAppendable(Appendable a) { + if (a == null) + return new StringBuilder(); + + return a; + } + + /* Private constructors */ + private Formatter(Locale l, Appendable a) { this.a = a; this.l = l; - setZero(); + this.zero = getZero(l); + } + + private Formatter(Charset charset, Locale l, File file) + throws FileNotFoundException + { + this(l, + new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), charset))); } /** @@ -1867,7 +1900,7 @@ public final class Formatter implements Closeable, Flushable { * virtual machine. */ public Formatter() { - init(new StringBuilder(), Locale.getDefault(Locale.Category.FORMAT)); + this(Locale.getDefault(Locale.Category.FORMAT), new StringBuilder()); } /** @@ -1881,9 +1914,7 @@ public final class Formatter implements Closeable, Flushable { * {@code null} then a {@link StringBuilder} will be created. */ public Formatter(Appendable a) { - if (a == null) - a = new StringBuilder(); - init(a, Locale.getDefault(Locale.Category.FORMAT)); + this(Locale.getDefault(Locale.Category.FORMAT), nonNullAppendable(a)); } /** @@ -1900,7 +1931,7 @@ public final class Formatter implements Closeable, Flushable { * is applied. */ public Formatter(Locale l) { - init(new StringBuilder(), l); + this(l, new StringBuilder()); } /** @@ -1916,9 +1947,7 @@ public final class Formatter implements Closeable, Flushable { * is applied. */ public Formatter(Appendable a, Locale l) { - if (a == null) - a = new StringBuilder(); - init(a, l); + this(l, nonNullAppendable(a)); } /** @@ -1949,8 +1978,8 @@ public final class Formatter implements Closeable, Flushable { * creating the file */ public Formatter(String fileName) throws FileNotFoundException { - init(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName))), - Locale.getDefault(Locale.Category.FORMAT)); + this(Locale.getDefault(Locale.Category.FORMAT), + new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName)))); } /** @@ -2025,8 +2054,7 @@ public final class Formatter implements Closeable, Flushable { public Formatter(String fileName, String csn, Locale l) throws FileNotFoundException, UnsupportedEncodingException { - init(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName), csn)), - l); + this(toCharset(csn), l, new File(fileName)); } /** @@ -2057,8 +2085,8 @@ public final class Formatter implements Closeable, Flushable { * creating the file */ public Formatter(File file) throws FileNotFoundException { - init(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file))), - Locale.getDefault(Locale.Category.FORMAT)); + this(Locale.getDefault(Locale.Category.FORMAT), + new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)))); } /** @@ -2133,8 +2161,7 @@ public final class Formatter implements Closeable, Flushable { public Formatter(File file, String csn, Locale l) throws FileNotFoundException, UnsupportedEncodingException { - init(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), csn)), - l); + this(toCharset(csn), l, file); } /** @@ -2151,9 +2178,8 @@ public final class Formatter implements Closeable, Flushable { * The stream to use as the destination of this formatter. */ public Formatter(PrintStream ps) { - if (ps == null) - throw new NullPointerException(); - init((Appendable)ps, Locale.getDefault(Locale.Category.FORMAT)); + this(Locale.getDefault(Locale.Category.FORMAT), + (Appendable)Objects.nonNull(ps)); } /** @@ -2171,8 +2197,8 @@ public final class Formatter implements Closeable, Flushable { * The output will be buffered. */ public Formatter(OutputStream os) { - init(new BufferedWriter(new OutputStreamWriter(os)), - Locale.getDefault(Locale.Category.FORMAT)); + this(Locale.getDefault(Locale.Category.FORMAT), + new BufferedWriter(new OutputStreamWriter(os))); } /** @@ -2222,13 +2248,15 @@ public final class Formatter implements Closeable, Flushable { public Formatter(OutputStream os, String csn, Locale l) throws UnsupportedEncodingException { - init(new BufferedWriter(new OutputStreamWriter(os, csn)), l); + this(l, new BufferedWriter(new OutputStreamWriter(os, csn))); } - private void setZero() { + private static char getZero(Locale l) { if ((l != null) && !l.equals(Locale.US)) { DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(l); - zero = dfs.getZeroDigit(); + return dfs.getZeroDigit(); + } else { + return '0'; } } diff --git a/src/share/classes/java/util/LinkedList.java b/src/share/classes/java/util/LinkedList.java index fbf8f5f92ce91284d2c5deb513d425a6515d287f..e4d0ddc0787010d5899fecce05ce819fdfd1821b 100644 --- a/src/share/classes/java/util/LinkedList.java +++ b/src/share/classes/java/util/LinkedList.java @@ -26,9 +26,9 @@ package java.util; /** - * Linked list implementation of the {@link List} and {@link Deque} interfaces. - * Implements all optional operations, and permits all elements (including - * {@code null}). + * Doubly-linked list implementation of the {@code List} and {@code Deque} + * interfaces. Implements all optional list operations, and permits all + * elements (including {@code null}). * *

    All of the operations perform as could be expected for a doubly-linked * list. Operations that index into the list will traverse the list from @@ -249,7 +249,7 @@ public class LinkedList * @return the last element in this list * @throws NoSuchElementException if this list is empty */ - public E getLast() { + public E getLast() { final Node l = last; if (l == null) throw new NoSuchElementException(); diff --git a/src/share/classes/java/util/Scanner.java b/src/share/classes/java/util/Scanner.java index 9fe2192b61b64ed4ed4b6a269067c868eb5dd733..834af330ff19a90b1c4f8497380b7efce6e8c637 100644 --- a/src/share/classes/java/util/Scanner.java +++ b/src/share/classes/java/util/Scanner.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -571,10 +571,8 @@ public final class Scanner implements Iterator, Closeable { * @return A scanner with the specified source and pattern */ private Scanner(Readable source, Pattern pattern) { - if (source == null) - throw new NullPointerException("source"); - if (pattern == null) - throw new NullPointerException("pattern"); + assert source != null : "source should not be null"; + assert pattern != null : "pattern should not be null"; this.source = source; delimPattern = pattern; buf = CharBuffer.allocate(BUFFER_SIZE); @@ -593,7 +591,7 @@ public final class Scanner implements Iterator, Closeable { * interface */ public Scanner(Readable source) { - this(source, WHITESPACE_PATTERN); + this(Objects.nonNull(source, "source"), WHITESPACE_PATTERN); } /** @@ -620,23 +618,27 @@ public final class Scanner implements Iterator, Closeable { * does not exist */ public Scanner(InputStream source, String charsetName) { - this(makeReadable(source, charsetName), WHITESPACE_PATTERN); + this(makeReadable(Objects.nonNull(source, "source"), toCharset(charsetName)), + WHITESPACE_PATTERN); } - private static Readable makeReadable(InputStream source, - String charsetName) - { - if (source == null) - throw new NullPointerException("source"); - InputStreamReader isr = null; + /** + * Returns a charset object for the given charset name. + * @throws NullPointerException is csn is null + * @throws IllegalArgumentException if the charset is not supported + */ + private static Charset toCharset(String csn) { + Objects.nonNull(csn, "charsetName"); try { - isr = new InputStreamReader(source, charsetName); - } catch (UnsupportedEncodingException uee) { - IllegalArgumentException iae = new IllegalArgumentException(); - iae.initCause(uee); - throw iae; + return Charset.forName(csn); + } catch (IllegalCharsetNameException|UnsupportedCharsetException e) { + // IllegalArgumentException should be thrown + throw new IllegalArgumentException(e); } - return isr; + } + + private static Readable makeReadable(InputStream source, Charset charset) { + return new InputStreamReader(source, charset); } /** @@ -648,9 +650,7 @@ public final class Scanner implements Iterator, Closeable { * @param source A file to be scanned * @throws FileNotFoundException if source is not found */ - public Scanner(File source) - throws FileNotFoundException - { + public Scanner(File source) throws FileNotFoundException { this((ReadableByteChannel)(new FileInputStream(source).getChannel())); } @@ -669,8 +669,27 @@ public final class Scanner implements Iterator, Closeable { public Scanner(File source, String charsetName) throws FileNotFoundException { - this((ReadableByteChannel)(new FileInputStream(source).getChannel()), - charsetName); + this(Objects.nonNull(source), toDecoder(charsetName)); + } + + private Scanner(File source, CharsetDecoder dec) + throws FileNotFoundException + { + this(makeReadable((ReadableByteChannel)(new FileInputStream(source).getChannel()), dec)); + } + + private static CharsetDecoder toDecoder(String charsetName) { + Objects.nonNull(charsetName, "charsetName"); + try { + return Charset.forName(charsetName).newDecoder(); + } catch (IllegalCharsetNameException|UnsupportedCharsetException unused) { + throw new IllegalArgumentException(charsetName); + } + } + + private static Readable makeReadable(ReadableByteChannel source, + CharsetDecoder dec) { + return Channels.newReader(source, dec, -1); } /** @@ -708,10 +727,12 @@ public final class Scanner implements Iterator, Closeable { * if the specified encoding is not found * @since 1.7 */ - public Scanner(FileRef source, String charsetName) - throws IOException - { - this(source.newInputStream(), charsetName); + public Scanner(FileRef source, String charsetName) throws IOException { + this(Objects.nonNull(source), toCharset(charsetName)); + } + + private Scanner(FileRef source, Charset charset) throws IOException { + this(makeReadable(source.newInputStream(), charset)); } /** @@ -733,16 +754,12 @@ public final class Scanner implements Iterator, Closeable { * @param source A channel to scan */ public Scanner(ReadableByteChannel source) { - this(makeReadable(source), WHITESPACE_PATTERN); + this(makeReadable(Objects.nonNull(source, "source")), + WHITESPACE_PATTERN); } private static Readable makeReadable(ReadableByteChannel source) { - if (source == null) - throw new NullPointerException("source"); - String defaultCharsetName = - java.nio.charset.Charset.defaultCharset().name(); - return Channels.newReader(source, - java.nio.charset.Charset.defaultCharset().name()); + return makeReadable(source, Charset.defaultCharset().newDecoder()); } /** @@ -757,17 +774,8 @@ public final class Scanner implements Iterator, Closeable { * does not exist */ public Scanner(ReadableByteChannel source, String charsetName) { - this(makeReadable(source, charsetName), WHITESPACE_PATTERN); - } - - private static Readable makeReadable(ReadableByteChannel source, - String charsetName) - { - if (source == null) - throw new NullPointerException("source"); - if (!Charset.isSupported(charsetName)) - throw new IllegalArgumentException(charsetName); - return Channels.newReader(source, charsetName); + this(makeReadable(Objects.nonNull(source, "source"), toDecoder(charsetName)), + WHITESPACE_PATTERN); } // Private primitives used to support scanning diff --git a/src/share/classes/java/util/concurrent/ArrayBlockingQueue.java b/src/share/classes/java/util/concurrent/ArrayBlockingQueue.java index 0690c8216e9a030afba8f339ae1d0c14fa495a3c..4f4b9d96af60a4b463f1b09fc0194af8b8dd4aac 100644 --- a/src/share/classes/java/util/concurrent/ArrayBlockingQueue.java +++ b/src/share/classes/java/util/concurrent/ArrayBlockingQueue.java @@ -49,14 +49,14 @@ import java.util.*; *

    This is a classic "bounded buffer", in which a * fixed-sized array holds elements inserted by producers and * extracted by consumers. Once created, the capacity cannot be - * increased. Attempts to put an element into a full queue - * will result in the operation blocking; attempts to take an + * changed. Attempts to {@code put} an element into a full queue + * will result in the operation blocking; attempts to {@code take} an * element from an empty queue will similarly block. * - *

    This class supports an optional fairness policy for ordering + *

    This class supports an optional fairness policy for ordering * waiting producer and consumer threads. By default, this ordering * is not guaranteed. However, a queue constructed with fairness set - * to true grants threads access in FIFO order. Fairness + * to {@code true} grants threads access in FIFO order. Fairness * generally decreases throughput but reduces variability and avoids * starvation. * @@ -83,14 +83,17 @@ public class ArrayBlockingQueue extends AbstractQueue */ private static final long serialVersionUID = -817911632652898426L; - /** The queued items */ - private final E[] items; - /** items index for next take, poll or remove */ - private int takeIndex; - /** items index for next put, offer, or add. */ - private int putIndex; - /** Number of items in the queue */ - private int count; + /** The queued items */ + final Object[] items; + + /** items index for next take, poll, peek or remove */ + int takeIndex; + + /** items index for next put, offer, or add */ + int putIndex; + + /** Number of elements in the queue */ + int count; /* * Concurrency control uses the classic two-condition algorithm @@ -98,7 +101,7 @@ public class ArrayBlockingQueue extends AbstractQueue */ /** Main lock guarding all access */ - private final ReentrantLock lock; + final ReentrantLock lock; /** Condition for waiting takes */ private final Condition notEmpty; /** Condition for waiting puts */ @@ -110,7 +113,36 @@ public class ArrayBlockingQueue extends AbstractQueue * Circularly increment i. */ final int inc(int i) { - return (++i == items.length)? 0 : i; + return (++i == items.length) ? 0 : i; + } + + /** + * Circularly decrement i. + */ + final int dec(int i) { + return ((i == 0) ? items.length : i) - 1; + } + + @SuppressWarnings("unchecked") + static E cast(Object item) { + return (E) item; + } + + /** + * Returns item at index i. + */ + final E itemAt(int i) { + return this.cast(items[i]); + } + + /** + * Throws NullPointerException if argument is null. + * + * @param v the element + */ + private static void checkNotNull(Object v) { + if (v == null) + throw new NullPointerException(); } /** @@ -129,8 +161,8 @@ public class ArrayBlockingQueue extends AbstractQueue * Call only when holding lock. */ private E extract() { - final E[] items = this.items; - E x = items[takeIndex]; + final Object[] items = this.items; + E x = this.cast(items[takeIndex]); items[takeIndex] = null; takeIndex = inc(takeIndex); --count; @@ -139,11 +171,12 @@ public class ArrayBlockingQueue extends AbstractQueue } /** - * Utility for remove and iterator.remove: Delete item at position i. + * Deletes item at position i. + * Utility for remove and iterator.remove. * Call only when holding lock. */ void removeAt(int i) { - final E[] items = this.items; + final Object[] items = this.items; // if removing front item, just advance if (i == takeIndex) { items[takeIndex] = null; @@ -167,69 +200,82 @@ public class ArrayBlockingQueue extends AbstractQueue } /** - * Creates an ArrayBlockingQueue with the given (fixed) + * Creates an {@code ArrayBlockingQueue} with the given (fixed) * capacity and default access policy. * * @param capacity the capacity of this queue - * @throws IllegalArgumentException if capacity is less than 1 + * @throws IllegalArgumentException if {@code capacity < 1} */ public ArrayBlockingQueue(int capacity) { this(capacity, false); } /** - * Creates an ArrayBlockingQueue with the given (fixed) + * Creates an {@code ArrayBlockingQueue} with the given (fixed) * capacity and the specified access policy. * * @param capacity the capacity of this queue - * @param fair if true then queue accesses for threads blocked + * @param fair if {@code true} then queue accesses for threads blocked * on insertion or removal, are processed in FIFO order; - * if false the access order is unspecified. - * @throws IllegalArgumentException if capacity is less than 1 + * if {@code false} the access order is unspecified. + * @throws IllegalArgumentException if {@code capacity < 1} */ public ArrayBlockingQueue(int capacity, boolean fair) { if (capacity <= 0) throw new IllegalArgumentException(); - this.items = (E[]) new Object[capacity]; + this.items = new Object[capacity]; lock = new ReentrantLock(fair); notEmpty = lock.newCondition(); notFull = lock.newCondition(); } /** - * Creates an ArrayBlockingQueue with the given (fixed) + * Creates an {@code ArrayBlockingQueue} with the given (fixed) * capacity, the specified access policy and initially containing the * elements of the given collection, * added in traversal order of the collection's iterator. * * @param capacity the capacity of this queue - * @param fair if true then queue accesses for threads blocked + * @param fair if {@code true} then queue accesses for threads blocked * on insertion or removal, are processed in FIFO order; - * if false the access order is unspecified. + * if {@code false} the access order is unspecified. * @param c the collection of elements to initially contain - * @throws IllegalArgumentException if capacity is less than - * c.size(), or less than 1. + * @throws IllegalArgumentException if {@code capacity} is less than + * {@code c.size()}, or less than 1. * @throws NullPointerException if the specified collection or any * of its elements are null */ public ArrayBlockingQueue(int capacity, boolean fair, Collection c) { this(capacity, fair); - if (capacity < c.size()) - throw new IllegalArgumentException(); - for (E e : c) - add(e); + final ReentrantLock lock = this.lock; + lock.lock(); // Lock only for visibility, not mutual exclusion + try { + int i = 0; + try { + for (E e : c) { + checkNotNull(e); + items[i++] = e; + } + } catch (ArrayIndexOutOfBoundsException ex) { + throw new IllegalArgumentException(); + } + count = i; + putIndex = (i == capacity) ? 0 : i; + } finally { + lock.unlock(); + } } /** * Inserts the specified element at the tail of this queue if it is * possible to do so immediately without exceeding the queue's capacity, - * returning true upon success and throwing an - * IllegalStateException if this queue is full. + * returning {@code true} upon success and throwing an + * {@code IllegalStateException} if this queue is full. * * @param e the element to add - * @return true (as specified by {@link Collection#add}) + * @return {@code true} (as specified by {@link Collection#add}) * @throws IllegalStateException if this queue is full * @throws NullPointerException if the specified element is null */ @@ -240,14 +286,14 @@ public class ArrayBlockingQueue extends AbstractQueue /** * Inserts the specified element at the tail of this queue if it is * possible to do so immediately without exceeding the queue's capacity, - * returning true upon success and false if this queue + * returning {@code true} upon success and {@code false} if this queue * is full. This method is generally preferable to method {@link #add}, * which can fail to insert an element only by throwing an exception. * * @throws NullPointerException if the specified element is null */ public boolean offer(E e) { - if (e == null) throw new NullPointerException(); + checkNotNull(e); final ReentrantLock lock = this.lock; lock.lock(); try { @@ -270,18 +316,12 @@ public class ArrayBlockingQueue extends AbstractQueue * @throws NullPointerException {@inheritDoc} */ public void put(E e) throws InterruptedException { - if (e == null) throw new NullPointerException(); - final E[] items = this.items; + checkNotNull(e); final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { - try { - while (count == items.length) - notFull.await(); - } catch (InterruptedException ie) { - notFull.signal(); // propagate to non-interrupted thread - throw ie; - } + while (count == items.length) + notFull.await(); insert(e); } finally { lock.unlock(); @@ -299,25 +339,18 @@ public class ArrayBlockingQueue extends AbstractQueue public boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException { - if (e == null) throw new NullPointerException(); + checkNotNull(e); long nanos = unit.toNanos(timeout); final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { - for (;;) { - if (count != items.length) { - insert(e); - return true; - } + while (count == items.length) { if (nanos <= 0) return false; - try { - nanos = notFull.awaitNanos(nanos); - } catch (InterruptedException ie) { - notFull.signal(); // propagate to non-interrupted thread - throw ie; - } + nanos = notFull.awaitNanos(nanos); } + insert(e); + return true; } finally { lock.unlock(); } @@ -327,10 +360,7 @@ public class ArrayBlockingQueue extends AbstractQueue final ReentrantLock lock = this.lock; lock.lock(); try { - if (count == 0) - return null; - E x = extract(); - return x; + return (count == 0) ? null : extract(); } finally { lock.unlock(); } @@ -340,15 +370,9 @@ public class ArrayBlockingQueue extends AbstractQueue final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { - try { - while (count == 0) - notEmpty.await(); - } catch (InterruptedException ie) { - notEmpty.signal(); // propagate to non-interrupted thread - throw ie; - } - E x = extract(); - return x; + while (count == 0) + notEmpty.await(); + return extract(); } finally { lock.unlock(); } @@ -359,21 +383,12 @@ public class ArrayBlockingQueue extends AbstractQueue final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { - for (;;) { - if (count != 0) { - E x = extract(); - return x; - } + while (count == 0) { if (nanos <= 0) return null; - try { - nanos = notEmpty.awaitNanos(nanos); - } catch (InterruptedException ie) { - notEmpty.signal(); // propagate to non-interrupted thread - throw ie; - } - + nanos = notEmpty.awaitNanos(nanos); } + return extract(); } finally { lock.unlock(); } @@ -383,7 +398,7 @@ public class ArrayBlockingQueue extends AbstractQueue final ReentrantLock lock = this.lock; lock.lock(); try { - return (count == 0) ? null : items[takeIndex]; + return (count == 0) ? null : itemAt(takeIndex); } finally { lock.unlock(); } @@ -412,10 +427,10 @@ public class ArrayBlockingQueue extends AbstractQueue * Returns the number of additional elements that this queue can ideally * (in the absence of memory or resource constraints) accept without * blocking. This is always equal to the initial capacity of this queue - * less the current size of this queue. + * less the current {@code size} of this queue. * *

    Note that you cannot always tell if an attempt to insert - * an element will succeed by inspecting remainingCapacity + * an element will succeed by inspecting {@code remainingCapacity} * because it may be the case that another thread is about to * insert or remove an element. */ @@ -431,59 +446,56 @@ public class ArrayBlockingQueue extends AbstractQueue /** * Removes a single instance of the specified element from this queue, - * if it is present. More formally, removes an element e such - * that o.equals(e), if this queue contains one or more such + * if it is present. More formally, removes an element {@code e} such + * that {@code o.equals(e)}, if this queue contains one or more such * elements. - * Returns true if this queue contained the specified element + * Returns {@code true} if this queue contained the specified element * (or equivalently, if this queue changed as a result of the call). * + *

    Removal of interior elements in circular array based queues + * is an intrinsically slow and disruptive operation, so should + * be undertaken only in exceptional circumstances, ideally + * only when the queue is known not to be accessible by other + * threads. + * * @param o element to be removed from this queue, if present - * @return true if this queue changed as a result of the call + * @return {@code true} if this queue changed as a result of the call */ public boolean remove(Object o) { if (o == null) return false; - final E[] items = this.items; + final Object[] items = this.items; final ReentrantLock lock = this.lock; lock.lock(); try { - int i = takeIndex; - int k = 0; - for (;;) { - if (k++ >= count) - return false; + for (int i = takeIndex, k = count; k > 0; i = inc(i), k--) { if (o.equals(items[i])) { removeAt(i); return true; } - i = inc(i); } - + return false; } finally { lock.unlock(); } } /** - * Returns true if this queue contains the specified element. - * More formally, returns true if and only if this queue contains - * at least one element e such that o.equals(e). + * Returns {@code true} if this queue contains the specified element. + * More formally, returns {@code true} if and only if this queue contains + * at least one element {@code e} such that {@code o.equals(e)}. * * @param o object to be checked for containment in this queue - * @return true if this queue contains the specified element + * @return {@code true} if this queue contains the specified element */ public boolean contains(Object o) { if (o == null) return false; - final E[] items = this.items; + final Object[] items = this.items; final ReentrantLock lock = this.lock; lock.lock(); try { - int i = takeIndex; - int k = 0; - while (k++ < count) { + for (int i = takeIndex, k = count; k > 0; i = inc(i), k--) if (o.equals(items[i])) return true; - i = inc(i); - } return false; } finally { lock.unlock(); @@ -504,17 +516,14 @@ public class ArrayBlockingQueue extends AbstractQueue * @return an array containing all of the elements in this queue */ public Object[] toArray() { - final E[] items = this.items; + final Object[] items = this.items; final ReentrantLock lock = this.lock; lock.lock(); try { + final int count = this.count; Object[] a = new Object[count]; - int k = 0; - int i = takeIndex; - while (k < count) { - a[k++] = items[i]; - i = inc(i); - } + for (int i = takeIndex, k = 0; k < count; i = inc(i), k++) + a[k] = items[i]; return a; } finally { lock.unlock(); @@ -531,22 +540,22 @@ public class ArrayBlockingQueue extends AbstractQueue *

    If this queue fits in the specified array with room to spare * (i.e., the array has more elements than this queue), the element in * the array immediately following the end of the queue is set to - * null. + * {@code null}. * *

    Like the {@link #toArray()} method, this method acts as bridge between * array-based and collection-based APIs. Further, this method allows * precise control over the runtime type of the output array, and may, * under certain circumstances, be used to save allocation costs. * - *

    Suppose x is a queue known to contain only strings. + *

    Suppose {@code x} is a queue known to contain only strings. * The following code can be used to dump the queue into a newly - * allocated array of String: + * allocated array of {@code String}: * *

          *     String[] y = x.toArray(new String[0]);
    * - * Note that toArray(new Object[0]) is identical in function to - * toArray(). + * Note that {@code toArray(new Object[0])} is identical in function to + * {@code toArray()}. * * @param a the array into which the elements of the queue are to * be stored, if it is big enough; otherwise, a new array of the @@ -557,24 +566,20 @@ public class ArrayBlockingQueue extends AbstractQueue * this queue * @throws NullPointerException if the specified array is null */ + @SuppressWarnings("unchecked") public T[] toArray(T[] a) { - final E[] items = this.items; + final Object[] items = this.items; final ReentrantLock lock = this.lock; lock.lock(); try { - if (a.length < count) + final int count = this.count; + final int len = a.length; + if (len < count) a = (T[])java.lang.reflect.Array.newInstance( - a.getClass().getComponentType(), - count - ); - - int k = 0; - int i = takeIndex; - while (k < count) { - a[k++] = (T)items[i]; - i = inc(i); - } - if (a.length > count) + a.getClass().getComponentType(), count); + for (int i = takeIndex, k = 0; k < count; i = inc(i), k++) + a[k] = (T) items[i]; + if (len > count) a[count] = null; return a; } finally { @@ -586,7 +591,19 @@ public class ArrayBlockingQueue extends AbstractQueue final ReentrantLock lock = this.lock; lock.lock(); try { - return super.toString(); + int k = count; + if (k == 0) + return "[]"; + + StringBuilder sb = new StringBuilder(); + sb.append('['); + for (int i = takeIndex; ; i = inc(i)) { + Object e = items[i]; + sb.append(e == this ? "(this Collection)" : e); + if (--k == 0) + return sb.append(']').toString(); + sb.append(',').append(' '); + } } finally { lock.unlock(); } @@ -597,16 +614,12 @@ public class ArrayBlockingQueue extends AbstractQueue * The queue will be empty after this call returns. */ public void clear() { - final E[] items = this.items; + final Object[] items = this.items; final ReentrantLock lock = this.lock; lock.lock(); try { - int i = takeIndex; - int k = count; - while (k-- > 0) { + for (int i = takeIndex, k = count; k > 0; i = inc(i), k--) items[i] = null; - i = inc(i); - } count = 0; putIndex = 0; takeIndex = 0; @@ -623,11 +636,10 @@ public class ArrayBlockingQueue extends AbstractQueue * @throws IllegalArgumentException {@inheritDoc} */ public int drainTo(Collection c) { - if (c == null) - throw new NullPointerException(); + checkNotNull(c); if (c == this) throw new IllegalArgumentException(); - final E[] items = this.items; + final Object[] items = this.items; final ReentrantLock lock = this.lock; lock.lock(); try { @@ -635,7 +647,7 @@ public class ArrayBlockingQueue extends AbstractQueue int n = 0; int max = count; while (n < max) { - c.add(items[i]); + c.add(this.cast(items[i])); items[i] = null; i = inc(i); ++n; @@ -659,22 +671,20 @@ public class ArrayBlockingQueue extends AbstractQueue * @throws IllegalArgumentException {@inheritDoc} */ public int drainTo(Collection c, int maxElements) { - if (c == null) - throw new NullPointerException(); + checkNotNull(c); if (c == this) throw new IllegalArgumentException(); if (maxElements <= 0) return 0; - final E[] items = this.items; + final Object[] items = this.items; final ReentrantLock lock = this.lock; lock.lock(); try { int i = takeIndex; int n = 0; - int sz = count; - int max = (maxElements < count)? maxElements : count; + int max = (maxElements < count) ? maxElements : count; while (n < max) { - c.add(items[i]); + c.add(this.cast(items[i])); items[i] = null; i = inc(i); ++n; @@ -690,11 +700,13 @@ public class ArrayBlockingQueue extends AbstractQueue } } - /** * Returns an iterator over the elements in this queue in proper sequence. - * The returned Iterator is a "weakly consistent" iterator that - * will never throw {@link ConcurrentModificationException}, + * The elements will be returned in order from first (head) to last (tail). + * + *

    The returned {@code Iterator} is a "weakly consistent" iterator that + * will never throw {@link java.util.ConcurrentModificationException + * ConcurrentModificationException}, * and guarantees to traverse elements as they existed upon * construction of the iterator, and may (but is not guaranteed to) * reflect any modifications subsequent to construction. @@ -702,83 +714,65 @@ public class ArrayBlockingQueue extends AbstractQueue * @return an iterator over the elements in this queue in proper sequence */ public Iterator iterator() { - final ReentrantLock lock = this.lock; - lock.lock(); - try { - return new Itr(); - } finally { - lock.unlock(); - } + return new Itr(); } /** - * Iterator for ArrayBlockingQueue + * Iterator for ArrayBlockingQueue. To maintain weak consistency + * with respect to puts and takes, we (1) read ahead one slot, so + * as to not report hasNext true but then not have an element to + * return -- however we later recheck this slot to use the most + * current value; (2) ensure that each array slot is traversed at + * most once (by tracking "remaining" elements); (3) skip over + * null slots, which can occur if takes race ahead of iterators. + * However, for circular array-based queues, we cannot rely on any + * well established definition of what it means to be weakly + * consistent with respect to interior removes since these may + * require slot overwrites in the process of sliding elements to + * cover gaps. So we settle for resiliency, operating on + * established apparent nexts, which may miss some elements that + * have moved between calls to next. */ private class Itr implements Iterator { - /** - * Index of element to be returned by next, - * or a negative number if no such. - */ - private int nextIndex; - - /** - * nextItem holds on to item fields because once we claim - * that an element exists in hasNext(), we must return it in - * the following next() call even if it was in the process of - * being removed when hasNext() was called. - */ - private E nextItem; - - /** - * Index of element returned by most recent call to next. - * Reset to -1 if this element is deleted by a call to remove. - */ - private int lastRet; + private int remaining; // Number of elements yet to be returned + private int nextIndex; // Index of element to be returned by next + private E nextItem; // Element to be returned by next call to next + private E lastItem; // Element returned by last call to next + private int lastRet; // Index of last element returned, or -1 if none Itr() { - lastRet = -1; - if (count == 0) - nextIndex = -1; - else { - nextIndex = takeIndex; - nextItem = items[takeIndex]; + final ReentrantLock lock = ArrayBlockingQueue.this.lock; + lock.lock(); + try { + lastRet = -1; + if ((remaining = count) > 0) + nextItem = itemAt(nextIndex = takeIndex); + } finally { + lock.unlock(); } } public boolean hasNext() { - /* - * No sync. We can return true by mistake here - * only if this iterator passed across threads, - * which we don't support anyway. - */ - return nextIndex >= 0; - } - - /** - * Checks whether nextIndex is valid; if so setting nextItem. - * Stops iterator when either hits putIndex or sees null item. - */ - private void checkNext() { - if (nextIndex == putIndex) { - nextIndex = -1; - nextItem = null; - } else { - nextItem = items[nextIndex]; - if (nextItem == null) - nextIndex = -1; - } + return remaining > 0; } public E next() { final ReentrantLock lock = ArrayBlockingQueue.this.lock; lock.lock(); try { - if (nextIndex < 0) + if (remaining <= 0) throw new NoSuchElementException(); lastRet = nextIndex; - E x = nextItem; - nextIndex = inc(nextIndex); - checkNext(); + E x = itemAt(nextIndex); // check for fresher value + if (x == null) { + x = nextItem; // we are forced to report old value + lastItem = null; // but ensure remove fails + } + else + lastItem = x; + while (--remaining > 0 && // skip over nulls + (nextItem = itemAt(nextIndex = inc(nextIndex))) == null) + ; return x; } finally { lock.unlock(); @@ -793,15 +787,19 @@ public class ArrayBlockingQueue extends AbstractQueue if (i == -1) throw new IllegalStateException(); lastRet = -1; - - int ti = takeIndex; - removeAt(i); - // back up cursor (reset to front if was first element) - nextIndex = (i == ti) ? takeIndex : i; - checkNext(); + E x = lastItem; + lastItem = null; + // only remove if item still at index + if (x != null && x == items[i]) { + boolean removingHead = (i == takeIndex); + removeAt(i); + if (!removingHead) + nextIndex = dec(nextIndex); + } } finally { lock.unlock(); } } } + } diff --git a/src/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java b/src/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java index 72133fedad7691db6cd64c944b17251fe3156bb0..2158084f9f9c1053b3068e6cbfd7cac01b92b2cf 100644 --- a/src/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java +++ b/src/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java @@ -869,6 +869,8 @@ public class ConcurrentLinkedDeque /** * Inserts the specified element at the front of this deque. + * As the deque is unbounded, this method will never throw + * {@link IllegalStateException}. * * @throws NullPointerException if the specified element is null */ @@ -878,6 +880,8 @@ public class ConcurrentLinkedDeque /** * Inserts the specified element at the end of this deque. + * As the deque is unbounded, this method will never throw + * {@link IllegalStateException}. * *

    This method is equivalent to {@link #add}. * @@ -889,8 +893,9 @@ public class ConcurrentLinkedDeque /** * Inserts the specified element at the front of this deque. + * As the deque is unbounded, this method will never return {@code false}. * - * @return {@code true} always + * @return {@code true} (as specified by {@link Deque#offerFirst}) * @throws NullPointerException if the specified element is null */ public boolean offerFirst(E e) { @@ -900,10 +905,11 @@ public class ConcurrentLinkedDeque /** * Inserts the specified element at the end of this deque. + * As the deque is unbounded, this method will never return {@code false}. * *

    This method is equivalent to {@link #add}. * - * @return {@code true} always + * @return {@code true} (as specified by {@link Deque#offerLast}) * @throws NullPointerException if the specified element is null */ public boolean offerLast(E e) { @@ -983,6 +989,7 @@ public class ConcurrentLinkedDeque /** * Inserts the specified element at the tail of this deque. + * As the deque is unbounded, this method will never return {@code false}. * * @return {@code true} (as specified by {@link Queue#offer}) * @throws NullPointerException if the specified element is null @@ -993,6 +1000,8 @@ public class ConcurrentLinkedDeque /** * Inserts the specified element at the tail of this deque. + * As the deque is unbounded, this method will never throw + * {@link IllegalStateException} or return {@code false}. * * @return {@code true} (as specified by {@link Collection#add}) * @throws NullPointerException if the specified element is null diff --git a/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java b/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java index 6ff1b8a5119b9b25c837f4856424647ed95c9a83..b7beda274daec21bfe78a2e8042e144569477f57 100644 --- a/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java +++ b/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java @@ -269,6 +269,8 @@ public class ConcurrentLinkedQueue extends AbstractQueue /** * Inserts the specified element at the tail of this queue. + * As the queue is unbounded, this method will never throw + * {@link IllegalStateException} or return {@code false}. * * @return {@code true} (as specified by {@link Collection#add}) * @throws NullPointerException if the specified element is null @@ -298,6 +300,7 @@ public class ConcurrentLinkedQueue extends AbstractQueue /** * Inserts the specified element at the tail of this queue. + * As the queue is unbounded, this method will never return {@code false}. * * @return {@code true} (as specified by {@link Queue#offer}) * @throws NullPointerException if the specified element is null diff --git a/src/share/classes/java/util/concurrent/ConcurrentSkipListMap.java b/src/share/classes/java/util/concurrent/ConcurrentSkipListMap.java index 4e0457f2877edac41980b4481b393e6b30e6b648..64d28cf60408f36f59e1f1bdc8c3ef6fcb7d025c 100644 --- a/src/share/classes/java/util/concurrent/ConcurrentSkipListMap.java +++ b/src/share/classes/java/util/concurrent/ConcurrentSkipListMap.java @@ -374,17 +374,11 @@ public class ConcurrentSkipListMap extends AbstractMap null, null, 1); } - /** Updater for casHead */ - private static final - AtomicReferenceFieldUpdater - headUpdater = AtomicReferenceFieldUpdater.newUpdater - (ConcurrentSkipListMap.class, HeadIndex.class, "head"); - /** * compareAndSet head node */ private boolean casHead(HeadIndex cmp, HeadIndex val) { - return headUpdater.compareAndSet(this, cmp, val); + return UNSAFE.compareAndSwapObject(this, headOffset, cmp, val); } /* ---------------- Nodes -------------- */ @@ -423,28 +417,18 @@ public class ConcurrentSkipListMap extends AbstractMap this.next = next; } - /** Updater for casNext */ - static final AtomicReferenceFieldUpdater - nextUpdater = AtomicReferenceFieldUpdater.newUpdater - (Node.class, Node.class, "next"); - - /** Updater for casValue */ - static final AtomicReferenceFieldUpdater - valueUpdater = AtomicReferenceFieldUpdater.newUpdater - (Node.class, Object.class, "value"); - /** * compareAndSet value field */ boolean casValue(Object cmp, Object val) { - return valueUpdater.compareAndSet(this, cmp, val); + return UNSAFE.compareAndSwapObject(this, valueOffset, cmp, val); } /** * compareAndSet next field */ boolean casNext(Node cmp, Node val) { - return nextUpdater.compareAndSet(this, cmp, val); + return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val); } /** @@ -522,6 +506,14 @@ public class ConcurrentSkipListMap extends AbstractMap return null; return new AbstractMap.SimpleImmutableEntry(key, v); } + + // Unsafe mechanics + private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe(); + private static final long valueOffset = + objectFieldOffset(UNSAFE, "value", Node.class); + private static final long nextOffset = + objectFieldOffset(UNSAFE, "next", Node.class); + } /* ---------------- Indexing -------------- */ @@ -547,16 +539,11 @@ public class ConcurrentSkipListMap extends AbstractMap this.right = right; } - /** Updater for casRight */ - static final AtomicReferenceFieldUpdater - rightUpdater = AtomicReferenceFieldUpdater.newUpdater - (Index.class, Index.class, "right"); - /** * compareAndSet right field */ final boolean casRight(Index cmp, Index val) { - return rightUpdater.compareAndSet(this, cmp, val); + return UNSAFE.compareAndSwapObject(this, rightOffset, cmp, val); } /** @@ -591,6 +578,12 @@ public class ConcurrentSkipListMap extends AbstractMap final boolean unlink(Index succ) { return !indexesDeletedNode() && casRight(succ, succ.right); } + + // Unsafe mechanics + private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe(); + private static final long rightOffset = + objectFieldOffset(UNSAFE, "right", Index.class); + } /* ---------------- Head nodes -------------- */ @@ -640,7 +633,8 @@ public class ConcurrentSkipListMap extends AbstractMap * cast key as Comparable, which may cause ClassCastException, * which is propagated back to caller. */ - private Comparable comparable(Object key) throws ClassCastException { + private Comparable comparable(Object key) + throws ClassCastException { if (key == null) throw new NullPointerException(); if (comparator != null) @@ -799,68 +793,12 @@ public class ConcurrentSkipListMap extends AbstractMap } /** - * Specialized variant of findNode to perform Map.get. Does a weak - * traversal, not bothering to fix any deleted index nodes, - * returning early if it happens to see key in index, and passing - * over any deleted base nodes, falling back to getUsingFindNode - * only if it would otherwise return value from an ongoing - * deletion. Also uses "bound" to eliminate need for some - * comparisons (see Pugh Cookbook). Also folds uses of null checks - * and node-skipping because markers have null keys. + * Gets value for key using findNode. * @param okey the key * @return the value, or null if absent */ private V doGet(Object okey) { Comparable key = comparable(okey); - Node bound = null; - Index q = head; - Index r = q.right; - Node n; - K k; - int c; - for (;;) { - Index d; - // Traverse rights - if (r != null && (n = r.node) != bound && (k = n.key) != null) { - if ((c = key.compareTo(k)) > 0) { - q = r; - r = r.right; - continue; - } else if (c == 0) { - Object v = n.value; - return (v != null)? (V)v : getUsingFindNode(key); - } else - bound = n; - } - - // Traverse down - if ((d = q.down) != null) { - q = d; - r = d.right; - } else - break; - } - - // Traverse nexts - for (n = q.node.next; n != null; n = n.next) { - if ((k = n.key) != null) { - if ((c = key.compareTo(k)) == 0) { - Object v = n.value; - return (v != null)? (V)v : getUsingFindNode(key); - } else if (c < 0) - break; - } - } - return null; - } - - /** - * Performs map.get via findNode. Used as a backup if doGet - * encounters an in-progress deletion. - * @param key the key - * @return the value, or null if absent - */ - private V getUsingFindNode(Comparable key) { /* * Loop needed here and elsewhere in case value field goes * null just as it is about to be returned, in which case we @@ -943,7 +881,7 @@ public class ConcurrentSkipListMap extends AbstractMap x ^= x << 13; x ^= x >>> 17; randomSeed = x ^= x << 5; - if ((x & 0x8001) != 0) // test highest and lowest bits + if ((x & 0x80000001) != 0) // test highest and lowest bits return 0; int level = 1; while (((x >>>= 1) & 1) != 0) ++level; @@ -1256,7 +1194,7 @@ public class ConcurrentSkipListMap extends AbstractMap Node n = b.next; for (;;) { if (n == null) - return (b.isBaseHeader())? null : b; + return b.isBaseHeader() ? null : b; Node f = n.next; // inconsistent read if (n != b.next) break; @@ -1374,7 +1312,7 @@ public class ConcurrentSkipListMap extends AbstractMap Node n = b.next; for (;;) { if (n == null) - return ((rel & LT) == 0 || b.isBaseHeader())? null : b; + return ((rel & LT) == 0 || b.isBaseHeader()) ? null : b; Node f = n.next; if (n != b.next) // inconsistent read break; @@ -1390,7 +1328,7 @@ public class ConcurrentSkipListMap extends AbstractMap (c < 0 && (rel & LT) == 0)) return n; if ( c <= 0 && (rel & LT) != 0) - return (b.isBaseHeader())? null : b; + return b.isBaseHeader() ? null : b; b = n; n = f; } @@ -1744,7 +1682,7 @@ public class ConcurrentSkipListMap extends AbstractMap if (n.getValidValue() != null) ++count; } - return (count >= Integer.MAX_VALUE)? Integer.MAX_VALUE : (int)count; + return (count >= Integer.MAX_VALUE) ? Integer.MAX_VALUE : (int) count; } /** @@ -2099,7 +2037,7 @@ public class ConcurrentSkipListMap extends AbstractMap */ public K lowerKey(K key) { Node n = findNear(key, LT); - return (n == null)? null : n.key; + return (n == null) ? null : n.key; } /** @@ -2123,7 +2061,7 @@ public class ConcurrentSkipListMap extends AbstractMap */ public K floorKey(K key) { Node n = findNear(key, LT|EQ); - return (n == null)? null : n.key; + return (n == null) ? null : n.key; } /** @@ -2145,7 +2083,7 @@ public class ConcurrentSkipListMap extends AbstractMap */ public K ceilingKey(K key) { Node n = findNear(key, GT|EQ); - return (n == null)? null : n.key; + return (n == null) ? null : n.key; } /** @@ -2169,7 +2107,7 @@ public class ConcurrentSkipListMap extends AbstractMap */ public K higherKey(K key) { Node n = findNear(key, GT); - return (n == null)? null : n.key; + return (n == null) ? null : n.key; } /** @@ -2342,7 +2280,8 @@ public class ConcurrentSkipListMap extends AbstractMap return list; } - static final class KeySet extends AbstractSet implements NavigableSet { + static final class KeySet + extends AbstractSet implements NavigableSet { private final ConcurrentNavigableMap m; KeySet(ConcurrentNavigableMap map) { m = map; } public int size() { return m.size(); } @@ -2359,11 +2298,11 @@ public class ConcurrentSkipListMap extends AbstractMap public E last() { return m.lastKey(); } public E pollFirst() { Map.Entry e = m.pollFirstEntry(); - return e == null? null : e.getKey(); + return (e == null) ? null : e.getKey(); } public E pollLast() { Map.Entry e = m.pollLastEntry(); - return e == null? null : e.getKey(); + return (e == null) ? null : e.getKey(); } public Iterator iterator() { if (m instanceof ConcurrentSkipListMap) @@ -2710,9 +2649,9 @@ public class ConcurrentSkipListMap extends AbstractMap rel &= ~m.LT; } if (tooLow(key)) - return ((rel & m.LT) != 0)? null : lowestEntry(); + return ((rel & m.LT) != 0) ? null : lowestEntry(); if (tooHigh(key)) - return ((rel & m.LT) != 0)? highestEntry() : null; + return ((rel & m.LT) != 0) ? highestEntry() : null; for (;;) { Node n = m.findNear(key, rel); if (n == null || !inBounds(n.key)) @@ -2783,7 +2722,7 @@ public class ConcurrentSkipListMap extends AbstractMap public V remove(Object key) { K k = (K)key; - return (!inBounds(k))? null : m.remove(k); + return (!inBounds(k)) ? null : m.remove(k); } public int size() { @@ -2794,7 +2733,7 @@ public class ConcurrentSkipListMap extends AbstractMap if (n.getValidValue() != null) ++count; } - return count >= Integer.MAX_VALUE? Integer.MAX_VALUE : (int)count; + return count >= Integer.MAX_VALUE ? Integer.MAX_VALUE : (int)count; } public boolean isEmpty() { @@ -2972,27 +2911,27 @@ public class ConcurrentSkipListMap extends AbstractMap } public K firstKey() { - return isDescending? highestKey() : lowestKey(); + return isDescending ? highestKey() : lowestKey(); } public K lastKey() { - return isDescending? lowestKey() : highestKey(); + return isDescending ? lowestKey() : highestKey(); } public Map.Entry firstEntry() { - return isDescending? highestEntry() : lowestEntry(); + return isDescending ? highestEntry() : lowestEntry(); } public Map.Entry lastEntry() { - return isDescending? lowestEntry() : highestEntry(); + return isDescending ? lowestEntry() : highestEntry(); } public Map.Entry pollFirstEntry() { - return isDescending? removeHighest() : removeLowest(); + return isDescending ? removeHighest() : removeLowest(); } public Map.Entry pollLastEntry() { - return isDescending? removeLowest() : removeHighest(); + return isDescending ? removeLowest() : removeHighest(); } /* ---------------- Submap Views -------------- */ @@ -3141,4 +3080,22 @@ public class ConcurrentSkipListMap extends AbstractMap } } } + + // Unsafe mechanics + private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe(); + private static final long headOffset = + objectFieldOffset(UNSAFE, "head", ConcurrentSkipListMap.class); + + static long objectFieldOffset(sun.misc.Unsafe UNSAFE, + String field, Class klazz) { + try { + return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field)); + } catch (NoSuchFieldException e) { + // Convert Exception to corresponding Error + NoSuchFieldError error = new NoSuchFieldError(field); + error.initCause(e); + throw error; + } + } + } diff --git a/src/share/classes/java/util/concurrent/CopyOnWriteArrayList.java b/src/share/classes/java/util/concurrent/CopyOnWriteArrayList.java index 465426ff8231b551123e3a74e0e08e5ada11443f..8c5193538fae26b24131730f74c3f7b6d20ad503 100644 --- a/src/share/classes/java/util/concurrent/CopyOnWriteArrayList.java +++ b/src/share/classes/java/util/concurrent/CopyOnWriteArrayList.java @@ -832,7 +832,7 @@ public class CopyOnWriteArrayList } /** - * Save the state of the list to a stream (i.e., serialize it). + * Saves the state of the list to a stream (that is, serializes it). * * @serialData The length of the array backing the list is emitted * (int), followed by all of its elements (each an Object) @@ -842,27 +842,25 @@ public class CopyOnWriteArrayList private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException{ - // Write out element count, and any hidden stuff s.defaultWriteObject(); Object[] elements = getArray(); - int len = elements.length; // Write out array length - s.writeInt(len); + s.writeInt(elements.length); // Write out all elements in the proper order. - for (int i = 0; i < len; i++) - s.writeObject(elements[i]); + for (Object element : elements) + s.writeObject(element); } /** - * Reconstitute the list from a stream (i.e., deserialize it). + * Reconstitutes the list from a stream (that is, deserializes it). + * * @param s the stream */ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { - // Read in size, and any hidden stuff s.defaultReadObject(); // bind to new lock diff --git a/src/share/classes/java/util/concurrent/ForkJoinPool.java b/src/share/classes/java/util/concurrent/ForkJoinPool.java index 263552a93ea544b7220a289f72f3355c6b7c1ddc..22938fe4ba90cb846ccac1fa5d81ee7e2137652f 100644 --- a/src/share/classes/java/util/concurrent/ForkJoinPool.java +++ b/src/share/classes/java/util/concurrent/ForkJoinPool.java @@ -525,8 +525,8 @@ public class ForkJoinPool extends AbstractExecutorService { */ private volatile long eventWaiters; - private static final int EVENT_COUNT_SHIFT = 32; - private static final long WAITER_ID_MASK = (1L << 16) - 1L; + private static final int EVENT_COUNT_SHIFT = 32; + private static final int WAITER_ID_MASK = (1 << 16) - 1; /** * A counter for events that may wake up worker threads: @@ -615,7 +615,7 @@ public class ForkJoinPool extends AbstractExecutorService { // are usually manually inlined by callers /** - * Increments running count part of workerCounts + * Increments running count part of workerCounts. */ final void incrementRunningCount() { int c; @@ -625,7 +625,17 @@ public class ForkJoinPool extends AbstractExecutorService { } /** - * Tries to decrement running count unless already zero + * Tries to increment running count part of workerCounts. + */ + final boolean tryIncrementRunningCount() { + int c; + return UNSAFE.compareAndSwapInt(this, workerCountsOffset, + c = workerCounts, + c + ONE_RUNNING); + } + + /** + * Tries to decrement running count unless already zero. */ final boolean tryDecrementRunningCount() { int wc = workerCounts; @@ -698,10 +708,11 @@ public class ForkJoinPool extends AbstractExecutorService { for (k = 0; k < n && ws[k] != null; ++k) ; if (k == n) - ws = Arrays.copyOf(ws, n << 1); + ws = workers = Arrays.copyOf(ws, n << 1); } ws[k] = w; - workers = ws; // volatile array write ensures slot visibility + int c = eventCount; // advance event count to ensure visibility + UNSAFE.compareAndSwapInt(this, eventCountOffset, c, c+1); } finally { lock.unlock(); } @@ -734,7 +745,7 @@ public class ForkJoinPool extends AbstractExecutorService { */ final void workerTerminated(ForkJoinWorkerThread w) { forgetWorker(w); - decrementWorkerCounts(w.isTrimmed()? 0 : ONE_RUNNING, ONE_TOTAL); + decrementWorkerCounts(w.isTrimmed() ? 0 : ONE_RUNNING, ONE_TOTAL); while (w.stealCount != 0) // collect final count tryAccumulateStealCount(w); tryTerminate(false); @@ -746,24 +757,23 @@ public class ForkJoinPool extends AbstractExecutorService { * Releases workers blocked on a count not equal to current count. * Normally called after precheck that eventWaiters isn't zero to * avoid wasted array checks. Gives up upon a change in count or - * upon releasing two workers, letting others take over. + * upon releasing four workers, letting others take over. */ private void releaseEventWaiters() { ForkJoinWorkerThread[] ws = workers; int n = ws.length; long h = eventWaiters; int ec = eventCount; - boolean releasedOne = false; + int releases = 4; ForkJoinWorkerThread w; int id; - while ((id = ((int)(h & WAITER_ID_MASK)) - 1) >= 0 && + while ((id = (((int)h) & WAITER_ID_MASK) - 1) >= 0 && (int)(h >>> EVENT_COUNT_SHIFT) != ec && id < n && (w = ws[id]) != null) { if (UNSAFE.compareAndSwapLong(this, eventWaitersOffset, h, w.nextWaiter)) { LockSupport.unpark(w); - if (releasedOne) // exit on second release + if (--releases == 0) break; - releasedOne = true; } if (eventCount != ec) break; @@ -793,7 +803,7 @@ public class ForkJoinPool extends AbstractExecutorService { long nh = (((long)ec) << EVENT_COUNT_SHIFT) | ((long)(w.poolIndex+1)); long h; while ((runState < SHUTDOWN || !tryTerminate(false)) && - (((int)((h = eventWaiters) & WAITER_ID_MASK)) == 0 || + (((int)(h = eventWaiters) & WAITER_ID_MASK) == 0 || (int)(h >>> EVENT_COUNT_SHIFT) == ec) && eventCount == ec) { if (UNSAFE.compareAndSwapLong(this, eventWaitersOffset, @@ -820,9 +830,9 @@ public class ForkJoinPool extends AbstractExecutorService { if (tryAccumulateStealCount(w)) { // transfer while idle boolean untimed = (w.nextWaiter != 0L || (workerCounts & RUNNING_COUNT_MASK) <= 1); - long startTime = untimed? 0 : System.nanoTime(); + long startTime = untimed ? 0 : System.nanoTime(); Thread.interrupted(); // clear/ignore interrupt - if (eventCount != ec || w.isTerminating()) + if (w.isTerminating() || eventCount != ec) break; // recheck after clear if (untimed) LockSupport.park(w); @@ -860,7 +870,8 @@ public class ForkJoinPool extends AbstractExecutorService { if ((sw = spareWaiters) != 0 && (id = (sw & SPARE_ID_MASK) - 1) >= 0 && id < n && (w = ws[id]) != null && - (workerCounts & RUNNING_COUNT_MASK) < parallelism && + (runState >= TERMINATING || + (workerCounts & RUNNING_COUNT_MASK) < parallelism) && spareWaiters == sw && UNSAFE.compareAndSwapInt(this, spareWaitersOffset, sw, w.nextSpare)) { @@ -914,12 +925,8 @@ public class ForkJoinPool extends AbstractExecutorService { break; } w.start(recordWorker(w), ueh); - if ((workerCounts >>> TOTAL_COUNT_SHIFT) >= pc) { - int c; // advance event count - UNSAFE.compareAndSwapInt(this, eventCountOffset, - c = eventCount, c+1); + if ((workerCounts >>> TOTAL_COUNT_SHIFT) >= pc) break; // add at most one unless total below target - } } } if (eventWaiters != 0L) @@ -955,7 +962,7 @@ public class ForkJoinPool extends AbstractExecutorService { } else if ((h = eventWaiters) != 0L) { long nh; - int id = ((int)(h & WAITER_ID_MASK)) - 1; + int id = (((int)h) & WAITER_ID_MASK) - 1; if (id >= 0 && id < n && (w = ws[id]) != null && (nh = w.nextWaiter) != 0L && // keep at least one worker UNSAFE.compareAndSwapLong(this, eventWaitersOffset, h, nh)) @@ -1003,24 +1010,31 @@ public class ForkJoinPool extends AbstractExecutorService { int pc = parallelism; while (w.runState == 0) { int rs = runState; - if (rs >= TERMINATING) { // propagate shutdown + if (rs >= TERMINATING) { // propagate shutdown w.shutdown(); break; } if ((inactivate || (active && (rs & ACTIVE_COUNT_MASK) >= pc)) && - UNSAFE.compareAndSwapInt(this, runStateOffset, rs, rs - 1)) + UNSAFE.compareAndSwapInt(this, runStateOffset, rs, --rs)) { inactivate = active = w.active = false; - int wc = workerCounts; + if (rs == SHUTDOWN) { // all inactive and shut down + tryTerminate(false); + continue; + } + } + int wc = workerCounts; // try to suspend as spare if ((wc & RUNNING_COUNT_MASK) > pc) { if (!(inactivate |= active) && // must inactivate to suspend - workerCounts == wc && // try to suspend as spare + workerCounts == wc && UNSAFE.compareAndSwapInt(this, workerCountsOffset, wc, wc - ONE_RUNNING)) w.suspendAsSpare(); } else if ((wc >>> TOTAL_COUNT_SHIFT) < pc) helpMaintainParallelism(); // not enough workers - else if (!ran) { + else if (ran) + break; + else { long h = eventWaiters; int ec = eventCount; if (h != 0L && (int)(h >>> EVENT_COUNT_SHIFT) != ec) @@ -1032,8 +1046,6 @@ public class ForkJoinPool extends AbstractExecutorService { else if (!(inactivate |= active)) eventSync(w, wec); // must inactivate before sync } - else - break; } } @@ -1043,35 +1055,67 @@ public class ForkJoinPool extends AbstractExecutorService { * * @param joinMe the task to join * @param worker the current worker thread + * @param timed true if wait should time out + * @param nanos timeout value if timed */ - final void awaitJoin(ForkJoinTask joinMe, ForkJoinWorkerThread worker) { + final void awaitJoin(ForkJoinTask joinMe, ForkJoinWorkerThread worker, + boolean timed, long nanos) { + long startTime = timed ? System.nanoTime() : 0L; int retries = 2 + (parallelism >> 2); // #helpJoins before blocking + boolean running = true; // false when count decremented while (joinMe.status >= 0) { - int wc; - worker.helpJoinTask(joinMe); + if (runState >= TERMINATING) { + joinMe.cancelIgnoringExceptions(); + break; + } + running = worker.helpJoinTask(joinMe, running); if (joinMe.status < 0) break; - else if (retries > 0) + if (retries > 0) { --retries; - else if (((wc = workerCounts) & RUNNING_COUNT_MASK) != 0 && - UNSAFE.compareAndSwapInt(this, workerCountsOffset, - wc, wc - ONE_RUNNING)) { - int stat, c; long h; - while ((stat = joinMe.status) >= 0 && - (h = eventWaiters) != 0L && // help release others - (int)(h >>> EVENT_COUNT_SHIFT) != eventCount) + continue; + } + int wc = workerCounts; + if ((wc & RUNNING_COUNT_MASK) != 0) { + if (running) { + if (!UNSAFE.compareAndSwapInt(this, workerCountsOffset, + wc, wc - ONE_RUNNING)) + continue; + running = false; + } + long h = eventWaiters; + if (h != 0L && (int)(h >>> EVENT_COUNT_SHIFT) != eventCount) releaseEventWaiters(); - if (stat >= 0 && - ((workerCounts & RUNNING_COUNT_MASK) == 0 || - (stat = - joinMe.internalAwaitDone(JOIN_TIMEOUT_MILLIS)) >= 0)) - helpMaintainParallelism(); // timeout or no running workers - do {} while (!UNSAFE.compareAndSwapInt - (this, workerCountsOffset, - c = workerCounts, c + ONE_RUNNING)); - if (stat < 0) - break; // else restart + if ((workerCounts & RUNNING_COUNT_MASK) != 0) { + long ms; int ns; + if (!timed) { + ms = JOIN_TIMEOUT_MILLIS; + ns = 0; + } + else { // at most JOIN_TIMEOUT_MILLIS per wait + long nt = nanos - (System.nanoTime() - startTime); + if (nt <= 0L) + break; + ms = nt / 1000000; + if (ms > JOIN_TIMEOUT_MILLIS) { + ms = JOIN_TIMEOUT_MILLIS; + ns = 0; + } + else + ns = (int) (nt % 1000000); + } + joinMe.internalAwaitDone(ms, ns); + } + if (joinMe.status < 0) + break; } + helpMaintainParallelism(); + } + if (!running) { + int c; + do {} while (!UNSAFE.compareAndSwapInt + (this, workerCountsOffset, + c = workerCounts, c + ONE_RUNNING)); } } @@ -1082,9 +1126,10 @@ public class ForkJoinPool extends AbstractExecutorService { throws InterruptedException { while (!blocker.isReleasable()) { int wc = workerCounts; - if ((wc & RUNNING_COUNT_MASK) != 0 && - UNSAFE.compareAndSwapInt(this, workerCountsOffset, - wc, wc - ONE_RUNNING)) { + if ((wc & RUNNING_COUNT_MASK) == 0) + helpMaintainParallelism(); + else if (UNSAFE.compareAndSwapInt(this, workerCountsOffset, + wc, wc - ONE_RUNNING)) { try { while (!blocker.isReleasable()) { long h = eventWaiters; @@ -1129,12 +1174,11 @@ public class ForkJoinPool extends AbstractExecutorService { // Finish now if all threads terminated; else in some subsequent call if ((workerCounts >>> TOTAL_COUNT_SHIFT) == 0) { advanceRunLevel(TERMINATED); - termination.arrive(); + termination.forceTermination(); } return true; } - /** * Actions on transition to TERMINATING * @@ -1325,17 +1369,13 @@ public class ForkJoinPool extends AbstractExecutorService { // Execution methods /** - * Common code for execute, invoke and submit + * Submits task and creates, starts, or resumes some workers if necessary */ private void doSubmit(ForkJoinTask task) { - if (task == null) - throw new NullPointerException(); - if (runState >= SHUTDOWN) - throw new RejectedExecutionException(); submissionQueue.offer(task); int c; // try to increment event count -- CAS failure OK UNSAFE.compareAndSwapInt(this, eventCountOffset, c = eventCount, c+1); - helpMaintainParallelism(); // create, start, or resume some workers + helpMaintainParallelism(); } /** @@ -1348,8 +1388,33 @@ public class ForkJoinPool extends AbstractExecutorService { * scheduled for execution */ public T invoke(ForkJoinTask task) { - doSubmit(task); - return task.join(); + if (task == null) + throw new NullPointerException(); + if (runState >= SHUTDOWN) + throw new RejectedExecutionException(); + Thread t = Thread.currentThread(); + if ((t instanceof ForkJoinWorkerThread) && + ((ForkJoinWorkerThread)t).pool == this) + return task.invoke(); // bypass submit if in same pool + else { + doSubmit(task); + return task.join(); + } + } + + /** + * Unless terminating, forks task if within an ongoing FJ + * computation in the current pool, else submits as external task. + */ + private void forkOrSubmit(ForkJoinTask task) { + if (runState >= SHUTDOWN) + throw new RejectedExecutionException(); + Thread t = Thread.currentThread(); + if ((t instanceof ForkJoinWorkerThread) && + ((ForkJoinWorkerThread)t).pool == this) + task.fork(); + else + doSubmit(task); } /** @@ -1361,7 +1426,9 @@ public class ForkJoinPool extends AbstractExecutorService { * scheduled for execution */ public void execute(ForkJoinTask task) { - doSubmit(task); + if (task == null) + throw new NullPointerException(); + forkOrSubmit(task); } // AbstractExecutorService methods @@ -1372,12 +1439,14 @@ public class ForkJoinPool extends AbstractExecutorService { * scheduled for execution */ public void execute(Runnable task) { + if (task == null) + throw new NullPointerException(); ForkJoinTask job; if (task instanceof ForkJoinTask) // avoid re-wrap job = (ForkJoinTask) task; else job = ForkJoinTask.adapt(task, null); - doSubmit(job); + forkOrSubmit(job); } /** @@ -1390,7 +1459,9 @@ public class ForkJoinPool extends AbstractExecutorService { * scheduled for execution */ public ForkJoinTask submit(ForkJoinTask task) { - doSubmit(task); + if (task == null) + throw new NullPointerException(); + forkOrSubmit(task); return task; } @@ -1400,8 +1471,10 @@ public class ForkJoinPool extends AbstractExecutorService { * scheduled for execution */ public ForkJoinTask submit(Callable task) { + if (task == null) + throw new NullPointerException(); ForkJoinTask job = ForkJoinTask.adapt(task); - doSubmit(job); + forkOrSubmit(job); return job; } @@ -1411,8 +1484,10 @@ public class ForkJoinPool extends AbstractExecutorService { * scheduled for execution */ public ForkJoinTask submit(Runnable task, T result) { + if (task == null) + throw new NullPointerException(); ForkJoinTask job = ForkJoinTask.adapt(task, result); - doSubmit(job); + forkOrSubmit(job); return job; } @@ -1422,12 +1497,14 @@ public class ForkJoinPool extends AbstractExecutorService { * scheduled for execution */ public ForkJoinTask submit(Runnable task) { + if (task == null) + throw new NullPointerException(); ForkJoinTask job; if (task instanceof ForkJoinTask) // avoid re-wrap job = (ForkJoinTask) task; else job = ForkJoinTask.adapt(task, null); - doSubmit(job); + forkOrSubmit(job); return job; } @@ -1725,8 +1802,11 @@ public class ForkJoinPool extends AbstractExecutorService { * commenced but not yet completed. This method may be useful for * debugging. A return of {@code true} reported a sufficient * period after shutdown may indicate that submitted tasks have - * ignored or suppressed interruption, causing this executor not - * to properly terminate. + * ignored or suppressed interruption, or are waiting for IO, + * causing this executor not to properly terminate. (See the + * advisory notes for class {@link ForkJoinTask} stating that + * tasks should not normally entail blocking operations. But if + * they do, they must abort them on interrupt.) * * @return {@code true} if terminating but not yet terminated */ @@ -1764,10 +1844,11 @@ public class ForkJoinPool extends AbstractExecutorService { public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { try { - return termination.awaitAdvanceInterruptibly(0, timeout, unit) > 0; + termination.awaitAdvanceInterruptibly(0, timeout, unit); } catch (TimeoutException ex) { return false; } + return true; } /** diff --git a/src/share/classes/java/util/concurrent/ForkJoinTask.java b/src/share/classes/java/util/concurrent/ForkJoinTask.java index cd18360f83da6f3e4a5e2ba725975c4bc663514a..b02323ffd6dc27ec7e11e4f075f1a6ecfb7bb92f 100644 --- a/src/share/classes/java/util/concurrent/ForkJoinTask.java +++ b/src/share/classes/java/util/concurrent/ForkJoinTask.java @@ -42,6 +42,16 @@ import java.util.List; import java.util.RandomAccess; import java.util.Map; import java.util.WeakHashMap; +import java.util.concurrent.Callable; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.RunnableFuture; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; /** * Abstract base class for tasks that run within a {@link ForkJoinPool}. @@ -129,6 +139,16 @@ import java.util.WeakHashMap; * result in exceptions or errors, possibly including * {@code ClassCastException}. * + *

    Method {@link #join} and its variants are appropriate for use + * only when completion dependencies are acyclic; that is, the + * parallel computation can be described as a directed acyclic graph + * (DAG). Otherwise, executions may encounter a form of deadlock as + * tasks cyclically wait for each other. However, this framework + * supports other methods and techniques (for example the use of + * {@link Phaser}, {@link #helpQuiesce}, and {@link #complete}) that + * may be of use in constructing custom subclasses for problems that + * are not statically structured as DAGs. + * *

    Most base support methods are {@code final}, to prevent * overriding of implementations that are intrinsically tied to the * underlying lightweight task scheduling framework. Developers @@ -143,9 +163,10 @@ import java.util.WeakHashMap; * computation. Large tasks should be split into smaller subtasks, * usually via recursive decomposition. As a very rough rule of thumb, * a task should perform more than 100 and less than 10000 basic - * computational steps. If tasks are too big, then parallelism cannot - * improve throughput. If too small, then memory and internal task - * maintenance overhead may overwhelm processing. + * computational steps, and should avoid indefinite looping. If tasks + * are too big, then parallelism cannot improve throughput. If too + * small, then memory and internal task maintenance overhead may + * overwhelm processing. * *

    This class provides {@code adapt} methods for {@link Runnable} * and {@link Callable}, that may be of use when mixing execution of @@ -241,66 +262,84 @@ public abstract class ForkJoinTask implements Future, Serializable { setCompletion(EXCEPTIONAL); } - /** - * Blocks a worker thread until completion. Called only by - * pool. Currently unused -- pool-based waits use timeout - * version below. - */ - final void internalAwaitDone() { - int s; // the odd construction reduces lock bias effects - while ((s = status) >= 0) { - try { - synchronized (this) { - if (UNSAFE.compareAndSwapInt(this, statusOffset, s,SIGNAL)) - wait(); - } - } catch (InterruptedException ie) { - cancelIfTerminating(); - } - } - } - /** * Blocks a worker thread until completed or timed out. Called * only by pool. - * - * @return status on exit */ - final int internalAwaitDone(long millis) { - int s; - if ((s = status) >= 0) { - try { + final void internalAwaitDone(long millis, int nanos) { + int s = status; + if ((s == 0 && + UNSAFE.compareAndSwapInt(this, statusOffset, 0, SIGNAL)) || + s > 0) { + try { // the odd construction reduces lock bias effects synchronized (this) { - if (UNSAFE.compareAndSwapInt(this, statusOffset, s,SIGNAL)) - wait(millis, 0); + if (status > 0) + wait(millis, nanos); + else + notifyAll(); } } catch (InterruptedException ie) { cancelIfTerminating(); } - s = status; } - return s; } /** * Blocks a non-worker-thread until completion. */ private void externalAwaitDone() { - int s; - while ((s = status) >= 0) { + if (status >= 0) { + boolean interrupted = false; synchronized (this) { - if (UNSAFE.compareAndSwapInt(this, statusOffset, s, SIGNAL)){ - boolean interrupted = false; - while (status >= 0) { + for (;;) { + int s = status; + if (s == 0) + UNSAFE.compareAndSwapInt(this, statusOffset, + 0, SIGNAL); + else if (s < 0) { + notifyAll(); + break; + } + else { try { wait(); } catch (InterruptedException ie) { interrupted = true; } } - if (interrupted) - Thread.currentThread().interrupt(); - break; + } + } + if (interrupted) + Thread.currentThread().interrupt(); + } + } + + /** + * Blocks a non-worker-thread until completion or interruption or timeout. + */ + private void externalInterruptibleAwaitDone(boolean timed, long nanos) + throws InterruptedException { + if (Thread.interrupted()) + throw new InterruptedException(); + if (status >= 0) { + long startTime = timed ? System.nanoTime() : 0L; + synchronized (this) { + for (;;) { + long nt; + int s = status; + if (s == 0) + UNSAFE.compareAndSwapInt(this, statusOffset, + 0, SIGNAL); + else if (s < 0) { + notifyAll(); + break; + } + else if (!timed) + wait(); + else if ((nt = nanos - (System.nanoTime()-startTime)) > 0L) + wait(nt / 1000000, (int)(nt % 1000000)); + else + break; } } } @@ -335,7 +374,7 @@ public abstract class ForkJoinTask implements Future, Serializable { * #isDone} returning {@code true}. * *

    This method may be invoked only from within {@code - * ForkJoinTask} computations (as may be determined using method + * ForkJoinPool} computations (as may be determined using method * {@link #inForkJoinPool}). Attempts to invoke in other contexts * result in exceptions or errors, possibly including {@code * ClassCastException}. @@ -349,10 +388,13 @@ public abstract class ForkJoinTask implements Future, Serializable { } /** - * Returns the result of the computation when it {@link #isDone is done}. - * This method differs from {@link #get()} in that + * Returns the result of the computation when it {@link #isDone is + * done}. This method differs from {@link #get()} in that * abnormal completion results in {@code RuntimeException} or - * {@code Error}, not {@code ExecutionException}. + * {@code Error}, not {@code ExecutionException}, and that + * interrupts of the calling thread do not cause the + * method to abruptly return by throwing {@code + * InterruptedException}. * * @return the computed result */ @@ -394,7 +436,7 @@ public abstract class ForkJoinTask implements Future, Serializable { * unprocessed. * *

    This method may be invoked only from within {@code - * ForkJoinTask} computations (as may be determined using method + * ForkJoinPool} computations (as may be determined using method * {@link #inForkJoinPool}). Attempts to invoke in other contexts * result in exceptions or errors, possibly including {@code * ClassCastException}. @@ -422,7 +464,7 @@ public abstract class ForkJoinTask implements Future, Serializable { * normally or exceptionally, or left unprocessed. * *

    This method may be invoked only from within {@code - * ForkJoinTask} computations (as may be determined using method + * ForkJoinPool} computations (as may be determined using method * {@link #inForkJoinPool}). Attempts to invoke in other contexts * result in exceptions or errors, possibly including {@code * ClassCastException}. @@ -477,7 +519,7 @@ public abstract class ForkJoinTask implements Future, Serializable { * unprocessed. * *

    This method may be invoked only from within {@code - * ForkJoinTask} computations (as may be determined using method + * ForkJoinPool} computations (as may be determined using method * {@link #inForkJoinPool}). Attempts to invoke in other contexts * result in exceptions or errors, possibly including {@code * ClassCastException}. @@ -529,25 +571,28 @@ public abstract class ForkJoinTask implements Future, Serializable { /** * Attempts to cancel execution of this task. This attempt will - * fail if the task has already completed, has already been - * cancelled, or could not be cancelled for some other reason. If - * successful, and this task has not started when cancel is - * called, execution of this task is suppressed, {@link - * #isCancelled} will report true, and {@link #join} will result - * in a {@code CancellationException} being thrown. + * fail if the task has already completed or could not be + * cancelled for some other reason. If successful, and this task + * has not started when {@code cancel} is called, execution of + * this task is suppressed. After this method returns + * successfully, unless there is an intervening call to {@link + * #reinitialize}, subsequent calls to {@link #isCancelled}, + * {@link #isDone}, and {@code cancel} will return {@code true} + * and calls to {@link #join} and related methods will result in + * {@code CancellationException}. * *

    This method may be overridden in subclasses, but if so, must - * still ensure that these minimal properties hold. In particular, - * the {@code cancel} method itself must not throw exceptions. + * still ensure that these properties hold. In particular, the + * {@code cancel} method itself must not throw exceptions. * *

    This method is designed to be invoked by other * tasks. To terminate the current task, you can just return or * throw an unchecked exception from its computation method, or * invoke {@link #completeExceptionally}. * - * @param mayInterruptIfRunning this value is ignored in the - * default implementation because tasks are not - * cancelled via interruption + * @param mayInterruptIfRunning this value has no effect in the + * default implementation because interrupts are not used to + * control cancellation. * * @return {@code true} if this task is now cancelled */ @@ -681,23 +726,13 @@ public abstract class ForkJoinTask implements Future, Serializable { * member of a ForkJoinPool and was interrupted while waiting */ public final V get() throws InterruptedException, ExecutionException { - int s; - if (Thread.currentThread() instanceof ForkJoinWorkerThread) { + Thread t = Thread.currentThread(); + if (t instanceof ForkJoinWorkerThread) quietlyJoin(); - s = status; - } - else { - while ((s = status) >= 0) { - synchronized (this) { // interruptible form of awaitDone - if (UNSAFE.compareAndSwapInt(this, statusOffset, - s, SIGNAL)) { - while (status >= 0) - wait(); - } - } - } - } - if (s < NORMAL) { + else + externalInterruptibleAwaitDone(false, 0L); + int s = status; + if (s != NORMAL) { Throwable ex; if (s == CANCELLED) throw new CancellationException(); @@ -723,72 +758,18 @@ public abstract class ForkJoinTask implements Future, Serializable { */ public final V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { + long nanos = unit.toNanos(timeout); Thread t = Thread.currentThread(); - ForkJoinPool pool; - if (t instanceof ForkJoinWorkerThread) { - ForkJoinWorkerThread w = (ForkJoinWorkerThread) t; - if (status >= 0 && w.unpushTask(this)) - quietlyExec(); - pool = w.pool; - } + if (t instanceof ForkJoinWorkerThread) + ((ForkJoinWorkerThread)t).joinTask(this, true, nanos); else - pool = null; - /* - * Timed wait loop intermixes cases for FJ (pool != null) and - * non FJ threads. For FJ, decrement pool count but don't try - * for replacement; increment count on completion. For non-FJ, - * deal with interrupts. This is messy, but a little less so - * than is splitting the FJ and nonFJ cases. - */ - boolean interrupted = false; - boolean dec = false; // true if pool count decremented - long nanos = unit.toNanos(timeout); - for (;;) { - if (pool == null && Thread.interrupted()) { - interrupted = true; - break; - } - int s = status; - if (s < 0) - break; - if (UNSAFE.compareAndSwapInt(this, statusOffset, s, SIGNAL)) { - long startTime = System.nanoTime(); - long nt; // wait time - while (status >= 0 && - (nt = nanos - (System.nanoTime() - startTime)) > 0) { - if (pool != null && !dec) - dec = pool.tryDecrementRunningCount(); - else { - long ms = nt / 1000000; - int ns = (int) (nt % 1000000); - try { - synchronized (this) { - if (status >= 0) - wait(ms, ns); - } - } catch (InterruptedException ie) { - if (pool != null) - cancelIfTerminating(); - else { - interrupted = true; - break; - } - } - } - } - break; - } - } - if (pool != null && dec) - pool.incrementRunningCount(); - if (interrupted) - throw new InterruptedException(); - int es = status; - if (es != NORMAL) { + externalInterruptibleAwaitDone(true, nanos); + int s = status; + if (s != NORMAL) { Throwable ex; - if (es == CANCELLED) + if (s == CANCELLED) throw new CancellationException(); - if (es == EXCEPTIONAL && (ex = exceptionMap.get(this)) != null) + if (s == EXCEPTIONAL && (ex = exceptionMap.get(this)) != null) throw new ExecutionException(ex); throw new TimeoutException(); } @@ -819,7 +800,7 @@ public abstract class ForkJoinTask implements Future, Serializable { return; } } - w.joinTask(this); + w.joinTask(this, false, 0L); } } else @@ -855,7 +836,7 @@ public abstract class ForkJoinTask implements Future, Serializable { * processed. * *

    This method may be invoked only from within {@code - * ForkJoinTask} computations (as may be determined using method + * ForkJoinPool} computations (as may be determined using method * {@link #inForkJoinPool}). Attempts to invoke in other contexts * result in exceptions or errors, possibly including {@code * ClassCastException}. @@ -874,6 +855,12 @@ public abstract class ForkJoinTask implements Future, Serializable { * under any other usage conditions are not guaranteed. * This method may be useful when executing * pre-constructed trees of subtasks in loops. + * + *

    Upon completion of this method, {@code isDone()} reports + * {@code false}, and {@code getException()} reports {@code + * null}. However, the value returned by {@code getRawResult} is + * unaffected. To clear this value, you can invoke {@code + * setRawResult(null)}. */ public void reinitialize() { if (status == EXCEPTIONAL) @@ -895,11 +882,12 @@ public abstract class ForkJoinTask implements Future, Serializable { } /** - * Returns {@code true} if the current thread is executing as a - * ForkJoinPool computation. + * Returns {@code true} if the current thread is a {@link + * ForkJoinWorkerThread} executing as a ForkJoinPool computation. * - * @return {@code true} if the current thread is executing as a - * ForkJoinPool computation, or false otherwise + * @return {@code true} if the current thread is a {@link + * ForkJoinWorkerThread} executing as a ForkJoinPool computation, + * or {@code false} otherwise */ public static boolean inForkJoinPool() { return Thread.currentThread() instanceof ForkJoinWorkerThread; @@ -914,7 +902,7 @@ public abstract class ForkJoinTask implements Future, Serializable { * were not, stolen. * *

    This method may be invoked only from within {@code - * ForkJoinTask} computations (as may be determined using method + * ForkJoinPool} computations (as may be determined using method * {@link #inForkJoinPool}). Attempts to invoke in other contexts * result in exceptions or errors, possibly including {@code * ClassCastException}. @@ -933,7 +921,7 @@ public abstract class ForkJoinTask implements Future, Serializable { * fork other tasks. * *

    This method may be invoked only from within {@code - * ForkJoinTask} computations (as may be determined using method + * ForkJoinPool} computations (as may be determined using method * {@link #inForkJoinPool}). Attempts to invoke in other contexts * result in exceptions or errors, possibly including {@code * ClassCastException}. @@ -956,7 +944,7 @@ public abstract class ForkJoinTask implements Future, Serializable { * exceeded. * *

    This method may be invoked only from within {@code - * ForkJoinTask} computations (as may be determined using method + * ForkJoinPool} computations (as may be determined using method * {@link #inForkJoinPool}). Attempts to invoke in other contexts * result in exceptions or errors, possibly including {@code * ClassCastException}. @@ -1014,7 +1002,7 @@ public abstract class ForkJoinTask implements Future, Serializable { * otherwise. * *

    This method may be invoked only from within {@code - * ForkJoinTask} computations (as may be determined using method + * ForkJoinPool} computations (as may be determined using method * {@link #inForkJoinPool}). Attempts to invoke in other contexts * result in exceptions or errors, possibly including {@code * ClassCastException}. @@ -1033,7 +1021,7 @@ public abstract class ForkJoinTask implements Future, Serializable { * be useful otherwise. * *

    This method may be invoked only from within {@code - * ForkJoinTask} computations (as may be determined using method + * ForkJoinPool} computations (as may be determined using method * {@link #inForkJoinPool}). Attempts to invoke in other contexts * result in exceptions or errors, possibly including {@code * ClassCastException}. @@ -1056,7 +1044,7 @@ public abstract class ForkJoinTask implements Future, Serializable { * otherwise. * *

    This method may be invoked only from within {@code - * ForkJoinTask} computations (as may be determined using method + * ForkJoinPool} computations (as may be determined using method * {@link #inForkJoinPool}). Attempts to invoke in other contexts * result in exceptions or errors, possibly including {@code * ClassCastException}. diff --git a/src/share/classes/java/util/concurrent/ForkJoinWorkerThread.java b/src/share/classes/java/util/concurrent/ForkJoinWorkerThread.java index 4dcfbbd571c55cfdead8edf85afa1a5f0151a01d..7d79c5190e2fe15c137957d039a36d33b3e73d69 100644 --- a/src/share/classes/java/util/concurrent/ForkJoinWorkerThread.java +++ b/src/share/classes/java/util/concurrent/ForkJoinWorkerThread.java @@ -38,16 +38,18 @@ package java.util.concurrent; import java.util.Random; import java.util.Collection; import java.util.concurrent.locks.LockSupport; +import java.util.concurrent.RejectedExecutionException; /** - * A thread managed by a {@link ForkJoinPool}. This class is - * subclassable solely for the sake of adding functionality -- there - * are no overridable methods dealing with scheduling or execution. - * However, you can override initialization and termination methods - * surrounding the main task processing loop. If you do create such a - * subclass, you will also need to supply a custom {@link - * ForkJoinPool.ForkJoinWorkerThreadFactory} to use it in a {@code - * ForkJoinPool}. + * A thread managed by a {@link ForkJoinPool}, which executes + * {@link ForkJoinTask}s. + * This class is subclassable solely for the sake of adding + * functionality -- there are no overridable methods dealing with + * scheduling or execution. However, you can override initialization + * and termination methods surrounding the main task processing loop. + * If you do create such a subclass, you will also need to supply a + * custom {@link ForkJoinPool.ForkJoinWorkerThreadFactory} to use it + * in a {@code ForkJoinPool}. * * @since 1.7 * @author Doug Lea @@ -376,7 +378,7 @@ public class ForkJoinWorkerThread extends Thread { /** * Initializes internal state after construction but before * processing any tasks. If you override this method, you must - * invoke @code{super.onStart()} at the beginning of the method. + * invoke {@code super.onStart()} at the beginning of the method. * Initialization requires care: Most fields must have legal * default values, to ensure that attempted accesses from other * threads work correctly even before this thread starts @@ -384,7 +386,7 @@ public class ForkJoinWorkerThread extends Thread { */ protected void onStart() { int rs = seedGenerator.nextInt(); - seed = rs == 0? 1 : rs; // seed must be nonzero + seed = (rs == 0) ? 1 : rs; // seed must be nonzero // Allocate name string and arrays in this thread String pid = Integer.toString(pool.getPoolNumber()); @@ -426,7 +428,7 @@ public class ForkJoinWorkerThread extends Thread { /** * This method is required to be public, but should never be * called explicitly. It performs the main run loop to execute - * ForkJoinTasks. + * {@link ForkJoinTask}s. */ public void run() { Throwable exception = null; @@ -628,6 +630,19 @@ public class ForkJoinWorkerThread extends Thread { if (t == null) // lost to stealer break; if (UNSAFE.compareAndSwapObject(q, u, t, null)) { + /* + * Note: here and in related methods, as a + * performance (not correctness) issue, we'd like + * to encourage compiler not to arbitrarily + * postpone setting sp after successful CAS. + * Currently there is no intrinsic for arranging + * this, but using Unsafe putOrderedInt may be a + * preferable strategy on some compilers even + * though its main effect is a pre-, not post- + * fence. To simplify possible changes, the option + * is left in comments next to the associated + * assignments. + */ sp = s; // putOrderedInt may encourage more timely write // UNSAFE.putOrderedInt(this, spOffset, s); return t; @@ -777,10 +792,10 @@ public class ForkJoinWorkerThread extends Thread { // Run State management // status check methods used mainly by ForkJoinPool - final boolean isRunning() { return runState == 0; } - final boolean isTerminated() { return (runState & TERMINATED) != 0; } - final boolean isSuspended() { return (runState & SUSPENDED) != 0; } - final boolean isTrimmed() { return (runState & TRIMMED) != 0; } + final boolean isRunning() { return runState == 0; } + final boolean isTerminated() { return (runState & TERMINATED) != 0; } + final boolean isSuspended() { return (runState & SUSPENDED) != 0; } + final boolean isTrimmed() { return (runState & TRIMMED) != 0; } final boolean isTerminating() { if ((runState & TERMINATING) != 0) @@ -884,8 +899,7 @@ public class ForkJoinWorkerThread extends Thread { */ final void cancelTasks() { ForkJoinTask cj = currentJoin; // try to cancel ongoing tasks - if (cj != null) { - currentJoin = null; + if (cj != null && cj.status >= 0) { cj.cancelIgnoringExceptions(); try { this.interrupt(); // awaken wait @@ -893,10 +907,8 @@ public class ForkJoinWorkerThread extends Thread { } } ForkJoinTask cs = currentSteal; - if (cs != null) { - currentSteal = null; + if (cs != null && cs.status >= 0) cs.cancelIgnoringExceptions(); - } while (base != sp) { ForkJoinTask t = deqTask(); if (t != null) @@ -959,57 +971,23 @@ public class ForkJoinWorkerThread extends Thread { * Possibly runs some tasks and/or blocks, until task is done. * * @param joinMe the task to join + * @param timed true if use timed wait + * @param nanos wait time if timed */ - final void joinTask(ForkJoinTask joinMe) { + final void joinTask(ForkJoinTask joinMe, boolean timed, long nanos) { // currentJoin only written by this thread; only need ordered store ForkJoinTask prevJoin = currentJoin; UNSAFE.putOrderedObject(this, currentJoinOffset, joinMe); - if (sp != base) - localHelpJoinTask(joinMe); - if (joinMe.status >= 0) - pool.awaitJoin(joinMe, this); + pool.awaitJoin(joinMe, this, timed, nanos); UNSAFE.putOrderedObject(this, currentJoinOffset, prevJoin); } /** - * Run tasks in local queue until given task is done. - * - * @param joinMe the task to join - */ - private void localHelpJoinTask(ForkJoinTask joinMe) { - int s; - ForkJoinTask[] q; - while (joinMe.status >= 0 && (s = sp) != base && (q = queue) != null) { - int i = (q.length - 1) & --s; - long u = (i << qShift) + qBase; // raw offset - ForkJoinTask t = q[i]; - if (t == null) // lost to a stealer - break; - if (UNSAFE.compareAndSwapObject(q, u, t, null)) { - /* - * This recheck (and similarly in helpJoinTask) - * handles cases where joinMe is independently - * cancelled or forced even though there is other work - * available. Back out of the pop by putting t back - * into slot before we commit by writing sp. - */ - if (joinMe.status < 0) { - UNSAFE.putObjectVolatile(q, u, t); - break; - } - sp = s; - // UNSAFE.putOrderedInt(this, spOffset, s); - t.quietlyExec(); - } - } - } - - /** - * Unless terminating, tries to locate and help perform tasks for - * a stealer of the given task, or in turn one of its stealers. - * Traces currentSteal->currentJoin links looking for a thread - * working on a descendant of the given task and with a non-empty - * queue to steal back and execute tasks from. + * Tries to locate and help perform tasks for a stealer of the + * given task, or in turn one of its stealers. Traces + * currentSteal->currentJoin links looking for a thread working on + * a descendant of the given task and with a non-empty queue to + * steal back and execute tasks from. * * The implementation is very branchy to cope with potential * inconsistencies or loops encountering chains that are stale, @@ -1019,77 +997,127 @@ public class ForkJoinWorkerThread extends Thread { * don't work out. * * @param joinMe the task to join + * @param running if false, then must update pool count upon + * running a task + * @return value of running on exit */ - final void helpJoinTask(ForkJoinTask joinMe) { - ForkJoinWorkerThread[] ws; - int n; - if (joinMe.status < 0) // already done - return; - if ((runState & TERMINATING) != 0) { // cancel if shutting down - joinMe.cancelIgnoringExceptions(); - return; + final boolean helpJoinTask(ForkJoinTask joinMe, boolean running) { + /* + * Initial checks to (1) abort if terminating; (2) clean out + * old cancelled tasks from local queue; (3) if joinMe is next + * task, run it; (4) omit scan if local queue nonempty (since + * it may contain non-descendents of joinMe). + */ + ForkJoinPool p = pool; + for (;;) { + ForkJoinTask[] q; + int s; + if (joinMe.status < 0) + return running; + else if ((runState & TERMINATING) != 0) { + joinMe.cancelIgnoringExceptions(); + return running; + } + else if ((s = sp) == base || (q = queue) == null) + break; // queue empty + else { + int i = (q.length - 1) & --s; + long u = (i << qShift) + qBase; // raw offset + ForkJoinTask t = q[i]; + if (t == null) + break; // lost to a stealer + else if (t != joinMe && t.status >= 0) + return running; // cannot safely help + else if ((running || + (running = p.tryIncrementRunningCount())) && + UNSAFE.compareAndSwapObject(q, u, t, null)) { + sp = s; // putOrderedInt may encourage more timely write + // UNSAFE.putOrderedInt(this, spOffset, s); + t.quietlyExec(); + } + } } - if ((ws = pool.workers) == null || (n = ws.length) <= 1) - return; // need at least 2 workers - - ForkJoinTask task = joinMe; // base of chain - ForkJoinWorkerThread thread = this; // thread with stolen task - for (int d = 0; d < MAX_HELP_DEPTH; ++d) { // chain length - // Try to find v, the stealer of task, by first using hint - ForkJoinWorkerThread v = ws[thread.stealHint & (n - 1)]; - if (v == null || v.currentSteal != task) { - for (int j = 0; ; ++j) { // search array - if (j < n) { - ForkJoinTask vs; - if ((v = ws[j]) != null && - (vs = v.currentSteal) != null) { - if (joinMe.status < 0 || task.status < 0) - return; // stale or done - if (vs == task) { - thread.stealHint = j; - break; // save hint for next time + + int n; // worker array size + ForkJoinWorkerThread[] ws = p.workers; + if (ws != null && (n = ws.length) > 1) { // need at least 2 workers + ForkJoinTask task = joinMe; // base of chain + ForkJoinWorkerThread thread = this; // thread with stolen task + + outer:for (int d = 0; d < MAX_HELP_DEPTH; ++d) { // chain length + // Try to find v, the stealer of task, by first using hint + ForkJoinWorkerThread v = ws[thread.stealHint & (n - 1)]; + if (v == null || v.currentSteal != task) { + for (int j = 0; ; ++j) { // search array + if (j < n) { + ForkJoinTask vs; + if ((v = ws[j]) != null && + (vs = v.currentSteal) != null) { + if (joinMe.status < 0) + break outer; + if (vs == task) { + if (task.status < 0) + break outer; // stale + thread.stealHint = j; + break; // save hint for next time + } } } + else + break outer; // no stealer } - else - return; // no stealer } - } - for (;;) { // Try to help v, using specialized form of deqTask - if (joinMe.status < 0) - return; - int b = v.base; - ForkJoinTask[] q = v.queue; - if (b == v.sp || q == null) - break; - int i = (q.length - 1) & b; - long u = (i << qShift) + qBase; - ForkJoinTask t = q[i]; - int pid = poolIndex; - ForkJoinTask ps = currentSteal; - if (task.status < 0) - return; // stale or done - if (t != null && v.base == b++ && - UNSAFE.compareAndSwapObject(q, u, t, null)) { - if (joinMe.status < 0) { - UNSAFE.putObjectVolatile(q, u, t); - return; // back out on cancel + + // Try to help v, using specialized form of deqTask + for (;;) { + if (joinMe.status < 0) + break outer; + int b = v.base; + ForkJoinTask[] q = v.queue; + if (b == v.sp || q == null) + break; // empty + int i = (q.length - 1) & b; + long u = (i << qShift) + qBase; + ForkJoinTask t = q[i]; + if (task.status < 0) + break outer; // stale + if (t != null && + (running || + (running = p.tryIncrementRunningCount())) && + v.base == b++ && + UNSAFE.compareAndSwapObject(q, u, t, null)) { + if (t != joinMe && joinMe.status < 0) { + UNSAFE.putObjectVolatile(q, u, t); + break outer; // joinMe cancelled; back out + } + v.base = b; + if (t.status >= 0) { + ForkJoinTask ps = currentSteal; + int pid = poolIndex; + v.stealHint = pid; + UNSAFE.putOrderedObject(this, + currentStealOffset, t); + t.quietlyExec(); + UNSAFE.putOrderedObject(this, + currentStealOffset, ps); + } + } + else if ((runState & TERMINATING) != 0) { + joinMe.cancelIgnoringExceptions(); + break outer; } - v.base = b; - v.stealHint = pid; - UNSAFE.putOrderedObject(this, currentStealOffset, t); - t.quietlyExec(); - UNSAFE.putOrderedObject(this, currentStealOffset, ps); } + + // Try to descend to find v's stealer + ForkJoinTask next = v.currentJoin; + if (task.status < 0 || next == null || next == task || + joinMe.status < 0) + break; // done, stale, dead-end, or cyclic + task = next; + thread = v; } - // Try to descend to find v's stealer - ForkJoinTask next = v.currentJoin; - if (task.status < 0 || next == null || next == task || - joinMe.status < 0) - return; - task = next; - thread = v; } + return running; } /** diff --git a/src/share/classes/java/util/concurrent/LinkedBlockingDeque.java b/src/share/classes/java/util/concurrent/LinkedBlockingDeque.java index 8051ccaa8483f71f0f873515a27f1880b051ab6f..f5d9da1cb178f52cfe7a505f3c69cdd9a10cf4d8 100644 --- a/src/share/classes/java/util/concurrent/LinkedBlockingDeque.java +++ b/src/share/classes/java/util/concurrent/LinkedBlockingDeque.java @@ -1029,6 +1029,8 @@ public class LinkedBlockingDeque * elements as they existed upon construction of the iterator, and * may (but is not guaranteed to) reflect any modifications * subsequent to construction. + * + * @return an iterator over the elements in this deque in reverse order */ public Iterator descendingIterator() { return new DescendingItr(); diff --git a/src/share/classes/java/util/concurrent/LinkedBlockingQueue.java b/src/share/classes/java/util/concurrent/LinkedBlockingQueue.java index 9746b7dedec8500f0f884c6c966882465fc23c88..5f62e79ce56bdf90da60e21d7b3076f1a5123973 100644 --- a/src/share/classes/java/util/concurrent/LinkedBlockingQueue.java +++ b/src/share/classes/java/util/concurrent/LinkedBlockingQueue.java @@ -189,14 +189,14 @@ public class LinkedBlockingQueue extends AbstractQueue } /** - * Creates a node and links it at end of queue. + * Links node at end of queue. * - * @param x the item + * @param node the node */ - private void enqueue(E x) { + private void enqueue(Node node) { // assert putLock.isHeldByCurrentThread(); // assert last.next == null; - last = last.next = new Node(x); + last = last.next = node; } /** @@ -282,7 +282,7 @@ public class LinkedBlockingQueue extends AbstractQueue throw new NullPointerException(); if (n == capacity) throw new IllegalStateException("Queue full"); - enqueue(e); + enqueue(new Node(e)); ++n; } count.set(n); @@ -332,6 +332,7 @@ public class LinkedBlockingQueue extends AbstractQueue // Note: convention in all put/take/etc is to preset local var // holding count negative to indicate failure unless set. int c = -1; + Node node = new Node(e); final ReentrantLock putLock = this.putLock; final AtomicInteger count = this.count; putLock.lockInterruptibly(); @@ -347,7 +348,7 @@ public class LinkedBlockingQueue extends AbstractQueue while (count.get() == capacity) { notFull.await(); } - enqueue(e); + enqueue(node); c = count.getAndIncrement(); if (c + 1 < capacity) notFull.signal(); @@ -382,7 +383,7 @@ public class LinkedBlockingQueue extends AbstractQueue return false; nanos = notFull.awaitNanos(nanos); } - enqueue(e); + enqueue(new Node(e)); c = count.getAndIncrement(); if (c + 1 < capacity) notFull.signal(); @@ -411,11 +412,12 @@ public class LinkedBlockingQueue extends AbstractQueue if (count.get() == capacity) return false; int c = -1; + Node node = new Node(e); final ReentrantLock putLock = this.putLock; putLock.lock(); try { if (count.get() < capacity) { - enqueue(e); + enqueue(node); c = count.getAndIncrement(); if (c + 1 < capacity) notFull.signal(); @@ -559,6 +561,27 @@ public class LinkedBlockingQueue extends AbstractQueue } } + /** + * Returns {@code true} if this queue contains the specified element. + * More formally, returns {@code true} if and only if this queue contains + * at least one element {@code e} such that {@code o.equals(e)}. + * + * @param o object to be checked for containment in this queue + * @return {@code true} if this queue contains the specified element + */ + public boolean contains(Object o) { + if (o == null) return false; + fullyLock(); + try { + for (Node p = head.next; p != null; p = p.next) + if (o.equals(p.item)) + return true; + return false; + } finally { + fullyUnlock(); + } + } + /** * Returns an array containing all of the elements in this queue, in * proper sequence. @@ -645,7 +668,20 @@ public class LinkedBlockingQueue extends AbstractQueue public String toString() { fullyLock(); try { - return super.toString(); + Node p = head.next; + if (p == null) + return "[]"; + + StringBuilder sb = new StringBuilder(); + sb.append('['); + for (;;) { + E e = p.item; + sb.append(e == this ? "(this Collection)" : e); + p = p.next; + if (p == null) + return sb.append(']').toString(); + sb.append(',').append(' '); + } } finally { fullyUnlock(); } @@ -727,12 +763,14 @@ public class LinkedBlockingQueue extends AbstractQueue /** * Returns an iterator over the elements in this queue in proper sequence. - * The returned {@code Iterator} is a "weakly consistent" iterator that + * The elements will be returned in order from first (head) to last (tail). + * + *

    The returned iterator is a "weakly consistent" iterator that * will never throw {@link java.util.ConcurrentModificationException - * ConcurrentModificationException}, - * and guarantees to traverse elements as they existed upon - * construction of the iterator, and may (but is not guaranteed to) - * reflect any modifications subsequent to construction. + * ConcurrentModificationException}, and guarantees to traverse + * elements as they existed upon construction of the iterator, and + * may (but is not guaranteed to) reflect any modifications + * subsequent to construction. * * @return an iterator over the elements in this queue in proper sequence */ diff --git a/src/share/classes/java/util/concurrent/LinkedTransferQueue.java b/src/share/classes/java/util/concurrent/LinkedTransferQueue.java index 82bed9290729a17e563ebbf7236e4099516be29d..fec92a8b189477406ab7800a2c14ca7ff5b88b03 100644 --- a/src/share/classes/java/util/concurrent/LinkedTransferQueue.java +++ b/src/share/classes/java/util/concurrent/LinkedTransferQueue.java @@ -37,10 +37,10 @@ package java.util.concurrent; import java.util.AbstractQueue; import java.util.Collection; -import java.util.ConcurrentModificationException; import java.util.Iterator; import java.util.NoSuchElementException; import java.util.Queue; +import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.LockSupport; /** @@ -450,7 +450,7 @@ public class LinkedTransferQueue extends AbstractQueue } final boolean casItem(Object cmp, Object val) { - // assert cmp == null || cmp.getClass() != Node.class; + // assert cmp == null || cmp.getClass() != Node.class; return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val); } @@ -516,7 +516,7 @@ public class LinkedTransferQueue extends AbstractQueue * Tries to artificially match a data node -- used by remove. */ final boolean tryMatchData() { - // assert isData; + // assert isData; Object x = item; if (x != null && x != this && casItem(x, null)) { LockSupport.unpark(waiter); @@ -569,7 +569,7 @@ public class LinkedTransferQueue extends AbstractQueue @SuppressWarnings("unchecked") static E cast(Object item) { - // assert item == null || item.getClass() != Node.class; + // assert item == null || item.getClass() != Node.class; return (E) item; } @@ -588,7 +588,8 @@ public class LinkedTransferQueue extends AbstractQueue throw new NullPointerException(); Node s = null; // the node to append, if needed - retry: for (;;) { // restart on append race + retry: + for (;;) { // restart on append race for (Node h = head, p = h; p != null;) { // find & match first node boolean isData = p.isData; @@ -599,7 +600,7 @@ public class LinkedTransferQueue extends AbstractQueue if (p.casItem(item, e)) { // match for (Node q = p; q != h;) { Node n = q.next; // update by 2 unless singleton - if (head == h && casHead(h, n == null? q : n)) { + if (head == h && casHead(h, n == null ? q : n)) { h.forgetNext(); break; } // advance and retry @@ -684,7 +685,7 @@ public class LinkedTransferQueue extends AbstractQueue for (;;) { Object item = s.item; if (item != e) { // matched - // assert item != s; + // assert item != s; s.forgetContents(); // avoid garbage return this.cast(item); } @@ -809,22 +810,61 @@ public class LinkedTransferQueue extends AbstractQueue * Moves to next node after prev, or first node if prev null. */ private void advance(Node prev) { - lastPred = lastRet; - lastRet = prev; - for (Node p = (prev == null) ? head : succ(prev); - p != null; p = succ(p)) { - Object item = p.item; - if (p.isData) { - if (item != null && item != p) { - nextItem = LinkedTransferQueue.this.cast(item); - nextNode = p; + /* + * To track and avoid buildup of deleted nodes in the face + * of calls to both Queue.remove and Itr.remove, we must + * include variants of unsplice and sweep upon each + * advance: Upon Itr.remove, we may need to catch up links + * from lastPred, and upon other removes, we might need to + * skip ahead from stale nodes and unsplice deleted ones + * found while advancing. + */ + + Node r, b; // reset lastPred upon possible deletion of lastRet + if ((r = lastRet) != null && !r.isMatched()) + lastPred = r; // next lastPred is old lastRet + else if ((b = lastPred) == null || b.isMatched()) + lastPred = null; // at start of list + else { + Node s, n; // help with removal of lastPred.next + while ((s = b.next) != null && + s != b && s.isMatched() && + (n = s.next) != null && n != s) + b.casNext(s, n); + } + + this.lastRet = prev; + + for (Node p = prev, s, n;;) { + s = (p == null) ? head : p.next; + if (s == null) + break; + else if (s == p) { + p = null; + continue; + } + Object item = s.item; + if (s.isData) { + if (item != null && item != s) { + nextItem = LinkedTransferQueue.cast(item); + nextNode = s; return; } } else if (item == null) break; + // assert s.isMatched(); + if (p == null) + p = s; + else if ((n = s.next) == null) + break; + else if (s == n) + p = null; + else + p.casNext(s, n); } nextNode = null; + nextItem = null; } Itr() { @@ -844,10 +884,12 @@ public class LinkedTransferQueue extends AbstractQueue } public final void remove() { - Node p = lastRet; - if (p == null) throw new IllegalStateException(); - if (p.tryMatchData()) - unsplice(lastPred, p); + final Node lastRet = this.lastRet; + if (lastRet == null) + throw new IllegalStateException(); + this.lastRet = null; + if (lastRet.tryMatchData()) + unsplice(lastPred, lastRet); } } @@ -997,8 +1039,7 @@ public class LinkedTransferQueue extends AbstractQueue * Inserts the specified element at the tail of this queue. * As the queue is unbounded, this method will never return {@code false}. * - * @return {@code true} (as specified by - * {@link BlockingQueue#offer(Object) BlockingQueue.offer}) + * @return {@code true} (as specified by {@link Queue#offer}) * @throws NullPointerException if the specified element is null */ public boolean offer(E e) { @@ -1130,15 +1171,15 @@ public class LinkedTransferQueue extends AbstractQueue } /** - * Returns an iterator over the elements in this queue in proper - * sequence, from head to tail. + * Returns an iterator over the elements in this queue in proper sequence. + * The elements will be returned in order from first (head) to last (tail). * *

    The returned iterator is a "weakly consistent" iterator that - * will never throw - * {@link ConcurrentModificationException ConcurrentModificationException}, - * and guarantees to traverse elements as they existed upon - * construction of the iterator, and may (but is not guaranteed - * to) reflect any modifications subsequent to construction. + * will never throw {@link java.util.ConcurrentModificationException + * ConcurrentModificationException}, and guarantees to traverse + * elements as they existed upon construction of the iterator, and + * may (but is not guaranteed to) reflect any modifications + * subsequent to construction. * * @return an iterator over the elements in this queue in proper sequence */ @@ -1202,6 +1243,28 @@ public class LinkedTransferQueue extends AbstractQueue return findAndRemove(o); } + /** + * Returns {@code true} if this queue contains the specified element. + * More formally, returns {@code true} if and only if this queue contains + * at least one element {@code e} such that {@code o.equals(e)}. + * + * @param o object to be checked for containment in this queue + * @return {@code true} if this queue contains the specified element + */ + public boolean contains(Object o) { + if (o == null) return false; + for (Node p = head; p != null; p = succ(p)) { + Object item = p.item; + if (p.isData) { + if (item != null && item != p && o.equals(item)) + return true; + } + else if (item == null) + break; + } + return false; + } + /** * Always returns {@code Integer.MAX_VALUE} because a * {@code LinkedTransferQueue} is not capacity constrained. diff --git a/src/share/classes/java/util/concurrent/Phaser.java b/src/share/classes/java/util/concurrent/Phaser.java index 623f46e41ed4d700dddb1f45905bb9d801f9e800..d5725b3e1a2dc1570fb6f5396f7f090c3b5c6c66 100644 --- a/src/share/classes/java/util/concurrent/Phaser.java +++ b/src/share/classes/java/util/concurrent/Phaser.java @@ -35,6 +35,8 @@ package java.util.concurrent; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.LockSupport; @@ -61,38 +63,38 @@ import java.util.concurrent.locks.LockSupport; * Phaser} may be repeatedly awaited. Method {@link * #arriveAndAwaitAdvance} has effect analogous to {@link * java.util.concurrent.CyclicBarrier#await CyclicBarrier.await}. Each - * generation of a {@code Phaser} has an associated phase number. The - * phase number starts at zero, and advances when all parties arrive - * at the barrier, wrapping around to zero after reaching {@code + * generation of a phaser has an associated phase number. The phase + * number starts at zero, and advances when all parties arrive at the + * phaser, wrapping around to zero after reaching {@code * Integer.MAX_VALUE}. The use of phase numbers enables independent - * control of actions upon arrival at a barrier and upon awaiting + * control of actions upon arrival at a phaser and upon awaiting * others, via two kinds of methods that may be invoked by any * registered party: * *

      * *
    • Arrival. Methods {@link #arrive} and - * {@link #arriveAndDeregister} record arrival at a - * barrier. These methods do not block, but return an associated - * arrival phase number; that is, the phase number of - * the barrier to which the arrival applied. When the final - * party for a given phase arrives, an optional barrier action - * is performed and the phase advances. Barrier actions, - * performed by the party triggering a phase advance, are - * arranged by overriding method {@link #onAdvance(int, int)}, - * which also controls termination. Overriding this method is - * similar to, but more flexible than, providing a barrier - * action to a {@code CyclicBarrier}. + * {@link #arriveAndDeregister} record arrival. These methods + * do not block, but return an associated arrival phase + * number; that is, the phase number of the phaser to which + * the arrival applied. When the final party for a given phase + * arrives, an optional action is performed and the phase + * advances. These actions are performed by the party + * triggering a phase advance, and are arranged by overriding + * method {@link #onAdvance(int, int)}, which also controls + * termination. Overriding this method is similar to, but more + * flexible than, providing a barrier action to a {@code + * CyclicBarrier}. * *
    • Waiting. Method {@link #awaitAdvance} requires an * argument indicating an arrival phase number, and returns when - * the barrier advances to (or is already at) a different phase. + * the phaser advances to (or is already at) a different phase. * Unlike similar constructions using {@code CyclicBarrier}, * method {@code awaitAdvance} continues to wait even if the * waiting thread is interrupted. Interruptible and timeout * versions are also available, but exceptions encountered while * tasks wait interruptibly or with timeout do not change the - * state of the barrier. If necessary, you can perform any + * state of the phaser. If necessary, you can perform any * associated recovery within handlers of those exceptions, * often after invoking {@code forceTermination}. Phasers may * also be used by tasks executing in a {@link ForkJoinPool}, @@ -101,26 +103,39 @@ import java.util.concurrent.locks.LockSupport; * *
    * - *

    Termination. A {@code Phaser} may enter a - * termination state in which all synchronization methods - * immediately return without updating phaser state or waiting for - * advance, and indicating (via a negative phase value) that execution - * is complete. Termination is triggered when an invocation of {@code - * onAdvance} returns {@code true}. As illustrated below, when - * phasers control actions with a fixed number of iterations, it is - * often convenient to override this method to cause termination when - * the current phase number reaches a threshold. Method {@link - * #forceTermination} is also available to abruptly release waiting - * threads and allow them to terminate. + *

    Termination. A phaser may enter a termination + * state, that may be checked using method {@link #isTerminated}. Upon + * termination, all synchronization methods immediately return without + * waiting for advance, as indicated by a negative return value. + * Similarly, attempts to register upon termination have no effect. + * Termination is triggered when an invocation of {@code onAdvance} + * returns {@code true}. The default implementation returns {@code + * true} if a deregistration has caused the number of registered + * parties to become zero. As illustrated below, when phasers control + * actions with a fixed number of iterations, it is often convenient + * to override this method to cause termination when the current phase + * number reaches a threshold. Method {@link #forceTermination} is + * also available to abruptly release waiting threads and allow them + * to terminate. * - *

    Tiering. Phasers may be tiered (i.e., arranged - * in tree structures) to reduce contention. Phasers with large - * numbers of parties that would otherwise experience heavy + *

    Tiering. Phasers may be tiered (i.e., + * constructed in tree structures) to reduce contention. Phasers with + * large numbers of parties that would otherwise experience heavy * synchronization contention costs may instead be set up so that * groups of sub-phasers share a common parent. This may greatly * increase throughput even though it incurs greater per-operation * overhead. * + *

    In a tree of tiered phasers, registration and deregistration of + * child phasers with their parent are managed automatically. + * Whenever the number of registered parties of a child phaser becomes + * non-zero (as established in the {@link #Phaser(Phaser,int)} + * constructor, {@link #register}, or {@link #bulkRegister}), the + * child phaser is registered with its parent. Whenever the number of + * registered parties becomes zero as the result of an invocation of + * {@link #arriveAndDeregister}, the child phaser is deregistered + * from its parent. + * *

    Monitoring. While synchronization methods may be invoked * only by registered parties, the current state of a phaser may be * monitored by any caller. At any given moment there are {@link @@ -136,9 +151,9 @@ import java.util.concurrent.locks.LockSupport; *

    Sample usages: * *

    A {@code Phaser} may be used instead of a {@code CountDownLatch} - * to control a one-shot action serving a variable number of - * parties. The typical idiom is for the method setting this up to - * first register, then start the actions, then deregister, as in: + * to control a one-shot action serving a variable number of parties. + * The typical idiom is for the method setting this up to first + * register, then start the actions, then deregister, as in: * *

     {@code
      * void runTasks(List tasks) {
    @@ -208,34 +223,32 @@ import java.util.concurrent.locks.LockSupport;
      * }}
    * * - *

    To create a set of tasks using a tree of phasers, - * you could use code of the following form, assuming a - * Task class with a constructor accepting a phaser that - * it registers for upon construction: + *

    To create a set of {@code n} tasks using a tree of phasers, you + * could use code of the following form, assuming a Task class with a + * constructor accepting a {@code Phaser} that it registers with upon + * construction. After invocation of {@code build(new Task[n], 0, n, + * new Phaser())}, these tasks could then be started, for example by + * submitting to a pool: * *

     {@code
    - * void build(Task[] actions, int lo, int hi, Phaser ph) {
    + * void build(Task[] tasks, int lo, int hi, Phaser ph) {
      *   if (hi - lo > TASKS_PER_PHASER) {
      *     for (int i = lo; i < hi; i += TASKS_PER_PHASER) {
      *       int j = Math.min(i + TASKS_PER_PHASER, hi);
    - *       build(actions, i, j, new Phaser(ph));
    + *       build(tasks, i, j, new Phaser(ph));
      *     }
      *   } else {
      *     for (int i = lo; i < hi; ++i)
    - *       actions[i] = new Task(ph);
    + *       tasks[i] = new Task(ph);
      *       // assumes new Task(ph) performs ph.register()
      *   }
    - * }
    - * // .. initially called, for n tasks via
    - * build(new Task[n], 0, n, new Phaser());}
    + * }} * * The best value of {@code TASKS_PER_PHASER} depends mainly on - * expected barrier synchronization rates. A value as low as four may - * be appropriate for extremely small per-barrier task bodies (thus + * expected synchronization rates. A value as low as four may + * be appropriate for extremely small per-phase task bodies (thus * high rates), or up to hundreds for extremely large ones. * - * - * *

    Implementation notes: This implementation restricts the * maximum number of parties to 65535. Attempts to register additional * parties result in {@code IllegalStateException}. However, you can and @@ -253,60 +266,66 @@ public class Phaser { */ /** - * Barrier state representation. Conceptually, a barrier contains - * four values: + * Primary state representation, holding four bit-fields: + * + * unarrived -- the number of parties yet to hit barrier (bits 0-15) + * parties -- the number of parties to wait (bits 16-31) + * phase -- the generation of the barrier (bits 32-62) + * terminated -- set if barrier is terminated (bit 63 / sign) * - * * parties -- the number of parties to wait (16 bits) - * * unarrived -- the number of parties yet to hit barrier (16 bits) - * * phase -- the generation of the barrier (31 bits) - * * terminated -- set if barrier is terminated (1 bit) + * Except that a phaser with no registered parties is + * distinguished by the otherwise illegal state of having zero + * parties and one unarrived parties (encoded as EMPTY below). * - * However, to efficiently maintain atomicity, these values are - * packed into a single (atomic) long. Termination uses the sign - * bit of 32 bit representation of phase, so phase is set to -1 on - * termination. Good performance relies on keeping state decoding - * and encoding simple, and keeping race windows short. + * To efficiently maintain atomicity, these values are packed into + * a single (atomic) long. Good performance relies on keeping + * state decoding and encoding simple, and keeping race windows + * short. * - * Note: there are some cheats in arrive() that rely on unarrived - * count being lowest 16 bits. + * All state updates are performed via CAS except initial + * registration of a sub-phaser (i.e., one with a non-null + * parent). In this (relatively rare) case, we use built-in + * synchronization to lock while first registering with its + * parent. + * + * The phase of a subphaser is allowed to lag that of its + * ancestors until it is actually accessed -- see method + * reconcileState. */ private volatile long state; - private static final int ushortMask = 0xffff; - private static final int phaseMask = 0x7fffffff; + private static final int MAX_PARTIES = 0xffff; + private static final int MAX_PHASE = Integer.MAX_VALUE; + private static final int PARTIES_SHIFT = 16; + private static final int PHASE_SHIFT = 32; + private static final int UNARRIVED_MASK = 0xffff; // to mask ints + private static final long PARTIES_MASK = 0xffff0000L; // to mask longs + private static final long TERMINATION_BIT = 1L << 63; + + // some special values + private static final int ONE_ARRIVAL = 1; + private static final int ONE_PARTY = 1 << PARTIES_SHIFT; + private static final int EMPTY = 1; + + // The following unpacking methods are usually manually inlined private static int unarrivedOf(long s) { - return (int) (s & ushortMask); + int counts = (int)s; + return (counts == EMPTY) ? 0 : counts & UNARRIVED_MASK; } private static int partiesOf(long s) { - return ((int) s) >>> 16; + return (int)s >>> PARTIES_SHIFT; } private static int phaseOf(long s) { - return (int) (s >>> 32); + return (int)(s >>> PHASE_SHIFT); } private static int arrivedOf(long s) { - return partiesOf(s) - unarrivedOf(s); - } - - private static long stateFor(int phase, int parties, int unarrived) { - return ((((long) phase) << 32) | (((long) parties) << 16) | - (long) unarrived); - } - - private static long trippedStateFor(int phase, int parties) { - long lp = (long) parties; - return (((long) phase) << 32) | (lp << 16) | lp; - } - - /** - * Returns message string for bad bounds exceptions. - */ - private static String badBounds(int parties, int unarrived) { - return ("Attempt to set " + unarrived + - " unarrived of " + parties + " parties"); + int counts = (int)s; + return (counts == EMPTY) ? 0 : + (counts >>> PARTIES_SHIFT) - (counts & UNARRIVED_MASK); } /** @@ -315,70 +334,180 @@ public class Phaser { private final Phaser parent; /** - * The root of phaser tree. Equals this if not in a tree. Used to - * support faster state push-down. + * The root of phaser tree. Equals this if not in a tree. */ private final Phaser root; - // Wait queues - /** * Heads of Treiber stacks for waiting threads. To eliminate - * contention while releasing some threads while adding others, we + * contention when releasing some threads while adding others, we * use two of them, alternating across even and odd phases. + * Subphasers share queues with root to speed up releases. */ - private final AtomicReference evenQ = new AtomicReference(); - private final AtomicReference oddQ = new AtomicReference(); + private final AtomicReference evenQ; + private final AtomicReference oddQ; private AtomicReference queueFor(int phase) { return ((phase & 1) == 0) ? evenQ : oddQ; } /** - * Returns current state, first resolving lagged propagation from - * root if necessary. + * Returns message string for bounds exceptions on arrival. */ - private long getReconciledState() { - return (parent == null) ? state : reconcileState(); + private String badArrive(long s) { + return "Attempted arrival of unregistered party for " + + stateToString(s); } /** - * Recursively resolves state. + * Returns message string for bounds exceptions on registration. */ - private long reconcileState() { - Phaser p = parent; - long s = state; - if (p != null) { - while (unarrivedOf(s) == 0 && phaseOf(s) != phaseOf(root.state)) { - long parentState = p.getReconciledState(); - int parentPhase = phaseOf(parentState); - int phase = phaseOf(s = state); - if (phase != parentPhase) { - long next = trippedStateFor(parentPhase, partiesOf(s)); - if (casState(s, next)) { - releaseWaiters(phase); - s = next; + private String badRegister(long s) { + return "Attempt to register more than " + + MAX_PARTIES + " parties for " + stateToString(s); + } + + /** + * Main implementation for methods arrive and arriveAndDeregister. + * Manually tuned to speed up and minimize race windows for the + * common case of just decrementing unarrived field. + * + * @param deregister false for arrive, true for arriveAndDeregister + */ + private int doArrive(boolean deregister) { + int adj = deregister ? ONE_ARRIVAL|ONE_PARTY : ONE_ARRIVAL; + final Phaser root = this.root; + for (;;) { + long s = (root == this) ? state : reconcileState(); + int phase = (int)(s >>> PHASE_SHIFT); + int counts = (int)s; + int unarrived = (counts & UNARRIVED_MASK) - 1; + if (phase < 0) + return phase; + else if (counts == EMPTY || unarrived < 0) { + if (root == this || reconcileState() == s) + throw new IllegalStateException(badArrive(s)); + } + else if (UNSAFE.compareAndSwapLong(this, stateOffset, s, s-=adj)) { + if (unarrived == 0) { + long n = s & PARTIES_MASK; // base of next state + int nextUnarrived = (int)n >>> PARTIES_SHIFT; + if (root != this) + return parent.doArrive(nextUnarrived == 0); + if (onAdvance(phase, nextUnarrived)) + n |= TERMINATION_BIT; + else if (nextUnarrived == 0) + n |= EMPTY; + else + n |= nextUnarrived; + n |= (long)((phase + 1) & MAX_PHASE) << PHASE_SHIFT; + UNSAFE.compareAndSwapLong(this, stateOffset, s, n); + releaseWaiters(phase); + } + return phase; + } + } + } + + /** + * Implementation of register, bulkRegister + * + * @param registrations number to add to both parties and + * unarrived fields. Must be greater than zero. + */ + private int doRegister(int registrations) { + // adjustment to state + long adj = ((long)registrations << PARTIES_SHIFT) | registrations; + final Phaser parent = this.parent; + int phase; + for (;;) { + long s = state; + int counts = (int)s; + int parties = counts >>> PARTIES_SHIFT; + int unarrived = counts & UNARRIVED_MASK; + if (registrations > MAX_PARTIES - parties) + throw new IllegalStateException(badRegister(s)); + else if ((phase = (int)(s >>> PHASE_SHIFT)) < 0) + break; + else if (counts != EMPTY) { // not 1st registration + if (parent == null || reconcileState() == s) { + if (unarrived == 0) // wait out advance + root.internalAwaitAdvance(phase, null); + else if (UNSAFE.compareAndSwapLong(this, stateOffset, + s, s + adj)) + break; + } + } + else if (parent == null) { // 1st root registration + long next = ((long)phase << PHASE_SHIFT) | adj; + if (UNSAFE.compareAndSwapLong(this, stateOffset, s, next)) + break; + } + else { + synchronized (this) { // 1st sub registration + if (state == s) { // recheck under lock + parent.doRegister(1); + do { // force current phase + phase = (int)(root.state >>> PHASE_SHIFT); + // assert phase < 0 || (int)state == EMPTY; + } while (!UNSAFE.compareAndSwapLong + (this, stateOffset, state, + ((long)phase << PHASE_SHIFT) | adj)); + break; } } } } + return phase; + } + + /** + * Resolves lagged phase propagation from root if necessary. + * Reconciliation normally occurs when root has advanced but + * subphasers have not yet done so, in which case they must finish + * their own advance by setting unarrived to parties (or if + * parties is zero, resetting to unregistered EMPTY state). + * However, this method may also be called when "floating" + * subphasers with possibly some unarrived parties are merely + * catching up to current phase, in which case counts are + * unaffected. + * + * @return reconciled state + */ + private long reconcileState() { + final Phaser root = this.root; + long s = state; + if (root != this) { + int phase, u, p; + // CAS root phase with current parties; possibly trip unarrived + while ((phase = (int)(root.state >>> PHASE_SHIFT)) != + (int)(s >>> PHASE_SHIFT) && + !UNSAFE.compareAndSwapLong + (this, stateOffset, s, + s = (((long)phase << PHASE_SHIFT) | + (s & PARTIES_MASK) | + ((p = (int)s >>> PARTIES_SHIFT) == 0 ? EMPTY : + (u = (int)s & UNARRIVED_MASK) == 0 ? p : u)))) + s = state; + } return s; } /** - * Creates a new phaser without any initially registered parties, - * initial phase number 0, and no parent. Any thread using this + * Creates a new phaser with no initially registered parties, no + * parent, and initial phase number 0. Any thread using this * phaser will need to first register for it. */ public Phaser() { - this(null); + this(null, 0); } /** - * Creates a new phaser with the given numbers of registered - * unarrived parties, initial phase number 0, and no parent. + * Creates a new phaser with the given number of registered + * unarrived parties, no parent, and initial phase number 0. * - * @param parties the number of parties required to trip barrier + * @param parties the number of parties required to advance to the + * next phase * @throws IllegalArgumentException if parties less than zero * or greater than the maximum number of parties supported */ @@ -387,54 +516,62 @@ public class Phaser { } /** - * Creates a new phaser with the given parent, without any - * initially registered parties. If parent is non-null this phaser - * is registered with the parent and its initial phase number is - * the same as that of parent phaser. + * Equivalent to {@link #Phaser(Phaser, int) Phaser(parent, 0)}. * * @param parent the parent phaser */ public Phaser(Phaser parent) { - int phase = 0; - this.parent = parent; - if (parent != null) { - this.root = parent.root; - phase = parent.register(); - } - else - this.root = this; - this.state = trippedStateFor(phase, 0); + this(parent, 0); } /** - * Creates a new phaser with the given parent and numbers of - * registered unarrived parties. If parent is non-null, this phaser - * is registered with the parent and its initial phase number is - * the same as that of parent phaser. + * Creates a new phaser with the given parent and number of + * registered unarrived parties. When the given parent is non-null + * and the given number of parties is greater than zero, this + * child phaser is registered with its parent. * * @param parent the parent phaser - * @param parties the number of parties required to trip barrier + * @param parties the number of parties required to advance to the + * next phase * @throws IllegalArgumentException if parties less than zero * or greater than the maximum number of parties supported */ public Phaser(Phaser parent, int parties) { - if (parties < 0 || parties > ushortMask) + if (parties >>> PARTIES_SHIFT != 0) throw new IllegalArgumentException("Illegal number of parties"); int phase = 0; this.parent = parent; if (parent != null) { - this.root = parent.root; - phase = parent.register(); + final Phaser root = parent.root; + this.root = root; + this.evenQ = root.evenQ; + this.oddQ = root.oddQ; + if (parties != 0) + phase = parent.doRegister(1); } - else + else { this.root = this; - this.state = trippedStateFor(phase, parties); + this.evenQ = new AtomicReference(); + this.oddQ = new AtomicReference(); + } + this.state = (parties == 0) ? (long)EMPTY : + ((long)phase << PHASE_SHIFT) | + ((long)parties << PARTIES_SHIFT) | + ((long)parties); } /** - * Adds a new unarrived party to this phaser. + * Adds a new unarrived party to this phaser. If an ongoing + * invocation of {@link #onAdvance} is in progress, this method + * may await its completion before returning. If this phaser has + * a parent, and this phaser previously had no registered parties, + * this child phaser is also registered with its parent. If + * this phaser is terminated, the attempt to register has + * no effect, and a negative value is returned. * - * @return the arrival phase number to which this registration applied + * @return the arrival phase number to which this registration + * applied. If this value is negative, then this phaser has + * terminated, in which case registration has no effect. * @throws IllegalStateException if attempting to register more * than the maximum supported number of parties */ @@ -444,11 +581,22 @@ public class Phaser { /** * Adds the given number of new unarrived parties to this phaser. + * If an ongoing invocation of {@link #onAdvance} is in progress, + * this method may await its completion before returning. If this + * phaser has a parent, and the given number of parties is greater + * than zero, and this phaser previously had no registered + * parties, this child phaser is also registered with its parent. + * If this phaser is terminated, the attempt to register has no + * effect, and a negative value is returned. * - * @param parties the number of parties required to trip barrier - * @return the arrival phase number to which this registration applied + * @param parties the number of additional parties required to + * advance to the next phase + * @return the arrival phase number to which this registration + * applied. If this value is negative, then this phaser has + * terminated, in which case registration has no effect. * @throws IllegalStateException if attempting to register more * than the maximum supported number of parties + * @throws IllegalArgumentException if {@code parties < 0} */ public int bulkRegister(int parties) { if (parties < 0) @@ -459,258 +607,210 @@ public class Phaser { } /** - * Shared code for register, bulkRegister - */ - private int doRegister(int registrations) { - int phase; - for (;;) { - long s = getReconciledState(); - phase = phaseOf(s); - int unarrived = unarrivedOf(s) + registrations; - int parties = partiesOf(s) + registrations; - if (phase < 0) - break; - if (parties > ushortMask || unarrived > ushortMask) - throw new IllegalStateException(badBounds(parties, unarrived)); - if (phase == phaseOf(root.state) && - casState(s, stateFor(phase, parties, unarrived))) - break; - } - return phase; - } - - /** - * Arrives at the barrier, but does not wait for others. (You can - * in turn wait for others via {@link #awaitAdvance}). It is an - * unenforced usage error for an unregistered party to invoke this - * method. + * Arrives at this phaser, without waiting for others to arrive. + * + *

    It is a usage error for an unregistered party to invoke this + * method. However, this error may result in an {@code + * IllegalStateException} only upon some subsequent operation on + * this phaser, if ever. * * @return the arrival phase number, or a negative value if terminated * @throws IllegalStateException if not terminated and the number * of unarrived parties would become negative */ public int arrive() { - int phase; - for (;;) { - long s = state; - phase = phaseOf(s); - if (phase < 0) - break; - int parties = partiesOf(s); - int unarrived = unarrivedOf(s) - 1; - if (unarrived > 0) { // Not the last arrival - if (casState(s, s - 1)) // s-1 adds one arrival - break; - } - else if (unarrived == 0) { // the last arrival - Phaser par = parent; - if (par == null) { // directly trip - if (casState - (s, - trippedStateFor(onAdvance(phase, parties) ? -1 : - ((phase + 1) & phaseMask), parties))) { - releaseWaiters(phase); - break; - } - } - else { // cascade to parent - if (casState(s, s - 1)) { // zeroes unarrived - par.arrive(); - reconcileState(); - break; - } - } - } - else if (phase != phaseOf(root.state)) // or if unreconciled - reconcileState(); - else - throw new IllegalStateException(badBounds(parties, unarrived)); - } - return phase; + return doArrive(false); } /** - * Arrives at the barrier and deregisters from it without waiting - * for others. Deregistration reduces the number of parties - * required to trip the barrier in future phases. If this phaser + * Arrives at this phaser and deregisters from it without waiting + * for others to arrive. Deregistration reduces the number of + * parties required to advance in future phases. If this phaser * has a parent, and deregistration causes this phaser to have - * zero parties, this phaser also arrives at and is deregistered - * from its parent. It is an unenforced usage error for an - * unregistered party to invoke this method. + * zero parties, this phaser is also deregistered from its parent. + * + *

    It is a usage error for an unregistered party to invoke this + * method. However, this error may result in an {@code + * IllegalStateException} only upon some subsequent operation on + * this phaser, if ever. * * @return the arrival phase number, or a negative value if terminated * @throws IllegalStateException if not terminated and the number * of registered or unarrived parties would become negative */ public int arriveAndDeregister() { - // similar code to arrive, but too different to merge - Phaser par = parent; - int phase; - for (;;) { - long s = state; - phase = phaseOf(s); - if (phase < 0) - break; - int parties = partiesOf(s) - 1; - int unarrived = unarrivedOf(s) - 1; - if (parties >= 0) { - if (unarrived > 0 || (unarrived == 0 && par != null)) { - if (casState - (s, - stateFor(phase, parties, unarrived))) { - if (unarrived == 0) { - par.arriveAndDeregister(); - reconcileState(); - } - break; - } - continue; - } - if (unarrived == 0) { - if (casState - (s, - trippedStateFor(onAdvance(phase, parties) ? -1 : - ((phase + 1) & phaseMask), parties))) { - releaseWaiters(phase); - break; - } - continue; - } - if (par != null && phase != phaseOf(root.state)) { - reconcileState(); - continue; - } - } - throw new IllegalStateException(badBounds(parties, unarrived)); - } - return phase; + return doArrive(true); } /** - * Arrives at the barrier and awaits others. Equivalent in effect + * Arrives at this phaser and awaits others. Equivalent in effect * to {@code awaitAdvance(arrive())}. If you need to await with * interruption or timeout, you can arrange this with an analogous - * construction using one of the other forms of the awaitAdvance - * method. If instead you need to deregister upon arrival use - * {@code arriveAndDeregister}. It is an unenforced usage error - * for an unregistered party to invoke this method. + * construction using one of the other forms of the {@code + * awaitAdvance} method. If instead you need to deregister upon + * arrival, use {@code awaitAdvance(arriveAndDeregister())}. + * + *

    It is a usage error for an unregistered party to invoke this + * method. However, this error may result in an {@code + * IllegalStateException} only upon some subsequent operation on + * this phaser, if ever. * - * @return the arrival phase number, or a negative number if terminated + * @return the arrival phase number, or the (negative) + * {@linkplain #getPhase() current phase} if terminated * @throws IllegalStateException if not terminated and the number * of unarrived parties would become negative */ public int arriveAndAwaitAdvance() { - return awaitAdvance(arrive()); + // Specialization of doArrive+awaitAdvance eliminating some reads/paths + final Phaser root = this.root; + for (;;) { + long s = (root == this) ? state : reconcileState(); + int phase = (int)(s >>> PHASE_SHIFT); + int counts = (int)s; + int unarrived = (counts & UNARRIVED_MASK) - 1; + if (phase < 0) + return phase; + else if (counts == EMPTY || unarrived < 0) { + if (reconcileState() == s) + throw new IllegalStateException(badArrive(s)); + } + else if (UNSAFE.compareAndSwapLong(this, stateOffset, s, + s -= ONE_ARRIVAL)) { + if (unarrived != 0) + return root.internalAwaitAdvance(phase, null); + if (root != this) + return parent.arriveAndAwaitAdvance(); + long n = s & PARTIES_MASK; // base of next state + int nextUnarrived = (int)n >>> PARTIES_SHIFT; + if (onAdvance(phase, nextUnarrived)) + n |= TERMINATION_BIT; + else if (nextUnarrived == 0) + n |= EMPTY; + else + n |= nextUnarrived; + int nextPhase = (phase + 1) & MAX_PHASE; + n |= (long)nextPhase << PHASE_SHIFT; + if (!UNSAFE.compareAndSwapLong(this, stateOffset, s, n)) + return (int)(state >>> PHASE_SHIFT); // terminated + releaseWaiters(phase); + return nextPhase; + } + } } /** - * Awaits the phase of the barrier to advance from the given phase - * value, returning immediately if the current phase of the - * barrier is not equal to the given phase value or this barrier - * is terminated. It is an unenforced usage error for an - * unregistered party to invoke this method. + * Awaits the phase of this phaser to advance from the given phase + * value, returning immediately if the current phase is not equal + * to the given phase value or this phaser is terminated. * * @param phase an arrival phase number, or negative value if * terminated; this argument is normally the value returned by a - * previous call to {@code arrive} or its variants - * @return the next arrival phase number, or a negative value - * if terminated or argument is negative + * previous call to {@code arrive} or {@code arriveAndDeregister}. + * @return the next arrival phase number, or the argument if it is + * negative, or the (negative) {@linkplain #getPhase() current phase} + * if terminated */ public int awaitAdvance(int phase) { + final Phaser root = this.root; + long s = (root == this) ? state : reconcileState(); + int p = (int)(s >>> PHASE_SHIFT); if (phase < 0) return phase; - long s = getReconciledState(); - int p = phaseOf(s); - if (p != phase) - return p; - if (unarrivedOf(s) == 0 && parent != null) - parent.awaitAdvance(phase); - // Fall here even if parent waited, to reconcile and help release - return untimedWait(phase); + if (p == phase) + return root.internalAwaitAdvance(phase, null); + return p; } /** - * Awaits the phase of the barrier to advance from the given phase + * Awaits the phase of this phaser to advance from the given phase * value, throwing {@code InterruptedException} if interrupted - * while waiting, or returning immediately if the current phase of - * the barrier is not equal to the given phase value or this - * barrier is terminated. It is an unenforced usage error for an - * unregistered party to invoke this method. + * while waiting, or returning immediately if the current phase is + * not equal to the given phase value or this phaser is + * terminated. * * @param phase an arrival phase number, or negative value if * terminated; this argument is normally the value returned by a - * previous call to {@code arrive} or its variants - * @return the next arrival phase number, or a negative value - * if terminated or argument is negative + * previous call to {@code arrive} or {@code arriveAndDeregister}. + * @return the next arrival phase number, or the argument if it is + * negative, or the (negative) {@linkplain #getPhase() current phase} + * if terminated * @throws InterruptedException if thread interrupted while waiting */ public int awaitAdvanceInterruptibly(int phase) throws InterruptedException { + final Phaser root = this.root; + long s = (root == this) ? state : reconcileState(); + int p = (int)(s >>> PHASE_SHIFT); if (phase < 0) return phase; - long s = getReconciledState(); - int p = phaseOf(s); - if (p != phase) - return p; - if (unarrivedOf(s) == 0 && parent != null) - parent.awaitAdvanceInterruptibly(phase); - return interruptibleWait(phase); + if (p == phase) { + QNode node = new QNode(this, phase, true, false, 0L); + p = root.internalAwaitAdvance(phase, node); + if (node.wasInterrupted) + throw new InterruptedException(); + } + return p; } /** - * Awaits the phase of the barrier to advance from the given phase + * Awaits the phase of this phaser to advance from the given phase * value or the given timeout to elapse, throwing {@code * InterruptedException} if interrupted while waiting, or - * returning immediately if the current phase of the barrier is - * not equal to the given phase value or this barrier is - * terminated. It is an unenforced usage error for an - * unregistered party to invoke this method. + * returning immediately if the current phase is not equal to the + * given phase value or this phaser is terminated. * * @param phase an arrival phase number, or negative value if * terminated; this argument is normally the value returned by a - * previous call to {@code arrive} or its variants + * previous call to {@code arrive} or {@code arriveAndDeregister}. * @param timeout how long to wait before giving up, in units of * {@code unit} * @param unit a {@code TimeUnit} determining how to interpret the * {@code timeout} parameter - * @return the next arrival phase number, or a negative value - * if terminated or argument is negative + * @return the next arrival phase number, or the argument if it is + * negative, or the (negative) {@linkplain #getPhase() current phase} + * if terminated * @throws InterruptedException if thread interrupted while waiting * @throws TimeoutException if timed out while waiting */ public int awaitAdvanceInterruptibly(int phase, long timeout, TimeUnit unit) throws InterruptedException, TimeoutException { + long nanos = unit.toNanos(timeout); + final Phaser root = this.root; + long s = (root == this) ? state : reconcileState(); + int p = (int)(s >>> PHASE_SHIFT); if (phase < 0) return phase; - long s = getReconciledState(); - int p = phaseOf(s); - if (p != phase) - return p; - if (unarrivedOf(s) == 0 && parent != null) - parent.awaitAdvanceInterruptibly(phase, timeout, unit); - return timedWait(phase, unit.toNanos(timeout)); + if (p == phase) { + QNode node = new QNode(this, phase, true, true, nanos); + p = root.internalAwaitAdvance(phase, node); + if (node.wasInterrupted) + throw new InterruptedException(); + else if (p == phase) + throw new TimeoutException(); + } + return p; } /** - * Forces this barrier to enter termination state. Counts of - * arrived and registered parties are unaffected. If this phaser - * has a parent, it too is terminated. This method may be useful - * for coordinating recovery after one or more tasks encounter + * Forces this phaser to enter termination state. Counts of + * registered parties are unaffected. If this phaser is a member + * of a tiered set of phasers, then all of the phasers in the set + * are terminated. If this phaser is already terminated, this + * method has no effect. This method may be useful for + * coordinating recovery after one or more tasks encounter * unexpected exceptions. */ public void forceTermination() { - for (;;) { - long s = getReconciledState(); - int phase = phaseOf(s); - int parties = partiesOf(s); - int unarrived = unarrivedOf(s); - if (phase < 0 || - casState(s, stateFor(-1, parties, unarrived))) { + // Only need to change root state + final Phaser root = this.root; + long s; + while ((s = root.state) >= 0) { + if (UNSAFE.compareAndSwapLong(root, stateOffset, + s, s | TERMINATION_BIT)) { + // signal all threads releaseWaiters(0); releaseWaiters(1); - if (parent != null) - parent.forceTermination(); return; } } @@ -719,16 +819,18 @@ public class Phaser { /** * Returns the current phase number. The maximum phase number is * {@code Integer.MAX_VALUE}, after which it restarts at - * zero. Upon termination, the phase number is negative. + * zero. Upon termination, the phase number is negative, + * in which case the prevailing phase prior to termination + * may be obtained via {@code getPhase() + Integer.MIN_VALUE}. * * @return the phase number, or a negative value if terminated */ public final int getPhase() { - return phaseOf(getReconciledState()); + return (int)(root.state >>> PHASE_SHIFT); } /** - * Returns the number of parties registered at this barrier. + * Returns the number of parties registered at this phaser. * * @return the number of parties */ @@ -738,22 +840,24 @@ public class Phaser { /** * Returns the number of registered parties that have arrived at - * the current phase of this barrier. + * the current phase of this phaser. If this phaser has terminated, + * the returned value is meaningless and arbitrary. * * @return the number of arrived parties */ public int getArrivedParties() { - return arrivedOf(state); + return arrivedOf(reconcileState()); } /** * Returns the number of registered parties that have not yet - * arrived at the current phase of this barrier. + * arrived at the current phase of this phaser. If this phaser has + * terminated, the returned value is meaningless and arbitrary. * * @return the number of unarrived parties */ public int getUnarrivedParties() { - return unarrivedOf(state); + return unarrivedOf(reconcileState()); } /** @@ -776,52 +880,56 @@ public class Phaser { } /** - * Returns {@code true} if this barrier has been terminated. + * Returns {@code true} if this phaser has been terminated. * - * @return {@code true} if this barrier has been terminated + * @return {@code true} if this phaser has been terminated */ public boolean isTerminated() { - return getPhase() < 0; + return root.state < 0L; } /** * Overridable method to perform an action upon impending phase * advance, and to control termination. This method is invoked - * upon arrival of the party tripping the barrier (when all other + * upon arrival of the party advancing this phaser (when all other * waiting parties are dormant). If this method returns {@code - * true}, then, rather than advance the phase number, this barrier - * will be set to a final termination state, and subsequent calls - * to {@link #isTerminated} will return true. Any (unchecked) - * Exception or Error thrown by an invocation of this method is - * propagated to the party attempting to trip the barrier, in - * which case no advance occurs. + * true}, this phaser will be set to a final termination state + * upon advance, and subsequent calls to {@link #isTerminated} + * will return true. Any (unchecked) Exception or Error thrown by + * an invocation of this method is propagated to the party + * attempting to advance this phaser, in which case no advance + * occurs. * *

    The arguments to this method provide the state of the phaser - * prevailing for the current transition. (When called from within - * an implementation of {@code onAdvance} the values returned by - * methods such as {@code getPhase} may or may not reliably - * indicate the state to which this transition applies.) + * prevailing for the current transition. The effects of invoking + * arrival, registration, and waiting methods on this phaser from + * within {@code onAdvance} are unspecified and should not be + * relied on. + * + *

    If this phaser is a member of a tiered set of phasers, then + * {@code onAdvance} is invoked only for its root phaser on each + * advance. * - *

    The default version returns {@code true} when the number of - * registered parties is zero. Normally, overrides that arrange - * termination for other reasons should also preserve this - * property. + *

    To support the most common use cases, the default + * implementation of this method returns {@code true} when the + * number of registered parties has become zero as the result of a + * party invoking {@code arriveAndDeregister}. You can disable + * this behavior, thus enabling continuation upon future + * registrations, by overriding this method to always return + * {@code false}: * - *

    You may override this method to perform an action with side - * effects visible to participating tasks, but it is only sensible - * to do so in designs where all parties register before any - * arrive, and all {@link #awaitAdvance} at each phase. - * Otherwise, you cannot ensure lack of interference from other - * parties during the invocation of this method. Additionally, - * method {@code onAdvance} may be invoked more than once per - * transition if registrations are intermixed with arrivals. + *

     {@code
    +     * Phaser phaser = new Phaser() {
    +     *   protected boolean onAdvance(int phase, int parties) { return false; }
    +     * }}
    * - * @param phase the phase number on entering the barrier + * @param phase the current phase number on entry to this method, + * before this phaser is advanced * @param registeredParties the current number of registered parties - * @return {@code true} if this barrier should terminate + * @return {@code true} if this phaser should terminate */ protected boolean onAdvance(int phase, int registeredParties) { - return registeredParties <= 0; + return registeredParties == 0; } /** @@ -831,192 +939,200 @@ public class Phaser { * followed by the number of registered parties, and {@code * "arrived = "} followed by the number of arrived parties. * - * @return a string identifying this barrier, as well as its state + * @return a string identifying this phaser, as well as its state */ public String toString() { - long s = getReconciledState(); + return stateToString(reconcileState()); + } + + /** + * Implementation of toString and string-based error messages + */ + private String stateToString(long s) { return super.toString() + "[phase = " + phaseOf(s) + " parties = " + partiesOf(s) + " arrived = " + arrivedOf(s) + "]"; } - // methods for waiting + // Waiting mechanics /** - * Wait nodes for Treiber stack representing wait queue + * Removes and signals threads from queue for phase. */ - static final class QNode implements ForkJoinPool.ManagedBlocker { - final Phaser phaser; - final int phase; - final long startTime; - final long nanos; - final boolean timed; - final boolean interruptible; - volatile boolean wasInterrupted = false; - volatile Thread thread; // nulled to cancel wait - QNode next; - QNode(Phaser phaser, int phase, boolean interruptible, - boolean timed, long startTime, long nanos) { - this.phaser = phaser; - this.phase = phase; - this.timed = timed; - this.interruptible = interruptible; - this.startTime = startTime; - this.nanos = nanos; - thread = Thread.currentThread(); - } - public boolean isReleasable() { - return (thread == null || - phaser.getPhase() != phase || - (interruptible && wasInterrupted) || - (timed && (nanos - (System.nanoTime() - startTime)) <= 0)); - } - public boolean block() { - if (Thread.interrupted()) { - wasInterrupted = true; - if (interruptible) - return true; - } - if (!timed) - LockSupport.park(this); - else { - long waitTime = nanos - (System.nanoTime() - startTime); - if (waitTime <= 0) - return true; - LockSupport.parkNanos(this, waitTime); - } - return isReleasable(); - } - void signal() { - Thread t = thread; - if (t != null) { - thread = null; + private void releaseWaiters(int phase) { + QNode q; // first element of queue + Thread t; // its thread + AtomicReference head = (phase & 1) == 0 ? evenQ : oddQ; + while ((q = head.get()) != null && + q.phase != (int)(root.state >>> PHASE_SHIFT)) { + if (head.compareAndSet(q, q.next) && + (t = q.thread) != null) { + q.thread = null; LockSupport.unpark(t); } } - boolean doWait() { - if (thread != null) { - try { - ForkJoinPool.managedBlock(this); - } catch (InterruptedException ie) { - } - } - return wasInterrupted; - } - } /** - * Removes and signals waiting threads from wait queue. + * Variant of releaseWaiters that additionally tries to remove any + * nodes no longer waiting for advance due to timeout or + * interrupt. Currently, nodes are removed only if they are at + * head of queue, which suffices to reduce memory footprint in + * most usages. + * + * @return current phase on exit */ - private void releaseWaiters(int phase) { - AtomicReference head = queueFor(phase); - QNode q; - while ((q = head.get()) != null) { - if (head.compareAndSet(q, q.next)) - q.signal(); + private int abortWait(int phase) { + AtomicReference head = (phase & 1) == 0 ? evenQ : oddQ; + for (;;) { + Thread t; + QNode q = head.get(); + int p = (int)(root.state >>> PHASE_SHIFT); + if (q == null || ((t = q.thread) != null && q.phase == p)) + return p; + if (head.compareAndSet(q, q.next) && t != null) { + q.thread = null; + LockSupport.unpark(t); + } } } + /** The number of CPUs, for spin control */ + private static final int NCPU = Runtime.getRuntime().availableProcessors(); + /** - * Tries to enqueue given node in the appropriate wait queue. - * - * @return true if successful + * The number of times to spin before blocking while waiting for + * advance, per arrival while waiting. On multiprocessors, fully + * blocking and waking up a large number of threads all at once is + * usually a very slow process, so we use rechargeable spins to + * avoid it when threads regularly arrive: When a thread in + * internalAwaitAdvance notices another arrival before blocking, + * and there appear to be enough CPUs available, it spins + * SPINS_PER_ARRIVAL more times before blocking. The value trades + * off good-citizenship vs big unnecessary slowdowns. */ - private boolean tryEnqueue(QNode node) { - AtomicReference head = queueFor(node.phase); - return head.compareAndSet(node.next = head.get(), node); - } + static final int SPINS_PER_ARRIVAL = (NCPU < 2) ? 1 : 1 << 8; /** - * Enqueues node and waits unless aborted or signalled. + * Possibly blocks and waits for phase to advance unless aborted. + * Call only from root node. * + * @param phase current phase + * @param node if non-null, the wait node to track interrupt and timeout; + * if null, denotes noninterruptible wait * @return current phase */ - private int untimedWait(int phase) { - QNode node = null; - boolean queued = false; - boolean interrupted = false; + private int internalAwaitAdvance(int phase, QNode node) { + releaseWaiters(phase-1); // ensure old queue clean + boolean queued = false; // true when node is enqueued + int lastUnarrived = 0; // to increase spins upon change + int spins = SPINS_PER_ARRIVAL; + long s; int p; - while ((p = getPhase()) == phase) { - if (Thread.interrupted()) - interrupted = true; - else if (node == null) - node = new QNode(this, phase, false, false, 0, 0); - else if (!queued) - queued = tryEnqueue(node); - else - interrupted = node.doWait(); + while ((p = (int)((s = state) >>> PHASE_SHIFT)) == phase) { + if (node == null) { // spinning in noninterruptible mode + int unarrived = (int)s & UNARRIVED_MASK; + if (unarrived != lastUnarrived && + (lastUnarrived = unarrived) < NCPU) + spins += SPINS_PER_ARRIVAL; + boolean interrupted = Thread.interrupted(); + if (interrupted || --spins < 0) { // need node to record intr + node = new QNode(this, phase, false, false, 0L); + node.wasInterrupted = interrupted; + } + } + else if (node.isReleasable()) // done or aborted + break; + else if (!queued) { // push onto queue + AtomicReference head = (phase & 1) == 0 ? evenQ : oddQ; + QNode q = node.next = head.get(); + if ((q == null || q.phase == phase) && + (int)(state >>> PHASE_SHIFT) == phase) // avoid stale enq + queued = head.compareAndSet(q, node); + } + else { + try { + ForkJoinPool.managedBlock(node); + } catch (InterruptedException ie) { + node.wasInterrupted = true; + } + } + } + + if (node != null) { + if (node.thread != null) + node.thread = null; // avoid need for unpark() + if (node.wasInterrupted && !node.interruptible) + Thread.currentThread().interrupt(); + if (p == phase && (p = (int)(state >>> PHASE_SHIFT)) == phase) + return abortWait(phase); // possibly clean up on abort } - if (node != null) - node.thread = null; releaseWaiters(phase); - if (interrupted) - Thread.currentThread().interrupt(); return p; } /** - * Interruptible version - * @return current phase + * Wait nodes for Treiber stack representing wait queue */ - private int interruptibleWait(int phase) throws InterruptedException { - QNode node = null; - boolean queued = false; - boolean interrupted = false; - int p; - while ((p = getPhase()) == phase && !interrupted) { - if (Thread.interrupted()) - interrupted = true; - else if (node == null) - node = new QNode(this, phase, true, false, 0, 0); - else if (!queued) - queued = tryEnqueue(node); - else - interrupted = node.doWait(); + static final class QNode implements ForkJoinPool.ManagedBlocker { + final Phaser phaser; + final int phase; + final boolean interruptible; + final boolean timed; + boolean wasInterrupted; + long nanos; + long lastTime; + volatile Thread thread; // nulled to cancel wait + QNode next; + + QNode(Phaser phaser, int phase, boolean interruptible, + boolean timed, long nanos) { + this.phaser = phaser; + this.phase = phase; + this.interruptible = interruptible; + this.nanos = nanos; + this.timed = timed; + this.lastTime = timed ? System.nanoTime() : 0L; + thread = Thread.currentThread(); } - if (node != null) - node.thread = null; - if (p != phase || (p = getPhase()) != phase) - releaseWaiters(phase); - if (interrupted) - throw new InterruptedException(); - return p; - } - /** - * Timeout version. - * @return current phase - */ - private int timedWait(int phase, long nanos) - throws InterruptedException, TimeoutException { - long startTime = System.nanoTime(); - QNode node = null; - boolean queued = false; - boolean interrupted = false; - int p; - while ((p = getPhase()) == phase && !interrupted) { + public boolean isReleasable() { + if (thread == null) + return true; + if (phaser.getPhase() != phase) { + thread = null; + return true; + } if (Thread.interrupted()) - interrupted = true; - else if (nanos - (System.nanoTime() - startTime) <= 0) - break; - else if (node == null) - node = new QNode(this, phase, true, true, startTime, nanos); - else if (!queued) - queued = tryEnqueue(node); - else - interrupted = node.doWait(); + wasInterrupted = true; + if (wasInterrupted && interruptible) { + thread = null; + return true; + } + if (timed) { + if (nanos > 0L) { + long now = System.nanoTime(); + nanos -= now - lastTime; + lastTime = now; + } + if (nanos <= 0L) { + thread = null; + return true; + } + } + return false; + } + + public boolean block() { + if (isReleasable()) + return true; + else if (!timed) + LockSupport.park(this); + else if (nanos > 0) + LockSupport.parkNanos(this, nanos); + return isReleasable(); } - if (node != null) - node.thread = null; - if (p != phase || (p = getPhase()) != phase) - releaseWaiters(phase); - if (interrupted) - throw new InterruptedException(); - if (p == phase) - throw new TimeoutException(); - return p; } // Unsafe mechanics @@ -1025,10 +1141,6 @@ public class Phaser { private static final long stateOffset = objectFieldOffset("state", Phaser.class); - private final boolean casState(long cmp, long val) { - return UNSAFE.compareAndSwapLong(this, stateOffset, cmp, val); - } - private static long objectFieldOffset(String field, Class klazz) { try { return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field)); diff --git a/src/share/classes/java/util/concurrent/PriorityBlockingQueue.java b/src/share/classes/java/util/concurrent/PriorityBlockingQueue.java index fec463e3d38d0c20eb3b0ada9b63a01f32508973..60928ac8a74304e623f4d79542184c48a6adad33 100644 --- a/src/share/classes/java/util/concurrent/PriorityBlockingQueue.java +++ b/src/share/classes/java/util/concurrent/PriorityBlockingQueue.java @@ -43,11 +43,11 @@ import java.util.*; * the same ordering rules as class {@link PriorityQueue} and supplies * blocking retrieval operations. While this queue is logically * unbounded, attempted additions may fail due to resource exhaustion - * (causing OutOfMemoryError). This class does not permit - * null elements. A priority queue relying on {@linkplain + * (causing {@code OutOfMemoryError}). This class does not permit + * {@code null} elements. A priority queue relying on {@linkplain * Comparable natural ordering} also does not permit insertion of * non-comparable objects (doing so results in - * ClassCastException). + * {@code ClassCastException}). * *

    This class and its iterator implement all of the * optional methods of the {@link Collection} and {@link @@ -55,7 +55,7 @@ import java.util.*; * #iterator()} is not guaranteed to traverse the elements of * the PriorityBlockingQueue in any particular order. If you need * ordered traversal, consider using - * Arrays.sort(pq.toArray()). Also, method drainTo + * {@code Arrays.sort(pq.toArray())}. Also, method {@code drainTo} * can be used to remove some or all elements in priority * order and place them in another collection. * @@ -65,12 +65,12 @@ import java.util.*; * secondary key to break ties in primary priority values. For * example, here is a class that applies first-in-first-out * tie-breaking to comparable elements. To use it, you would insert a - * new FIFOEntry(anEntry) instead of a plain entry object. + * {@code new FIFOEntry(anEntry)} instead of a plain entry object. * - *

    - * class FIFOEntry<E extends Comparable<? super E>>
    - *     implements Comparable<FIFOEntry<E>> {
    - *   final static AtomicLong seq = new AtomicLong();
    + *  
     {@code
    + * class FIFOEntry>
    + *     implements Comparable> {
    + *   static final AtomicLong seq = new AtomicLong(0);
      *   final long seqNum;
      *   final E entry;
      *   public FIFOEntry(E entry) {
    @@ -78,13 +78,13 @@ import java.util.*;
      *     this.entry = entry;
      *   }
      *   public E getEntry() { return entry; }
    - *   public int compareTo(FIFOEntry<E> other) {
    + *   public int compareTo(FIFOEntry other) {
      *     int res = entry.compareTo(other.entry);
    - *     if (res == 0 && other.entry != this.entry)
    - *       res = (seqNum < other.seqNum ? -1 : 1);
    + *     if (res == 0 && other.entry != this.entry)
    + *       res = (seqNum < other.seqNum ? -1 : 1);
      *     return res;
      *   }
    - * }
    + * }}
    * *

    This class is a member of the * @@ -98,34 +98,102 @@ public class PriorityBlockingQueue extends AbstractQueue implements BlockingQueue, java.io.Serializable { private static final long serialVersionUID = 5595510919245408276L; - private final PriorityQueue q; - private final ReentrantLock lock = new ReentrantLock(true); - private final Condition notEmpty = lock.newCondition(); + /* + * The implementation uses an array-based binary heap, with public + * operations protected with a single lock. However, allocation + * during resizing uses a simple spinlock (used only while not + * holding main lock) in order to allow takes to operate + * concurrently with allocation. This avoids repeated + * postponement of waiting consumers and consequent element + * build-up. The need to back away from lock during allocation + * makes it impossible to simply wrap delegated + * java.util.PriorityQueue operations within a lock, as was done + * in a previous version of this class. To maintain + * interoperability, a plain PriorityQueue is still used during + * serialization, which maintains compatibility at the espense of + * transiently doubling overhead. + */ + + /** + * Default array capacity. + */ + private static final int DEFAULT_INITIAL_CAPACITY = 11; + + /** + * The maximum size of array to allocate. + * Some VMs reserve some header words in an array. + * Attempts to allocate larger arrays may result in + * OutOfMemoryError: Requested array size exceeds VM limit + */ + private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; + + /** + * Priority queue represented as a balanced binary heap: the two + * children of queue[n] are queue[2*n+1] and queue[2*(n+1)]. The + * priority queue is ordered by comparator, or by the elements' + * natural ordering, if comparator is null: For each node n in the + * heap and each descendant d of n, n <= d. The element with the + * lowest value is in queue[0], assuming the queue is nonempty. + */ + private transient Object[] queue; + + /** + * The number of elements in the priority queue. + */ + private transient int size; + + /** + * The comparator, or null if priority queue uses elements' + * natural ordering. + */ + private transient Comparator comparator; /** - * Creates a PriorityBlockingQueue with the default + * Lock used for all public operations + */ + private final ReentrantLock lock; + + /** + * Condition for blocking when empty + */ + private final Condition notEmpty; + + /** + * Spinlock for allocation, acquired via CAS. + */ + private transient volatile int allocationSpinLock; + + /** + * A plain PriorityQueue used only for serialization, + * to maintain compatibility with previous versions + * of this class. Non-null only during serialization/deserialization. + */ + private PriorityQueue q; + + /** + * Creates a {@code PriorityBlockingQueue} with the default * initial capacity (11) that orders its elements according to * their {@linkplain Comparable natural ordering}. */ public PriorityBlockingQueue() { - q = new PriorityQueue(); + this(DEFAULT_INITIAL_CAPACITY, null); } /** - * Creates a PriorityBlockingQueue with the specified + * Creates a {@code PriorityBlockingQueue} with the specified * initial capacity that orders its elements according to their * {@linkplain Comparable natural ordering}. * * @param initialCapacity the initial capacity for this priority queue - * @throws IllegalArgumentException if initialCapacity is less + * @throws IllegalArgumentException if {@code initialCapacity} is less * than 1 */ public PriorityBlockingQueue(int initialCapacity) { - q = new PriorityQueue(initialCapacity, null); + this(initialCapacity, null); } /** - * Creates a PriorityBlockingQueue with the specified initial + * Creates a {@code PriorityBlockingQueue} with the specified initial * capacity that orders its elements according to the specified * comparator. * @@ -133,16 +201,21 @@ public class PriorityBlockingQueue extends AbstractQueue * @param comparator the comparator that will be used to order this * priority queue. If {@code null}, the {@linkplain Comparable * natural ordering} of the elements will be used. - * @throws IllegalArgumentException if initialCapacity is less + * @throws IllegalArgumentException if {@code initialCapacity} is less * than 1 */ public PriorityBlockingQueue(int initialCapacity, Comparator comparator) { - q = new PriorityQueue(initialCapacity, comparator); + if (initialCapacity < 1) + throw new IllegalArgumentException(); + this.lock = new ReentrantLock(); + this.notEmpty = lock.newCondition(); + this.comparator = comparator; + this.queue = new Object[initialCapacity]; } /** - * Creates a PriorityBlockingQueue containing the elements + * Creates a {@code PriorityBlockingQueue} containing the elements * in the specified collection. If the specified collection is a * {@link SortedSet} or a {@link PriorityQueue}, this * priority queue will be ordered according to the same ordering. @@ -158,14 +231,215 @@ public class PriorityBlockingQueue extends AbstractQueue * of its elements are null */ public PriorityBlockingQueue(Collection c) { - q = new PriorityQueue(c); + this.lock = new ReentrantLock(); + this.notEmpty = lock.newCondition(); + boolean heapify = true; // true if not known to be in heap order + boolean screen = true; // true if must screen for nulls + if (c instanceof SortedSet) { + SortedSet ss = (SortedSet) c; + this.comparator = (Comparator) ss.comparator(); + heapify = false; + } + else if (c instanceof PriorityBlockingQueue) { + PriorityBlockingQueue pq = + (PriorityBlockingQueue) c; + this.comparator = (Comparator) pq.comparator(); + screen = false; + if (pq.getClass() == PriorityBlockingQueue.class) // exact match + heapify = false; + } + Object[] a = c.toArray(); + int n = a.length; + // If c.toArray incorrectly doesn't return Object[], copy it. + if (a.getClass() != Object[].class) + a = Arrays.copyOf(a, n, Object[].class); + if (screen && (n == 1 || this.comparator != null)) { + for (int i = 0; i < n; ++i) + if (a[i] == null) + throw new NullPointerException(); + } + this.queue = a; + this.size = n; + if (heapify) + heapify(); + } + + /** + * Tries to grow array to accommodate at least one more element + * (but normally expand by about 50%), giving up (allowing retry) + * on contention (which we expect to be rare). Call only while + * holding lock. + * + * @param array the heap array + * @param oldCap the length of the array + */ + private void tryGrow(Object[] array, int oldCap) { + lock.unlock(); // must release and then re-acquire main lock + Object[] newArray = null; + if (allocationSpinLock == 0 && + UNSAFE.compareAndSwapInt(this, allocationSpinLockOffset, + 0, 1)) { + try { + int newCap = oldCap + ((oldCap < 64) ? + (oldCap + 2) : // grow faster if small + (oldCap >> 1)); + if (newCap - MAX_ARRAY_SIZE > 0) { // possible overflow + int minCap = oldCap + 1; + if (minCap < 0 || minCap > MAX_ARRAY_SIZE) + throw new OutOfMemoryError(); + newCap = MAX_ARRAY_SIZE; + } + if (newCap > oldCap && queue == array) + newArray = new Object[newCap]; + } finally { + allocationSpinLock = 0; + } + } + if (newArray == null) // back off if another thread is allocating + Thread.yield(); + lock.lock(); + if (newArray != null && queue == array) { + queue = newArray; + System.arraycopy(array, 0, newArray, 0, oldCap); + } + } + + /** + * Mechanics for poll(). Call only while holding lock. + */ + private E extract() { + E result; + int n = size - 1; + if (n < 0) + result = null; + else { + Object[] array = queue; + result = (E) array[0]; + E x = (E) array[n]; + array[n] = null; + Comparator cmp = comparator; + if (cmp == null) + siftDownComparable(0, x, array, n); + else + siftDownUsingComparator(0, x, array, n, cmp); + size = n; + } + return result; + } + + /** + * Inserts item x at position k, maintaining heap invariant by + * promoting x up the tree until it is greater than or equal to + * its parent, or is the root. + * + * To simplify and speed up coercions and comparisons. the + * Comparable and Comparator versions are separated into different + * methods that are otherwise identical. (Similarly for siftDown.) + * These methods are static, with heap state as arguments, to + * simplify use in light of possible comparator exceptions. + * + * @param k the position to fill + * @param x the item to insert + * @param array the heap array + * @param n heap size + */ + private static void siftUpComparable(int k, T x, Object[] array) { + Comparable key = (Comparable) x; + while (k > 0) { + int parent = (k - 1) >>> 1; + Object e = array[parent]; + if (key.compareTo((T) e) >= 0) + break; + array[k] = e; + k = parent; + } + array[k] = key; + } + + private static void siftUpUsingComparator(int k, T x, Object[] array, + Comparator cmp) { + while (k > 0) { + int parent = (k - 1) >>> 1; + Object e = array[parent]; + if (cmp.compare(x, (T) e) >= 0) + break; + array[k] = e; + k = parent; + } + array[k] = x; + } + + /** + * Inserts item x at position k, maintaining heap invariant by + * demoting x down the tree repeatedly until it is less than or + * equal to its children or is a leaf. + * + * @param k the position to fill + * @param x the item to insert + * @param array the heap array + * @param n heap size + */ + private static void siftDownComparable(int k, T x, Object[] array, + int n) { + Comparable key = (Comparable)x; + int half = n >>> 1; // loop while a non-leaf + while (k < half) { + int child = (k << 1) + 1; // assume left child is least + Object c = array[child]; + int right = child + 1; + if (right < n && + ((Comparable) c).compareTo((T) array[right]) > 0) + c = array[child = right]; + if (key.compareTo((T) c) <= 0) + break; + array[k] = c; + k = child; + } + array[k] = key; + } + + private static void siftDownUsingComparator(int k, T x, Object[] array, + int n, + Comparator cmp) { + int half = n >>> 1; + while (k < half) { + int child = (k << 1) + 1; + Object c = array[child]; + int right = child + 1; + if (right < n && cmp.compare((T) c, (T) array[right]) > 0) + c = array[child = right]; + if (cmp.compare(x, (T) c) <= 0) + break; + array[k] = c; + k = child; + } + array[k] = x; + } + + /** + * Establishes the heap invariant (described above) in the entire tree, + * assuming nothing about the order of the elements prior to the call. + */ + private void heapify() { + Object[] array = queue; + int n = size; + int half = (n >>> 1) - 1; + Comparator cmp = comparator; + if (cmp == null) { + for (int i = half; i >= 0; i--) + siftDownComparable(i, (E) array[i], array, n); + } + else { + for (int i = half; i >= 0; i--) + siftDownUsingComparator(i, (E) array[i], array, n, cmp); + } } /** * Inserts the specified element into this priority queue. * * @param e the element to add - * @return true (as specified by {@link Collection#add}) + * @return {@code true} (as specified by {@link Collection#add}) * @throws ClassCastException if the specified element cannot be compared * with elements currently in the priority queue according to the * priority queue's ordering @@ -177,30 +451,41 @@ public class PriorityBlockingQueue extends AbstractQueue /** * Inserts the specified element into this priority queue. + * As the queue is unbounded, this method will never return {@code false}. * * @param e the element to add - * @return true (as specified by {@link Queue#offer}) + * @return {@code true} (as specified by {@link Queue#offer}) * @throws ClassCastException if the specified element cannot be compared * with elements currently in the priority queue according to the * priority queue's ordering * @throws NullPointerException if the specified element is null */ public boolean offer(E e) { + if (e == null) + throw new NullPointerException(); final ReentrantLock lock = this.lock; lock.lock(); + int n, cap; + Object[] array; + while ((n = size) >= (cap = (array = queue).length)) + tryGrow(array, cap); try { - boolean ok = q.offer(e); - assert ok; + Comparator cmp = comparator; + if (cmp == null) + siftUpComparable(n, e, array); + else + siftUpUsingComparator(n, e, array, cmp); + size = n + 1; notEmpty.signal(); - return true; } finally { lock.unlock(); } + return true; } /** - * Inserts the specified element into this priority queue. As the queue is - * unbounded this method will never block. + * Inserts the specified element into this priority queue. + * As the queue is unbounded, this method will never block. * * @param e the element to add * @throws ClassCastException if the specified element cannot be compared @@ -213,13 +498,15 @@ public class PriorityBlockingQueue extends AbstractQueue } /** - * Inserts the specified element into this priority queue. As the queue is - * unbounded this method will never block. + * Inserts the specified element into this priority queue. + * As the queue is unbounded, this method will never block or + * return {@code false}. * * @param e the element to add * @param timeout This parameter is ignored as the method never blocks * @param unit This parameter is ignored as the method never blocks - * @return true + * @return {@code true} (as specified by + * {@link BlockingQueue#offer(Object,long,TimeUnit) BlockingQueue.offer}) * @throws ClassCastException if the specified element cannot be compared * with elements currently in the priority queue according to the * priority queue's ordering @@ -232,97 +519,123 @@ public class PriorityBlockingQueue extends AbstractQueue public E poll() { final ReentrantLock lock = this.lock; lock.lock(); + E result; try { - return q.poll(); + result = extract(); } finally { lock.unlock(); } + return result; } public E take() throws InterruptedException { final ReentrantLock lock = this.lock; lock.lockInterruptibly(); + E result; try { - try { - while (q.size() == 0) - notEmpty.await(); - } catch (InterruptedException ie) { - notEmpty.signal(); // propagate to non-interrupted thread - throw ie; - } - E x = q.poll(); - assert x != null; - return x; + while ( (result = extract()) == null) + notEmpty.await(); } finally { lock.unlock(); } + return result; } public E poll(long timeout, TimeUnit unit) throws InterruptedException { long nanos = unit.toNanos(timeout); final ReentrantLock lock = this.lock; lock.lockInterruptibly(); + E result; try { - for (;;) { - E x = q.poll(); - if (x != null) - return x; - if (nanos <= 0) - return null; - try { - nanos = notEmpty.awaitNanos(nanos); - } catch (InterruptedException ie) { - notEmpty.signal(); // propagate to non-interrupted thread - throw ie; - } - } + while ( (result = extract()) == null && nanos > 0) + nanos = notEmpty.awaitNanos(nanos); } finally { lock.unlock(); } + return result; } public E peek() { final ReentrantLock lock = this.lock; lock.lock(); + E result; try { - return q.peek(); + result = size > 0 ? (E) queue[0] : null; } finally { lock.unlock(); } + return result; } /** * Returns the comparator used to order the elements in this queue, - * or null if this queue uses the {@linkplain Comparable + * or {@code null} if this queue uses the {@linkplain Comparable * natural ordering} of its elements. * * @return the comparator used to order the elements in this queue, - * or null if this queue uses the natural + * or {@code null} if this queue uses the natural * ordering of its elements */ public Comparator comparator() { - return q.comparator(); + return comparator; } public int size() { final ReentrantLock lock = this.lock; lock.lock(); try { - return q.size(); + return size; } finally { lock.unlock(); } } /** - * Always returns Integer.MAX_VALUE because - * a PriorityBlockingQueue is not capacity constrained. - * @return Integer.MAX_VALUE + * Always returns {@code Integer.MAX_VALUE} because + * a {@code PriorityBlockingQueue} is not capacity constrained. + * @return {@code Integer.MAX_VALUE} always */ public int remainingCapacity() { return Integer.MAX_VALUE; } + private int indexOf(Object o) { + if (o != null) { + Object[] array = queue; + int n = size; + for (int i = 0; i < n; i++) + if (o.equals(array[i])) + return i; + } + return -1; + } + + /** + * Removes the ith element from queue. + */ + private void removeAt(int i) { + Object[] array = queue; + int n = size - 1; + if (n == i) // removed last element + array[i] = null; + else { + E moved = (E) array[n]; + array[n] = null; + Comparator cmp = comparator; + if (cmp == null) + siftDownComparable(i, moved, array, n); + else + siftDownUsingComparator(i, moved, array, n, cmp); + if (array[i] == moved) { + if (cmp == null) + siftUpComparable(i, moved, array); + else + siftUpUsingComparator(i, moved, array, cmp); + } + } + size = n; + } + /** * Removes a single instance of the specified element from this queue, * if it is present. More formally, removes an element {@code e} such @@ -332,13 +645,40 @@ public class PriorityBlockingQueue extends AbstractQueue * result of the call). * * @param o element to be removed from this queue, if present - * @return true if this queue changed as a result of the call + * @return {@code true} if this queue changed as a result of the call */ public boolean remove(Object o) { + boolean removed = false; final ReentrantLock lock = this.lock; lock.lock(); try { - return q.remove(o); + int i = indexOf(o); + if (i != -1) { + removeAt(i); + removed = true; + } + } finally { + lock.unlock(); + } + return removed; + } + + + /** + * Identity-based version for use in Itr.remove + */ + private void removeEQ(Object o) { + final ReentrantLock lock = this.lock; + lock.lock(); + try { + Object[] array = queue; + int n = size; + for (int i = 0; i < n; i++) { + if (o == array[i]) { + removeAt(i); + break; + } + } } finally { lock.unlock(); } @@ -350,16 +690,18 @@ public class PriorityBlockingQueue extends AbstractQueue * at least one element {@code e} such that {@code o.equals(e)}. * * @param o object to be checked for containment in this queue - * @return true if this queue contains the specified element + * @return {@code true} if this queue contains the specified element */ public boolean contains(Object o) { + int index; final ReentrantLock lock = this.lock; lock.lock(); try { - return q.contains(o); + index = indexOf(o); } finally { lock.unlock(); } + return index != -1; } /** @@ -379,7 +721,7 @@ public class PriorityBlockingQueue extends AbstractQueue final ReentrantLock lock = this.lock; lock.lock(); try { - return q.toArray(); + return Arrays.copyOf(queue, size); } finally { lock.unlock(); } @@ -390,7 +732,18 @@ public class PriorityBlockingQueue extends AbstractQueue final ReentrantLock lock = this.lock; lock.lock(); try { - return q.toString(); + int n = size; + if (n == 0) + return "[]"; + StringBuilder sb = new StringBuilder(); + sb.append('['); + for (int i = 0; i < n; ++i) { + E e = (E)queue[i]; + sb.append(e == this ? "(this Collection)" : e); + if (i != n - 1) + sb.append(',').append(' '); + } + return sb.append(']').toString(); } finally { lock.unlock(); } @@ -412,7 +765,7 @@ public class PriorityBlockingQueue extends AbstractQueue try { int n = 0; E e; - while ( (e = q.poll()) != null) { + while ( (e = extract()) != null) { c.add(e); ++n; } @@ -440,7 +793,7 @@ public class PriorityBlockingQueue extends AbstractQueue try { int n = 0; E e; - while (n < maxElements && (e = q.poll()) != null) { + while (n < maxElements && (e = extract()) != null) { c.add(e); ++n; } @@ -458,7 +811,11 @@ public class PriorityBlockingQueue extends AbstractQueue final ReentrantLock lock = this.lock; lock.lock(); try { - q.clear(); + Object[] array = queue; + int n = size; + size = 0; + for (int i = 0; i < n; i++) + array[i] = null; } finally { lock.unlock(); } @@ -475,22 +832,22 @@ public class PriorityBlockingQueue extends AbstractQueue *

    If this queue fits in the specified array with room to spare * (i.e., the array has more elements than this queue), the element in * the array immediately following the end of the queue is set to - * null. + * {@code null}. * *

    Like the {@link #toArray()} method, this method acts as bridge between * array-based and collection-based APIs. Further, this method allows * precise control over the runtime type of the output array, and may, * under certain circumstances, be used to save allocation costs. * - *

    Suppose x is a queue known to contain only strings. + *

    Suppose {@code x} is a queue known to contain only strings. * The following code can be used to dump the queue into a newly - * allocated array of String: + * allocated array of {@code String}: * *

          *     String[] y = x.toArray(new String[0]);
    * - * Note that toArray(new Object[0]) is identical in function to - * toArray(). + * Note that {@code toArray(new Object[0])} is identical in function to + * {@code toArray()}. * * @param a the array into which the elements of the queue are to * be stored, if it is big enough; otherwise, a new array of the @@ -505,7 +862,14 @@ public class PriorityBlockingQueue extends AbstractQueue final ReentrantLock lock = this.lock; lock.lock(); try { - return q.toArray(a); + int n = size; + if (a.length < n) + // Make a new array of a's runtime type, but my contents: + return (T[]) Arrays.copyOf(queue, size, a.getClass()); + System.arraycopy(queue, 0, a, 0, n); + if (a.length > n) + a[n] = null; + return a; } finally { lock.unlock(); } @@ -514,8 +878,9 @@ public class PriorityBlockingQueue extends AbstractQueue /** * Returns an iterator over the elements in this queue. The * iterator does not return the elements in any particular order. - * The returned Iterator is a "weakly consistent" - * iterator that will never throw {@link + * + *

    The returned iterator is a "weakly consistent" iterator that + * will never throw {@link java.util.ConcurrentModificationException * ConcurrentModificationException}, and guarantees to traverse * elements as they existed upon construction of the iterator, and * may (but is not guaranteed to) reflect any modifications @@ -530,7 +895,7 @@ public class PriorityBlockingQueue extends AbstractQueue /** * Snapshot iterator that works off copy of underlying q array. */ - private class Itr implements Iterator { + final class Itr implements Iterator { final Object[] array; // Array of all elements int cursor; // index of next element to return; int lastRet; // index of last element, or -1 if no such @@ -554,39 +919,65 @@ public class PriorityBlockingQueue extends AbstractQueue public void remove() { if (lastRet < 0) throw new IllegalStateException(); - Object x = array[lastRet]; + removeEQ(array[lastRet]); lastRet = -1; - // Traverse underlying queue to find == element, - // not just a .equals element. - lock.lock(); - try { - for (Iterator it = q.iterator(); it.hasNext(); ) { - if (it.next() == x) { - it.remove(); - return; - } - } - } finally { - lock.unlock(); - } } } /** - * Saves the state to a stream (that is, serializes it). This - * merely wraps default serialization within lock. The - * serialization strategy for items is left to underlying - * Queue. Note that locking is not needed on deserialization, so - * readObject is not defined, just relying on default. + * Saves the state to a stream (that is, serializes it). For + * compatibility with previous version of this class, + * elements are first copied to a java.util.PriorityQueue, + * which is then serialized. */ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { lock.lock(); try { + int n = size; // avoid zero capacity argument + q = new PriorityQueue(n == 0 ? 1 : n, comparator); + q.addAll(this); s.defaultWriteObject(); } finally { + q = null; lock.unlock(); } } + /** + * Reconstitutes the {@code PriorityBlockingQueue} instance from a stream + * (that is, deserializes it). + * + * @param s the stream + */ + private void readObject(java.io.ObjectInputStream s) + throws java.io.IOException, ClassNotFoundException { + try { + s.defaultReadObject(); + this.queue = new Object[q.size()]; + comparator = q.comparator(); + addAll(q); + } finally { + q = null; + } + } + + // Unsafe mechanics + private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe(); + private static final long allocationSpinLockOffset = + objectFieldOffset(UNSAFE, "allocationSpinLock", + PriorityBlockingQueue.class); + + static long objectFieldOffset(sun.misc.Unsafe UNSAFE, + String field, Class klazz) { + try { + return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field)); + } catch (NoSuchFieldException e) { + // Convert Exception to corresponding Error + NoSuchFieldError error = new NoSuchFieldError(field); + error.initCause(e); + throw error; + } + } + } diff --git a/src/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java b/src/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java index 46961b7aa40a43bf01bd9c0107b1ea618e4d6cb5..f1731420897b2ed7788ca340c28cc948799f6f7a 100644 --- a/src/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java +++ b/src/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java @@ -360,8 +360,12 @@ public class ScheduledThreadPoolExecutor getExecuteExistingDelayedTasksAfterShutdownPolicy(); boolean keepPeriodic = getContinueExistingPeriodicTasksAfterShutdownPolicy(); - if (!keepDelayed && !keepPeriodic) + if (!keepDelayed && !keepPeriodic) { + for (Object e : q.toArray()) + if (e instanceof RunnableScheduledFuture) + ((RunnableScheduledFuture) e).cancel(false); q.clear(); + } else { // Traverse snapshot to avoid iterator exceptions for (Object e : q.toArray()) { diff --git a/src/share/classes/java/util/concurrent/SynchronousQueue.java b/src/share/classes/java/util/concurrent/SynchronousQueue.java index f39f1a906e6a9dd465b757b7a5800b3a07bbb123..47b352f9e355034410804c307b1c6278f1575003 100644 --- a/src/share/classes/java/util/concurrent/SynchronousQueue.java +++ b/src/share/classes/java/util/concurrent/SynchronousQueue.java @@ -163,7 +163,7 @@ public class SynchronousQueue extends AbstractQueue /** * Shared internal API for dual stacks and queues. */ - static abstract class Transferer { + abstract static class Transferer { /** * Performs a put or take. * @@ -190,7 +190,7 @@ public class SynchronousQueue extends AbstractQueue * seems not to vary with number of CPUs (beyond 2) so is just * a constant. */ - static final int maxTimedSpins = (NCPUS < 2)? 0 : 32; + static final int maxTimedSpins = (NCPUS < 2) ? 0 : 32; /** * The number of times to spin before blocking in untimed waits. @@ -241,19 +241,11 @@ public class SynchronousQueue extends AbstractQueue this.item = item; } - static final AtomicReferenceFieldUpdater - nextUpdater = AtomicReferenceFieldUpdater.newUpdater - (SNode.class, SNode.class, "next"); - boolean casNext(SNode cmp, SNode val) { - return (cmp == next && - nextUpdater.compareAndSet(this, cmp, val)); + return cmp == next && + UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val); } - static final AtomicReferenceFieldUpdater - matchUpdater = AtomicReferenceFieldUpdater.newUpdater - (SNode.class, SNode.class, "match"); - /** * Tries to match node s to this node, if so, waking up thread. * Fulfillers call tryMatch to identify their waiters. @@ -264,7 +256,7 @@ public class SynchronousQueue extends AbstractQueue */ boolean tryMatch(SNode s) { if (match == null && - matchUpdater.compareAndSet(this, null, s)) { + UNSAFE.compareAndSwapObject(this, matchOffset, null, s)) { Thread w = waiter; if (w != null) { // waiters need at most one unpark waiter = null; @@ -279,23 +271,28 @@ public class SynchronousQueue extends AbstractQueue * Tries to cancel a wait by matching node to itself. */ void tryCancel() { - matchUpdater.compareAndSet(this, null, this); + UNSAFE.compareAndSwapObject(this, matchOffset, null, this); } boolean isCancelled() { return match == this; } + + // Unsafe mechanics + private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe(); + private static final long nextOffset = + objectFieldOffset(UNSAFE, "next", SNode.class); + private static final long matchOffset = + objectFieldOffset(UNSAFE, "match", SNode.class); + } /** The head (top) of the stack */ volatile SNode head; - static final AtomicReferenceFieldUpdater - headUpdater = AtomicReferenceFieldUpdater.newUpdater - (TransferStack.class, SNode.class, "head"); - boolean casHead(SNode h, SNode nh) { - return h == head && headUpdater.compareAndSet(this, h, nh); + return h == head && + UNSAFE.compareAndSwapObject(this, headOffset, h, nh); } /** @@ -338,7 +335,7 @@ public class SynchronousQueue extends AbstractQueue */ SNode s = null; // constructed/reused as needed - int mode = (e == null)? REQUEST : DATA; + int mode = (e == null) ? REQUEST : DATA; for (;;) { SNode h = head; @@ -356,7 +353,7 @@ public class SynchronousQueue extends AbstractQueue } if ((h = head) != null && h.next == s) casHead(h, s.next); // help s's fulfiller - return mode == REQUEST? m.item : s.item; + return (mode == REQUEST) ? m.item : s.item; } } else if (!isFulfilling(h.mode)) { // try to fulfill if (h.isCancelled()) // already cancelled @@ -372,7 +369,7 @@ public class SynchronousQueue extends AbstractQueue SNode mn = m.next; if (m.tryMatch(s)) { casHead(s, mn); // pop both s and m - return (mode == REQUEST)? m.item : s.item; + return (mode == REQUEST) ? m.item : s.item; } else // lost match s.casNext(m, mn); // help unlink } @@ -423,11 +420,11 @@ public class SynchronousQueue extends AbstractQueue * and don't wait at all, so are trapped in transfer * method rather than calling awaitFulfill. */ - long lastTime = (timed)? System.nanoTime() : 0; + long lastTime = timed ? System.nanoTime() : 0; Thread w = Thread.currentThread(); SNode h = head; - int spins = (shouldSpin(s)? - (timed? maxTimedSpins : maxUntimedSpins) : 0); + int spins = (shouldSpin(s) ? + (timed ? maxTimedSpins : maxUntimedSpins) : 0); for (;;) { if (w.isInterrupted()) s.tryCancel(); @@ -444,7 +441,7 @@ public class SynchronousQueue extends AbstractQueue } } if (spins > 0) - spins = shouldSpin(s)? (spins-1) : 0; + spins = shouldSpin(s) ? (spins-1) : 0; else if (s.waiter == null) s.waiter = w; // establish waiter so can park next iter else if (!timed) @@ -499,6 +496,12 @@ public class SynchronousQueue extends AbstractQueue p = n; } } + + // Unsafe mechanics + private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe(); + private static final long headOffset = + objectFieldOffset(UNSAFE, "head", TransferStack.class); + } /** Dual Queue */ @@ -524,29 +527,21 @@ public class SynchronousQueue extends AbstractQueue this.isData = isData; } - static final AtomicReferenceFieldUpdater - nextUpdater = AtomicReferenceFieldUpdater.newUpdater - (QNode.class, QNode.class, "next"); - boolean casNext(QNode cmp, QNode val) { - return (next == cmp && - nextUpdater.compareAndSet(this, cmp, val)); + return next == cmp && + UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val); } - static final AtomicReferenceFieldUpdater - itemUpdater = AtomicReferenceFieldUpdater.newUpdater - (QNode.class, Object.class, "item"); - boolean casItem(Object cmp, Object val) { - return (item == cmp && - itemUpdater.compareAndSet(this, cmp, val)); + return item == cmp && + UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val); } /** * Tries to cancel by CAS'ing ref to this as item. */ void tryCancel(Object cmp) { - itemUpdater.compareAndSet(this, cmp, this); + UNSAFE.compareAndSwapObject(this, itemOffset, cmp, this); } boolean isCancelled() { @@ -561,6 +556,13 @@ public class SynchronousQueue extends AbstractQueue boolean isOffList() { return next == this; } + + // Unsafe mechanics + private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe(); + private static final long nextOffset = + objectFieldOffset(UNSAFE, "next", QNode.class); + private static final long itemOffset = + objectFieldOffset(UNSAFE, "item", QNode.class); } /** Head of queue */ @@ -580,41 +582,30 @@ public class SynchronousQueue extends AbstractQueue tail = h; } - static final AtomicReferenceFieldUpdater - headUpdater = AtomicReferenceFieldUpdater.newUpdater - (TransferQueue.class, QNode.class, "head"); - /** * Tries to cas nh as new head; if successful, unlink * old head's next node to avoid garbage retention. */ void advanceHead(QNode h, QNode nh) { - if (h == head && headUpdater.compareAndSet(this, h, nh)) + if (h == head && + UNSAFE.compareAndSwapObject(this, headOffset, h, nh)) h.next = h; // forget old next } - static final AtomicReferenceFieldUpdater - tailUpdater = AtomicReferenceFieldUpdater.newUpdater - (TransferQueue.class, QNode.class, "tail"); - /** * Tries to cas nt as new tail. */ void advanceTail(QNode t, QNode nt) { if (tail == t) - tailUpdater.compareAndSet(this, t, nt); + UNSAFE.compareAndSwapObject(this, tailOffset, t, nt); } - static final AtomicReferenceFieldUpdater - cleanMeUpdater = AtomicReferenceFieldUpdater.newUpdater - (TransferQueue.class, QNode.class, "cleanMe"); - /** * Tries to CAS cleanMe slot. */ boolean casCleanMe(QNode cmp, QNode val) { - return (cleanMe == cmp && - cleanMeUpdater.compareAndSet(this, cmp, val)); + return cleanMe == cmp && + UNSAFE.compareAndSwapObject(this, cleanMeOffset, cmp, val); } /** @@ -683,7 +674,7 @@ public class SynchronousQueue extends AbstractQueue s.item = s; s.waiter = null; } - return (x != null)? x : e; + return (x != null) ? x : e; } else { // complementary-mode QNode m = h.next; // node to fulfill @@ -700,7 +691,7 @@ public class SynchronousQueue extends AbstractQueue advanceHead(h, m); // successfully fulfilled LockSupport.unpark(m.waiter); - return (x != null)? x : e; + return (x != null) ? x : e; } } } @@ -716,10 +707,10 @@ public class SynchronousQueue extends AbstractQueue */ Object awaitFulfill(QNode s, Object e, boolean timed, long nanos) { /* Same idea as TransferStack.awaitFulfill */ - long lastTime = (timed)? System.nanoTime() : 0; + long lastTime = timed ? System.nanoTime() : 0; Thread w = Thread.currentThread(); int spins = ((head.next == s) ? - (timed? maxTimedSpins : maxUntimedSpins) : 0); + (timed ? maxTimedSpins : maxUntimedSpins) : 0); for (;;) { if (w.isInterrupted()) s.tryCancel(e); @@ -799,6 +790,16 @@ public class SynchronousQueue extends AbstractQueue return; // Postpone cleaning s } } + + // unsafe mechanics + private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe(); + private static final long headOffset = + objectFieldOffset(UNSAFE, "head", TransferQueue.class); + private static final long tailOffset = + objectFieldOffset(UNSAFE, "tail", TransferQueue.class); + private static final long cleanMeOffset = + objectFieldOffset(UNSAFE, "cleanMe", TransferQueue.class); + } /** @@ -824,7 +825,7 @@ public class SynchronousQueue extends AbstractQueue * access; otherwise the order is unspecified. */ public SynchronousQueue(boolean fair) { - transferer = (fair)? new TransferQueue() : new TransferStack(); + transferer = fair ? new TransferQueue() : new TransferStack(); } /** @@ -1141,4 +1142,17 @@ public class SynchronousQueue extends AbstractQueue transferer = new TransferStack(); } + // Unsafe mechanics + static long objectFieldOffset(sun.misc.Unsafe UNSAFE, + String field, Class klazz) { + try { + return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field)); + } catch (NoSuchFieldException e) { + // Convert Exception to corresponding Error + NoSuchFieldError error = new NoSuchFieldError(field); + error.initCause(e); + throw error; + } + } + } diff --git a/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java b/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java index bfd3b8381f83b35fe91e6e70f1dc29a796b2a1cf..841a5804430080b6a16feb4643af297d08d34780 100644 --- a/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java +++ b/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java @@ -1841,6 +1841,43 @@ public class ThreadPoolExecutor extends AbstractExecutorService { } } + /** + * Returns a string identifying this pool, as well as its state, + * including indications of run state and estimated worker and + * task counts. + * + * @return a string identifying this pool, as well as its state + */ + public String toString() { + long ncompleted; + int nworkers, nactive; + final ReentrantLock mainLock = this.mainLock; + mainLock.lock(); + try { + ncompleted = completedTaskCount; + nactive = 0; + nworkers = workers.size(); + for (Worker w : workers) { + ncompleted += w.completedTasks; + if (w.isLocked()) + ++nactive; + } + } finally { + mainLock.unlock(); + } + int c = ctl.get(); + String rs = (runStateLessThan(c, SHUTDOWN) ? "Running" : + (runStateAtLeast(c, TERMINATED) ? "Terminated" : + "Shutting down")); + return super.toString() + + "[" + rs + + ", pool size = " + nworkers + + ", active threads = " + nactive + + ", queued tasks = " + workQueue.size() + + ", completed tasks = " + ncompleted + + "]"; + } + /* Extension hooks */ /** @@ -1961,7 +1998,9 @@ public class ThreadPoolExecutor extends AbstractExecutorService { * @throws RejectedExecutionException always. */ public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { - throw new RejectedExecutionException(); + throw new RejectedExecutionException("Task " + r.toString() + + " rejected from " + + e.toString()); } } diff --git a/src/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java b/src/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java index 2a9b8a80db0fec38835995c798d6b31ca386d9b6..54b9488ab51210cdb920808e2641e3be5d34e01c 100644 --- a/src/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java +++ b/src/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java @@ -48,28 +48,37 @@ import java.util.*; public class AtomicIntegerArray implements java.io.Serializable { private static final long serialVersionUID = 2862133569453604235L; - // setup to use Unsafe.compareAndSwapInt for updates private static final Unsafe unsafe = Unsafe.getUnsafe(); private static final int base = unsafe.arrayBaseOffset(int[].class); - private static final int scale = unsafe.arrayIndexScale(int[].class); + private static final int shift; private final int[] array; - private long rawIndex(int i) { + static { + int scale = unsafe.arrayIndexScale(int[].class); + if ((scale & (scale - 1)) != 0) + throw new Error("data type scale not a power of two"); + shift = 31 - Integer.numberOfLeadingZeros(scale); + } + + private long checkedByteOffset(int i) { if (i < 0 || i >= array.length) throw new IndexOutOfBoundsException("index " + i); - return base + (long) i * scale; + + return byteOffset(i); + } + + private static long byteOffset(int i) { + return ((long) i << shift) + base; } /** - * Creates a new AtomicIntegerArray of given length. + * Creates a new AtomicIntegerArray of the given length, with all + * elements initially zero. * * @param length the length of the array */ public AtomicIntegerArray(int length) { array = new int[length]; - // must perform at least one volatile write to conform to JMM - if (length > 0) - unsafe.putIntVolatile(array, rawIndex(0), 0); } /** @@ -80,17 +89,8 @@ public class AtomicIntegerArray implements java.io.Serializable { * @throws NullPointerException if array is null */ public AtomicIntegerArray(int[] array) { - if (array == null) - throw new NullPointerException(); - int length = array.length; - this.array = new int[length]; - if (length > 0) { - int last = length-1; - for (int i = 0; i < last; ++i) - this.array[i] = array[i]; - // Do the last write as volatile - unsafe.putIntVolatile(this.array, rawIndex(last), array[last]); - } + // Visibility guaranteed by final field guarantees + this.array = array.clone(); } /** @@ -109,7 +109,11 @@ public class AtomicIntegerArray implements java.io.Serializable { * @return the current value */ public final int get(int i) { - return unsafe.getIntVolatile(array, rawIndex(i)); + return getRaw(checkedByteOffset(i)); + } + + private int getRaw(long offset) { + return unsafe.getIntVolatile(array, offset); } /** @@ -119,7 +123,7 @@ public class AtomicIntegerArray implements java.io.Serializable { * @param newValue the new value */ public final void set(int i, int newValue) { - unsafe.putIntVolatile(array, rawIndex(i), newValue); + unsafe.putIntVolatile(array, checkedByteOffset(i), newValue); } /** @@ -130,7 +134,7 @@ public class AtomicIntegerArray implements java.io.Serializable { * @since 1.6 */ public final void lazySet(int i, int newValue) { - unsafe.putOrderedInt(array, rawIndex(i), newValue); + unsafe.putOrderedInt(array, checkedByteOffset(i), newValue); } /** @@ -142,9 +146,10 @@ public class AtomicIntegerArray implements java.io.Serializable { * @return the previous value */ public final int getAndSet(int i, int newValue) { + long offset = checkedByteOffset(i); while (true) { - int current = get(i); - if (compareAndSet(i, current, newValue)) + int current = getRaw(offset); + if (compareAndSetRaw(offset, current, newValue)) return current; } } @@ -160,8 +165,11 @@ public class AtomicIntegerArray implements java.io.Serializable { * the actual value was not equal to the expected value. */ public final boolean compareAndSet(int i, int expect, int update) { - return unsafe.compareAndSwapInt(array, rawIndex(i), - expect, update); + return compareAndSetRaw(checkedByteOffset(i), expect, update); + } + + private boolean compareAndSetRaw(long offset, int expect, int update) { + return unsafe.compareAndSwapInt(array, offset, expect, update); } /** @@ -188,12 +196,7 @@ public class AtomicIntegerArray implements java.io.Serializable { * @return the previous value */ public final int getAndIncrement(int i) { - while (true) { - int current = get(i); - int next = current + 1; - if (compareAndSet(i, current, next)) - return current; - } + return getAndAdd(i, 1); } /** @@ -203,12 +206,7 @@ public class AtomicIntegerArray implements java.io.Serializable { * @return the previous value */ public final int getAndDecrement(int i) { - while (true) { - int current = get(i); - int next = current - 1; - if (compareAndSet(i, current, next)) - return current; - } + return getAndAdd(i, -1); } /** @@ -219,10 +217,10 @@ public class AtomicIntegerArray implements java.io.Serializable { * @return the previous value */ public final int getAndAdd(int i, int delta) { + long offset = checkedByteOffset(i); while (true) { - int current = get(i); - int next = current + delta; - if (compareAndSet(i, current, next)) + int current = getRaw(offset); + if (compareAndSetRaw(offset, current, current + delta)) return current; } } @@ -234,12 +232,7 @@ public class AtomicIntegerArray implements java.io.Serializable { * @return the updated value */ public final int incrementAndGet(int i) { - while (true) { - int current = get(i); - int next = current + 1; - if (compareAndSet(i, current, next)) - return next; - } + return addAndGet(i, 1); } /** @@ -249,12 +242,7 @@ public class AtomicIntegerArray implements java.io.Serializable { * @return the updated value */ public final int decrementAndGet(int i) { - while (true) { - int current = get(i); - int next = current - 1; - if (compareAndSet(i, current, next)) - return next; - } + return addAndGet(i, -1); } /** @@ -265,22 +253,32 @@ public class AtomicIntegerArray implements java.io.Serializable { * @return the updated value */ public final int addAndGet(int i, int delta) { + long offset = checkedByteOffset(i); while (true) { - int current = get(i); + int current = getRaw(offset); int next = current + delta; - if (compareAndSet(i, current, next)) + if (compareAndSetRaw(offset, current, next)) return next; } } /** * Returns the String representation of the current values of array. - * @return the String representation of the current values of array. + * @return the String representation of the current values of array */ public String toString() { - if (array.length > 0) // force volatile read - get(0); - return Arrays.toString(array); + int iMax = array.length - 1; + if (iMax == -1) + return "[]"; + + StringBuilder b = new StringBuilder(); + b.append('['); + for (int i = 0; ; i++) { + b.append(getRaw(byteOffset(i))); + if (i == iMax) + return b.append(']').toString(); + b.append(',').append(' '); + } } } diff --git a/src/share/classes/java/util/concurrent/atomic/AtomicLongArray.java b/src/share/classes/java/util/concurrent/atomic/AtomicLongArray.java index d1f404ca69b0b134bf1c6ac64889bc77ecd54667..f1873c54d7a4d27ee91c42db91d1e1ca0a34c5af 100644 --- a/src/share/classes/java/util/concurrent/atomic/AtomicLongArray.java +++ b/src/share/classes/java/util/concurrent/atomic/AtomicLongArray.java @@ -47,28 +47,37 @@ import java.util.*; public class AtomicLongArray implements java.io.Serializable { private static final long serialVersionUID = -2308431214976778248L; - // setup to use Unsafe.compareAndSwapInt for updates private static final Unsafe unsafe = Unsafe.getUnsafe(); private static final int base = unsafe.arrayBaseOffset(long[].class); - private static final int scale = unsafe.arrayIndexScale(long[].class); + private static final int shift; private final long[] array; - private long rawIndex(int i) { + static { + int scale = unsafe.arrayIndexScale(long[].class); + if ((scale & (scale - 1)) != 0) + throw new Error("data type scale not a power of two"); + shift = 31 - Integer.numberOfLeadingZeros(scale); + } + + private long checkedByteOffset(int i) { if (i < 0 || i >= array.length) throw new IndexOutOfBoundsException("index " + i); - return base + (long) i * scale; + + return byteOffset(i); + } + + private static long byteOffset(int i) { + return ((long) i << shift) + base; } /** - * Creates a new AtomicLongArray of given length. + * Creates a new AtomicLongArray of the given length, with all + * elements initially zero. * * @param length the length of the array */ public AtomicLongArray(int length) { array = new long[length]; - // must perform at least one volatile write to conform to JMM - if (length > 0) - unsafe.putLongVolatile(array, rawIndex(0), 0); } /** @@ -79,17 +88,8 @@ public class AtomicLongArray implements java.io.Serializable { * @throws NullPointerException if array is null */ public AtomicLongArray(long[] array) { - if (array == null) - throw new NullPointerException(); - int length = array.length; - this.array = new long[length]; - if (length > 0) { - int last = length-1; - for (int i = 0; i < last; ++i) - this.array[i] = array[i]; - // Do the last write as volatile - unsafe.putLongVolatile(this.array, rawIndex(last), array[last]); - } + // Visibility guaranteed by final field guarantees + this.array = array.clone(); } /** @@ -108,7 +108,11 @@ public class AtomicLongArray implements java.io.Serializable { * @return the current value */ public final long get(int i) { - return unsafe.getLongVolatile(array, rawIndex(i)); + return getRaw(checkedByteOffset(i)); + } + + private long getRaw(long offset) { + return unsafe.getLongVolatile(array, offset); } /** @@ -118,7 +122,7 @@ public class AtomicLongArray implements java.io.Serializable { * @param newValue the new value */ public final void set(int i, long newValue) { - unsafe.putLongVolatile(array, rawIndex(i), newValue); + unsafe.putLongVolatile(array, checkedByteOffset(i), newValue); } /** @@ -129,7 +133,7 @@ public class AtomicLongArray implements java.io.Serializable { * @since 1.6 */ public final void lazySet(int i, long newValue) { - unsafe.putOrderedLong(array, rawIndex(i), newValue); + unsafe.putOrderedLong(array, checkedByteOffset(i), newValue); } @@ -142,16 +146,17 @@ public class AtomicLongArray implements java.io.Serializable { * @return the previous value */ public final long getAndSet(int i, long newValue) { + long offset = checkedByteOffset(i); while (true) { - long current = get(i); - if (compareAndSet(i, current, newValue)) + long current = getRaw(offset); + if (compareAndSetRaw(offset, current, newValue)) return current; } } /** - * Atomically sets the value to the given updated value - * if the current value {@code ==} the expected value. + * Atomically sets the element at position {@code i} to the given + * updated value if the current value {@code ==} the expected value. * * @param i the index * @param expect the expected value @@ -160,13 +165,16 @@ public class AtomicLongArray implements java.io.Serializable { * the actual value was not equal to the expected value. */ public final boolean compareAndSet(int i, long expect, long update) { - return unsafe.compareAndSwapLong(array, rawIndex(i), - expect, update); + return compareAndSetRaw(checkedByteOffset(i), expect, update); + } + + private boolean compareAndSetRaw(long offset, long expect, long update) { + return unsafe.compareAndSwapLong(array, offset, expect, update); } /** - * Atomically sets the value to the given updated value - * if the current value {@code ==} the expected value. + * Atomically sets the element at position {@code i} to the given + * updated value if the current value {@code ==} the expected value. * *

    May fail spuriously * and does not provide ordering guarantees, so is only rarely an @@ -188,12 +196,7 @@ public class AtomicLongArray implements java.io.Serializable { * @return the previous value */ public final long getAndIncrement(int i) { - while (true) { - long current = get(i); - long next = current + 1; - if (compareAndSet(i, current, next)) - return current; - } + return getAndAdd(i, 1); } /** @@ -203,12 +206,7 @@ public class AtomicLongArray implements java.io.Serializable { * @return the previous value */ public final long getAndDecrement(int i) { - while (true) { - long current = get(i); - long next = current - 1; - if (compareAndSet(i, current, next)) - return current; - } + return getAndAdd(i, -1); } /** @@ -219,10 +217,10 @@ public class AtomicLongArray implements java.io.Serializable { * @return the previous value */ public final long getAndAdd(int i, long delta) { + long offset = checkedByteOffset(i); while (true) { - long current = get(i); - long next = current + delta; - if (compareAndSet(i, current, next)) + long current = getRaw(offset); + if (compareAndSetRaw(offset, current, current + delta)) return current; } } @@ -234,12 +232,7 @@ public class AtomicLongArray implements java.io.Serializable { * @return the updated value */ public final long incrementAndGet(int i) { - while (true) { - long current = get(i); - long next = current + 1; - if (compareAndSet(i, current, next)) - return next; - } + return addAndGet(i, 1); } /** @@ -249,12 +242,7 @@ public class AtomicLongArray implements java.io.Serializable { * @return the updated value */ public final long decrementAndGet(int i) { - while (true) { - long current = get(i); - long next = current - 1; - if (compareAndSet(i, current, next)) - return next; - } + return addAndGet(i, -1); } /** @@ -265,22 +253,32 @@ public class AtomicLongArray implements java.io.Serializable { * @return the updated value */ public long addAndGet(int i, long delta) { + long offset = checkedByteOffset(i); while (true) { - long current = get(i); + long current = getRaw(offset); long next = current + delta; - if (compareAndSet(i, current, next)) + if (compareAndSetRaw(offset, current, next)) return next; } } /** * Returns the String representation of the current values of array. - * @return the String representation of the current values of array. + * @return the String representation of the current values of array */ public String toString() { - if (array.length > 0) // force volatile read - get(0); - return Arrays.toString(array); + int iMax = array.length - 1; + if (iMax == -1) + return "[]"; + + StringBuilder b = new StringBuilder(); + b.append('['); + for (int i = 0; ; i++) { + b.append(getRaw(byteOffset(i))); + if (i == iMax) + return b.append(']').toString(); + b.append(',').append(' '); + } } } diff --git a/src/share/classes/java/util/concurrent/atomic/AtomicMarkableReference.java b/src/share/classes/java/util/concurrent/atomic/AtomicMarkableReference.java index ca1ca6507a03b89ee499d0e0d95e722217b1e9da..e898758f52285a7a775b08d16905e1737db35e36 100644 --- a/src/share/classes/java/util/concurrent/atomic/AtomicMarkableReference.java +++ b/src/share/classes/java/util/concurrent/atomic/AtomicMarkableReference.java @@ -38,8 +38,8 @@ package java.util.concurrent.atomic; /** * An {@code AtomicMarkableReference} maintains an object reference * along with a mark bit, that can be updated atomically. - *

    - *

    Implementation note. This implementation maintains markable + * + *

    Implementation note: This implementation maintains markable * references by creating internal objects representing "boxed" * [reference, boolean] pairs. * @@ -47,17 +47,21 @@ package java.util.concurrent.atomic; * @author Doug Lea * @param The type of object referred to by this reference */ -public class AtomicMarkableReference { +public class AtomicMarkableReference { - private static class ReferenceBooleanPair { - private final T reference; - private final boolean bit; - ReferenceBooleanPair(T r, boolean i) { - reference = r; bit = i; + private static class Pair { + final T reference; + final boolean mark; + private Pair(T reference, boolean mark) { + this.reference = reference; + this.mark = mark; + } + static Pair of(T reference, boolean mark) { + return new Pair(reference, mark); } } - private final AtomicReference> atomicRef; + private volatile Pair pair; /** * Creates a new {@code AtomicMarkableReference} with the given @@ -67,7 +71,7 @@ public class AtomicMarkableReference { * @param initialMark the initial mark */ public AtomicMarkableReference(V initialRef, boolean initialMark) { - atomicRef = new AtomicReference> (new ReferenceBooleanPair(initialRef, initialMark)); + pair = Pair.of(initialRef, initialMark); } /** @@ -76,7 +80,7 @@ public class AtomicMarkableReference { * @return the current value of the reference */ public V getReference() { - return atomicRef.get().reference; + return pair.reference; } /** @@ -85,7 +89,7 @@ public class AtomicMarkableReference { * @return the current value of the mark */ public boolean isMarked() { - return atomicRef.get().bit; + return pair.mark; } /** @@ -97,9 +101,9 @@ public class AtomicMarkableReference { * @return the current value of the reference */ public V get(boolean[] markHolder) { - ReferenceBooleanPair p = atomicRef.get(); - markHolder[0] = p.bit; - return p.reference; + Pair pair = this.pair; + markHolder[0] = pair.mark; + return pair.reference; } /** @@ -122,13 +126,8 @@ public class AtomicMarkableReference { V newReference, boolean expectedMark, boolean newMark) { - ReferenceBooleanPair current = atomicRef.get(); - return expectedReference == current.reference && - expectedMark == current.bit && - ((newReference == current.reference && newMark == current.bit) || - atomicRef.weakCompareAndSet(current, - new ReferenceBooleanPair(newReference, - newMark))); + return compareAndSet(expectedReference, newReference, + expectedMark, newMark); } /** @@ -147,13 +146,13 @@ public class AtomicMarkableReference { V newReference, boolean expectedMark, boolean newMark) { - ReferenceBooleanPair current = atomicRef.get(); - return expectedReference == current.reference && - expectedMark == current.bit && - ((newReference == current.reference && newMark == current.bit) || - atomicRef.compareAndSet(current, - new ReferenceBooleanPair(newReference, - newMark))); + Pair current = pair; + return + expectedReference == current.reference && + expectedMark == current.mark && + ((newReference == current.reference && + newMark == current.mark) || + casPair(current, Pair.of(newReference, newMark))); } /** @@ -163,9 +162,9 @@ public class AtomicMarkableReference { * @param newMark the new value for the mark */ public void set(V newReference, boolean newMark) { - ReferenceBooleanPair current = atomicRef.get(); - if (newReference != current.reference || newMark != current.bit) - atomicRef.set(new ReferenceBooleanPair(newReference, newMark)); + Pair current = pair; + if (newReference != current.reference || newMark != current.mark) + this.pair = Pair.of(newReference, newMark); } /** @@ -182,11 +181,32 @@ public class AtomicMarkableReference { * @return true if successful */ public boolean attemptMark(V expectedReference, boolean newMark) { - ReferenceBooleanPair current = atomicRef.get(); - return expectedReference == current.reference && - (newMark == current.bit || - atomicRef.compareAndSet - (current, new ReferenceBooleanPair(expectedReference, - newMark))); + Pair current = pair; + return + expectedReference == current.reference && + (newMark == current.mark || + casPair(current, Pair.of(expectedReference, newMark))); + } + + // Unsafe mechanics + + private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe(); + private static final long pairOffset = + objectFieldOffset(UNSAFE, "pair", AtomicMarkableReference.class); + + private boolean casPair(Pair cmp, Pair val) { + return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val); + } + + static long objectFieldOffset(sun.misc.Unsafe UNSAFE, + String field, Class klazz) { + try { + return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field)); + } catch (NoSuchFieldException e) { + // Convert Exception to corresponding Error + NoSuchFieldError error = new NoSuchFieldError(field); + error.initCause(e); + throw error; + } } } diff --git a/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java b/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java index 6aca62c5cc76bfac570851e98c04c4bb8a954607..b5fd65ab48fd1c7e0352915eb16029ea55a081cc 100644 --- a/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java +++ b/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java @@ -51,24 +51,35 @@ public class AtomicReferenceArray implements java.io.Serializable { private static final Unsafe unsafe = Unsafe.getUnsafe(); private static final int base = unsafe.arrayBaseOffset(Object[].class); - private static final int scale = unsafe.arrayIndexScale(Object[].class); + private static final int shift; private final Object[] array; - private long rawIndex(int i) { + static { + int scale = unsafe.arrayIndexScale(Object[].class); + if ((scale & (scale - 1)) != 0) + throw new Error("data type scale not a power of two"); + shift = 31 - Integer.numberOfLeadingZeros(scale); + } + + private long checkedByteOffset(int i) { if (i < 0 || i >= array.length) throw new IndexOutOfBoundsException("index " + i); - return base + (long) i * scale; + + return byteOffset(i); + } + + private static long byteOffset(int i) { + return ((long) i << shift) + base; } /** - * Creates a new AtomicReferenceArray of given length. + * Creates a new AtomicReferenceArray of the given length, with all + * elements initially null. + * * @param length the length of the array */ public AtomicReferenceArray(int length) { array = new Object[length]; - // must perform at least one volatile write to conform to JMM - if (length > 0) - unsafe.putObjectVolatile(array, rawIndex(0), null); } /** @@ -79,18 +90,8 @@ public class AtomicReferenceArray implements java.io.Serializable { * @throws NullPointerException if array is null */ public AtomicReferenceArray(E[] array) { - if (array == null) - throw new NullPointerException(); - int length = array.length; - this.array = new Object[length]; - if (length > 0) { - int last = length-1; - for (int i = 0; i < last; ++i) - this.array[i] = array[i]; - // Do the last write as volatile - E e = array[last]; - unsafe.putObjectVolatile(this.array, rawIndex(last), e); - } + // Visibility guaranteed by final field guarantees + this.array = array.clone(); } /** @@ -109,7 +110,11 @@ public class AtomicReferenceArray implements java.io.Serializable { * @return the current value */ public final E get(int i) { - return (E) unsafe.getObjectVolatile(array, rawIndex(i)); + return getRaw(checkedByteOffset(i)); + } + + private E getRaw(long offset) { + return (E) unsafe.getObjectVolatile(array, offset); } /** @@ -119,7 +124,7 @@ public class AtomicReferenceArray implements java.io.Serializable { * @param newValue the new value */ public final void set(int i, E newValue) { - unsafe.putObjectVolatile(array, rawIndex(i), newValue); + unsafe.putObjectVolatile(array, checkedByteOffset(i), newValue); } /** @@ -130,7 +135,7 @@ public class AtomicReferenceArray implements java.io.Serializable { * @since 1.6 */ public final void lazySet(int i, E newValue) { - unsafe.putOrderedObject(array, rawIndex(i), newValue); + unsafe.putOrderedObject(array, checkedByteOffset(i), newValue); } @@ -143,9 +148,10 @@ public class AtomicReferenceArray implements java.io.Serializable { * @return the previous value */ public final E getAndSet(int i, E newValue) { + long offset = checkedByteOffset(i); while (true) { - E current = get(i); - if (compareAndSet(i, current, newValue)) + E current = (E) getRaw(offset); + if (compareAndSetRaw(offset, current, newValue)) return current; } } @@ -153,6 +159,7 @@ public class AtomicReferenceArray implements java.io.Serializable { /** * Atomically sets the element at position {@code i} to the given * updated value if the current value {@code ==} the expected value. + * * @param i the index * @param expect the expected value * @param update the new value @@ -160,8 +167,11 @@ public class AtomicReferenceArray implements java.io.Serializable { * the actual value was not equal to the expected value. */ public final boolean compareAndSet(int i, E expect, E update) { - return unsafe.compareAndSwapObject(array, rawIndex(i), - expect, update); + return compareAndSetRaw(checkedByteOffset(i), expect, update); + } + + private boolean compareAndSetRaw(long offset, E expect, E update) { + return unsafe.compareAndSwapObject(array, offset, expect, update); } /** @@ -183,12 +193,21 @@ public class AtomicReferenceArray implements java.io.Serializable { /** * Returns the String representation of the current values of array. - * @return the String representation of the current values of array. + * @return the String representation of the current values of array */ public String toString() { - if (array.length > 0) // force volatile read - get(0); - return Arrays.toString(array); + int iMax = array.length - 1; + if (iMax == -1) + return "[]"; + + StringBuilder b = new StringBuilder(); + b.append('['); + for (int i = 0; ; i++) { + b.append(getRaw(byteOffset(i))); + if (i == iMax) + return b.append(']').toString(); + b.append(',').append(' '); + } } } diff --git a/src/share/classes/java/util/concurrent/atomic/AtomicStampedReference.java b/src/share/classes/java/util/concurrent/atomic/AtomicStampedReference.java index 854c02c12a3114226869f6749a5be3f097391d11..412eca36eb3e5993c6442314cd54a84aa01d4d75 100644 --- a/src/share/classes/java/util/concurrent/atomic/AtomicStampedReference.java +++ b/src/share/classes/java/util/concurrent/atomic/AtomicStampedReference.java @@ -39,7 +39,7 @@ package java.util.concurrent.atomic; * An {@code AtomicStampedReference} maintains an object reference * along with an integer "stamp", that can be updated atomically. * - *

    Implementation note. This implementation maintains stamped + *

    Implementation note: This implementation maintains stamped * references by creating internal objects representing "boxed" * [reference, integer] pairs. * @@ -47,17 +47,21 @@ package java.util.concurrent.atomic; * @author Doug Lea * @param The type of object referred to by this reference */ -public class AtomicStampedReference { +public class AtomicStampedReference { - private static class ReferenceIntegerPair { - private final T reference; - private final int integer; - ReferenceIntegerPair(T r, int i) { - reference = r; integer = i; + private static class Pair { + final T reference; + final int stamp; + private Pair(T reference, int stamp) { + this.reference = reference; + this.stamp = stamp; + } + static Pair of(T reference, int stamp) { + return new Pair(reference, stamp); } } - private final AtomicReference> atomicRef; + private volatile Pair pair; /** * Creates a new {@code AtomicStampedReference} with the given @@ -67,8 +71,7 @@ public class AtomicStampedReference { * @param initialStamp the initial stamp */ public AtomicStampedReference(V initialRef, int initialStamp) { - atomicRef = new AtomicReference> - (new ReferenceIntegerPair(initialRef, initialStamp)); + pair = Pair.of(initialRef, initialStamp); } /** @@ -77,7 +80,7 @@ public class AtomicStampedReference { * @return the current value of the reference */ public V getReference() { - return atomicRef.get().reference; + return pair.reference; } /** @@ -86,7 +89,7 @@ public class AtomicStampedReference { * @return the current value of the stamp */ public int getStamp() { - return atomicRef.get().integer; + return pair.stamp; } /** @@ -98,9 +101,9 @@ public class AtomicStampedReference { * @return the current value of the reference */ public V get(int[] stampHolder) { - ReferenceIntegerPair p = atomicRef.get(); - stampHolder[0] = p.integer; - return p.reference; + Pair pair = this.pair; + stampHolder[0] = pair.stamp; + return pair.reference; } /** @@ -119,18 +122,12 @@ public class AtomicStampedReference { * @param newStamp the new value for the stamp * @return true if successful */ - public boolean weakCompareAndSet(V expectedReference, - V newReference, - int expectedStamp, - int newStamp) { - ReferenceIntegerPair current = atomicRef.get(); - return expectedReference == current.reference && - expectedStamp == current.integer && - ((newReference == current.reference && - newStamp == current.integer) || - atomicRef.weakCompareAndSet(current, - new ReferenceIntegerPair(newReference, - newStamp))); + public boolean weakCompareAndSet(V expectedReference, + V newReference, + int expectedStamp, + int newStamp) { + return compareAndSet(expectedReference, newReference, + expectedStamp, newStamp); } /** @@ -145,18 +142,17 @@ public class AtomicStampedReference { * @param newStamp the new value for the stamp * @return true if successful */ - public boolean compareAndSet(V expectedReference, - V newReference, - int expectedStamp, - int newStamp) { - ReferenceIntegerPair current = atomicRef.get(); - return expectedReference == current.reference && - expectedStamp == current.integer && + public boolean compareAndSet(V expectedReference, + V newReference, + int expectedStamp, + int newStamp) { + Pair current = pair; + return + expectedReference == current.reference && + expectedStamp == current.stamp && ((newReference == current.reference && - newStamp == current.integer) || - atomicRef.compareAndSet(current, - new ReferenceIntegerPair(newReference, - newStamp))); + newStamp == current.stamp) || + casPair(current, Pair.of(newReference, newStamp))); } @@ -167,9 +163,9 @@ public class AtomicStampedReference { * @param newStamp the new value for the stamp */ public void set(V newReference, int newStamp) { - ReferenceIntegerPair current = atomicRef.get(); - if (newReference != current.reference || newStamp != current.integer) - atomicRef.set(new ReferenceIntegerPair(newReference, newStamp)); + Pair current = pair; + if (newReference != current.reference || newStamp != current.stamp) + this.pair = Pair.of(newReference, newStamp); } /** @@ -186,11 +182,32 @@ public class AtomicStampedReference { * @return true if successful */ public boolean attemptStamp(V expectedReference, int newStamp) { - ReferenceIntegerPair current = atomicRef.get(); - return expectedReference == current.reference && - (newStamp == current.integer || - atomicRef.compareAndSet(current, - new ReferenceIntegerPair(expectedReference, - newStamp))); + Pair current = pair; + return + expectedReference == current.reference && + (newStamp == current.stamp || + casPair(current, Pair.of(expectedReference, newStamp))); + } + + // Unsafe mechanics + + private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe(); + private static final long pairOffset = + objectFieldOffset(UNSAFE, "pair", AtomicStampedReference.class); + + private boolean casPair(Pair cmp, Pair val) { + return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val); + } + + static long objectFieldOffset(sun.misc.Unsafe UNSAFE, + String field, Class klazz) { + try { + return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field)); + } catch (NoSuchFieldException e) { + // Convert Exception to corresponding Error + NoSuchFieldError error = new NoSuchFieldError(field); + error.initCause(e); + throw error; + } } } diff --git a/src/share/classes/java/util/concurrent/locks/Condition.java b/src/share/classes/java/util/concurrent/locks/Condition.java index c1774bc25dd543a7a933dec6eab831595ce4e6d9..f3fb607a47e566245a6db4e28203826d92aaa99f 100644 --- a/src/share/classes/java/util/concurrent/locks/Condition.java +++ b/src/share/classes/java/util/concurrent/locks/Condition.java @@ -308,18 +308,21 @@ public interface Condition { * condition still does not hold. Typical uses of this method take * the following form: * - *

    -     * synchronized boolean aMethod(long timeout, TimeUnit unit) {
    -     *   long nanosTimeout = unit.toNanos(timeout);
    -     *   while (!conditionBeingWaitedFor) {
    -     *     if (nanosTimeout > 0)
    -     *         nanosTimeout = theCondition.awaitNanos(nanosTimeout);
    -     *      else
    -     *        return false;
    +     *  
     {@code
    +     * boolean aMethod(long timeout, TimeUnit unit) {
    +     *   long nanos = unit.toNanos(timeout);
    +     *   lock.lock();
    +     *   try {
    +     *     while (!conditionBeingWaitedFor()) {
    +     *       if (nanos <= 0L)
    +     *         return false;
    +     *       nanos = theCondition.awaitNanos(nanos);
    +     *     }
    +     *     // ...
    +     *   } finally {
    +     *     lock.unlock();
          *   }
    -     *   // ...
    -     * }
    -     * 
    + * }}
    * *

    Design note: This method requires a nanosecond argument so * as to avoid truncation errors in reporting remaining times. @@ -408,18 +411,21 @@ public interface Condition { * *

    The return value indicates whether the deadline has elapsed, * which can be used as follows: - *

    -     * synchronized boolean aMethod(Date deadline) {
    +     *  
     {@code
    +     * boolean aMethod(Date deadline) {
          *   boolean stillWaiting = true;
    -     *   while (!conditionBeingWaitedFor) {
    -     *     if (stillWaiting)
    -     *         stillWaiting = theCondition.awaitUntil(deadline);
    -     *      else
    -     *        return false;
    +     *   lock.lock();
    +     *   try {
    +     *     while (!conditionBeingWaitedFor()) {
    +     *       if (!stillWaiting)
    +     *         return false;
    +     *       stillWaiting = theCondition.awaitUntil(deadline);
    +     *     }
    +     *     // ...
    +     *   } finally {
    +     *     lock.unlock();
          *   }
    -     *   // ...
    -     * }
    -     * 
    + * }}
    * *

    Implementation Considerations * @@ -450,6 +456,15 @@ public interface Condition { *

    If any threads are waiting on this condition then one * is selected for waking up. That thread must then re-acquire the * lock before returning from {@code await}. + * + *

    Implementation Considerations + * + *

    An implementation may (and typically does) require that the + * current thread hold the lock associated with this {@code + * Condition} when this method is called. Implementations must + * document this precondition and any actions taken if the lock is + * not held. Typically, an exception such as {@link + * IllegalMonitorStateException} will be thrown. */ void signal(); @@ -459,6 +474,15 @@ public interface Condition { *

    If any threads are waiting on this condition then they are * all woken up. Each thread must re-acquire the lock before it can * return from {@code await}. + * + *

    Implementation Considerations + * + *

    An implementation may (and typically does) require that the + * current thread hold the lock associated with this {@code + * Condition} when this method is called. Implementations must + * document this precondition and any actions taken if the lock is + * not held. Typically, an exception such as {@link + * IllegalMonitorStateException} will be thrown. */ void signalAll(); } diff --git a/src/share/classes/java/util/logging/Logger.java b/src/share/classes/java/util/logging/Logger.java index 4d822de4792010a6266a3f063f9e83af037d8852..b75caa56005a9e449f6f9db036b04a998535e8eb 100644 --- a/src/share/classes/java/util/logging/Logger.java +++ b/src/share/classes/java/util/logging/Logger.java @@ -1426,7 +1426,7 @@ public class Logger { // we didn't have a previous parent ref = manager.new LoggerWeakRef(this); } - ref.setParentRef(new WeakReference<>(parent)); + ref.setParentRef(new WeakReference(parent)); parent.kids.add(ref); // As a result of the reparenting, the effective level diff --git a/src/share/classes/javax/script/CompiledScript.java b/src/share/classes/javax/script/CompiledScript.java index da31be3bb4661ae65ed75fbd63597500b1ef244c..4a9a4ba056c92b97c030b08ca44ef52f930b76d2 100644 --- a/src/share/classes/javax/script/CompiledScript.java +++ b/src/share/classes/javax/script/CompiledScript.java @@ -107,7 +107,7 @@ public abstract class CompiledScript { } /** - * Returns the ScriptEngine wbose compile method created this CompiledScript. + * Returns the ScriptEngine whose compile method created this CompiledScript. * The CompiledScript will execute in this engine. * * @return The ScriptEngine that created this CompiledScript diff --git a/src/share/classes/javax/security/auth/PrivateCredentialPermission.java b/src/share/classes/javax/security/auth/PrivateCredentialPermission.java index e78df3fdb5b8a577c9598edda971193c2dc930b7..22cb6ef2d2ff1228685c6d28f15fa8378cf81640 100644 --- a/src/share/classes/javax/security/auth/PrivateCredentialPermission.java +++ b/src/share/classes/javax/security/auth/PrivateCredentialPermission.java @@ -329,7 +329,7 @@ public final class PrivateCredentialPermission extends Permission { throw new IllegalArgumentException("invalid empty name"); } - ArrayList pList = new ArrayList(); + ArrayList pList = new ArrayList<>(); StringTokenizer tokenizer = new StringTokenizer(name, " ", true); String principalClass = null; String principalName = null; diff --git a/src/share/classes/javax/security/auth/SubjectDomainCombiner.java b/src/share/classes/javax/security/auth/SubjectDomainCombiner.java index 9dc82fc0153a37f72c6114847a4ecec21e569f68..6ac38515e1c9a758164d7616a74ec3bbe021eed6 100644 --- a/src/share/classes/javax/security/auth/SubjectDomainCombiner.java +++ b/src/share/classes/javax/security/auth/SubjectDomainCombiner.java @@ -48,7 +48,7 @@ public class SubjectDomainCombiner implements java.security.DomainCombiner { private Subject subject; private WeakKeyValueMap cachedPDs = - new WeakKeyValueMap(); + new WeakKeyValueMap<>(); private Set principalSet; private Principal[] principals; diff --git a/src/share/classes/javax/security/auth/kerberos/DelegationPermission.java b/src/share/classes/javax/security/auth/kerberos/DelegationPermission.java index 09387897d2ec7708a474f2542dbcd2d26367f3ea..76dbf65afe0a98cc2b10f25c0b41001a4b067ee3 100644 --- a/src/share/classes/javax/security/auth/kerberos/DelegationPermission.java +++ b/src/share/classes/javax/security/auth/kerberos/DelegationPermission.java @@ -361,7 +361,7 @@ final class KrbDelegationPermissionCollection extends PermissionCollection // Don't call out.defaultWriteObject() // Write out Vector - Vector permissions = new Vector(perms.size()); + Vector permissions = new Vector<>(perms.size()); synchronized (this) { permissions.addAll(perms); diff --git a/src/share/classes/javax/security/auth/kerberos/ServicePermission.java b/src/share/classes/javax/security/auth/kerberos/ServicePermission.java index 98d2878154b83795329f82248b42e52031153b06..e9aedd09bc6be64a00e5c6e94c272bf78ef8e941 100644 --- a/src/share/classes/javax/security/auth/kerberos/ServicePermission.java +++ b/src/share/classes/javax/security/auth/kerberos/ServicePermission.java @@ -569,7 +569,7 @@ final class KrbServicePermissionCollection extends PermissionCollection // Don't call out.defaultWriteObject() // Write out Vector - Vector permissions = new Vector(perms.size()); + Vector permissions = new Vector<>(perms.size()); synchronized (this) { permissions.addAll(perms); diff --git a/src/share/classes/javax/sql/rowset/serial/SerialJavaObject.java b/src/share/classes/javax/sql/rowset/serial/SerialJavaObject.java index 0a05a01e031a98015a268c65ed5c542924b6c1f0..5aa034f6854517d3158498e4ea4d3a097a5d549d 100644 --- a/src/share/classes/javax/sql/rowset/serial/SerialJavaObject.java +++ b/src/share/classes/javax/sql/rowset/serial/SerialJavaObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,7 @@ package javax.sql.rowset.serial; -import java.sql.*; import java.io.*; -import java.util.Map; import java.lang.reflect.*; import javax.sql.rowset.RowSetWarning; @@ -51,7 +49,7 @@ public class SerialJavaObject implements Serializable, Cloneable { /** * Placeholder for object to be serialized. */ - private Object obj; + private final Object obj; /** @@ -64,8 +62,7 @@ public class SerialJavaObject implements Serializable, Cloneable { *

    * * @param obj the Java Object to be serialized - * @throws SerialException if the object is found - * to be unserializable + * @throws SerialException if the object is found not to be serializable */ public SerialJavaObject(Object obj) throws SerialException { @@ -74,16 +71,11 @@ public class SerialJavaObject implements Serializable, Cloneable { // get Class. Object instance should always be available - Class c = obj.getClass(); + Class c = obj.getClass(); // determine if object implements Serializable i/f - boolean serializableImpl = false; - Class[] theIf = c.getInterfaces(); - for (int i = 0; i < theIf.length; i++) { - String ifName = theIf[i].getName(); - if (ifName == "java.io.Serializable") { - serializableImpl = true; - } + if (!(obj instanceof java.io.Serializable)) { + setWarning(new RowSetWarning("Warning, the object passed to the constructor does not implement Serializable")); } // can only determine public fields (obviously). If @@ -93,22 +85,14 @@ public class SerialJavaObject implements Serializable, Cloneable { boolean anyStaticFields = false; fields = c.getFields(); - //fields = new Object[field.length]; for (int i = 0; i < fields.length; i++ ) { if ( fields[i].getModifiers() == Modifier.STATIC ) { anyStaticFields = true; } - //fields[i] = field[i].get(obj); - } - try { - if (!(serializableImpl)) { - throw new RowSetWarning("Test"); - } - } catch (RowSetWarning w) { - setWarning(w); } + if (anyStaticFields) { throw new SerialException("Located static fields in " + "object instance. Cannot serialize"); @@ -139,11 +123,8 @@ public class SerialJavaObject implements Serializable, Cloneable { */ public Field[] getFields() throws SerialException { if (fields != null) { - Class c = this.obj.getClass(); - //the following has to be commented before mustang integration - //return c.getFields(); - //the following has to be uncommented before mustang integration - return sun.reflect.misc.FieldUtil.getFields(c); + Class c = this.obj.getClass(); + return c.getFields(); } else { throw new SerialException("SerialJavaObject does not contain" + " a serialized object instance"); diff --git a/src/share/classes/javax/swing/AbstractButton.java b/src/share/classes/javax/swing/AbstractButton.java index aac3be32aa40530bc8751df5fe96ad7d15b70c1f..7aff31b4c6749f6bf03bac8feb57e2f8b92b99f3 100644 --- a/src/share/classes/javax/swing/AbstractButton.java +++ b/src/share/classes/javax/swing/AbstractButton.java @@ -1335,7 +1335,6 @@ public abstract class AbstractButton extends JComponent implements ItemSelectabl * * @param a the button's action * @since 1.3 - * @see Actions * @see Action * @see #setAction */ diff --git a/src/share/classes/javax/swing/JEditorPane.java b/src/share/classes/javax/swing/JEditorPane.java index acc910800860735eb366e14f37ddd914f3ce0fdf..056cc36b3942c2a36b0cb2a124284bf014a31ca7 100644 --- a/src/share/classes/javax/swing/JEditorPane.java +++ b/src/share/classes/javax/swing/JEditorPane.java @@ -145,8 +145,8 @@ import javax.accessibility.*; *

  • * One way is to specify the character set as a parameter of the MIME * type. This will be established by a call to the - * setContentType method. If the content - * is loaded by the setPage method the content + * {@link #setContentType setContentType} method. If the content + * is loaded by the {@link #setPage setPage} method the content * type will have been set according to the specification of the URL. * It the file is loaded directly, the content type would be expected to * have been set prior to loading. diff --git a/src/share/classes/javax/swing/JFileChooser.java b/src/share/classes/javax/swing/JFileChooser.java index eb67589e15c3545ea759884ad3970816c0321f88..3715ca0f43b5eb252276c8d9f4262939869358c7 100644 --- a/src/share/classes/javax/swing/JFileChooser.java +++ b/src/share/classes/javax/swing/JFileChooser.java @@ -256,10 +256,6 @@ public class JFileChooser extends JComponent implements Accessible { private FileView fileView = null; - // uiFileView is not serialized, as it is initialized - // by updateUI() after deserialization - private transient FileView uiFileView = null; - private boolean controlsShown = true; private boolean useFileHiding = true; @@ -1504,6 +1500,9 @@ public class JFileChooser extends JComponent implements Accessible { if(getFileView() != null) { filename = getFileView().getName(f); } + + FileView uiFileView = getUI().getFileView(this); + if(filename == null && uiFileView != null) { filename = uiFileView.getName(f); } @@ -1524,6 +1523,9 @@ public class JFileChooser extends JComponent implements Accessible { if(getFileView() != null) { description = getFileView().getDescription(f); } + + FileView uiFileView = getUI().getFileView(this); + if(description == null && uiFileView != null) { description = uiFileView.getDescription(f); } @@ -1544,6 +1546,9 @@ public class JFileChooser extends JComponent implements Accessible { if(getFileView() != null) { typeDescription = getFileView().getTypeDescription(f); } + + FileView uiFileView = getUI().getFileView(this); + if(typeDescription == null && uiFileView != null) { typeDescription = uiFileView.getTypeDescription(f); } @@ -1564,6 +1569,9 @@ public class JFileChooser extends JComponent implements Accessible { if(getFileView() != null) { icon = getFileView().getIcon(f); } + + FileView uiFileView = getUI().getFileView(this); + if(icon == null && uiFileView != null) { icon = uiFileView.getIcon(f); } @@ -1584,6 +1592,9 @@ public class JFileChooser extends JComponent implements Accessible { if (getFileView() != null) { traversable = getFileView().isTraversable(f); } + + FileView uiFileView = getUI().getFileView(this); + if (traversable == null && uiFileView != null) { traversable = uiFileView.isTraversable(f); } @@ -1791,7 +1802,6 @@ public class JFileChooser extends JComponent implements Accessible { } setUI(ui); - uiFileView = getUI().getFileView(this); if(isAcceptAllFileFilterUsed()) { addChoosableFileFilter(getAcceptAllFileFilter()); } diff --git a/src/share/classes/javax/swing/SizeSequence.java b/src/share/classes/javax/swing/SizeSequence.java index 5667a66ce08e2e727886d48d4c946d2dbd2b9467..1ec97520827852bb76babcf37a0d80bfdacf4a80 100644 --- a/src/share/classes/javax/swing/SizeSequence.java +++ b/src/share/classes/javax/swing/SizeSequence.java @@ -132,7 +132,7 @@ public class SizeSequence { * can use insertEntries or setSizes. * * @see #insertEntries - * @see #setSizes + * @see #setSizes(int[]) */ public SizeSequence() { a = emptyArray; diff --git a/src/share/classes/javax/swing/TransferHandler.java b/src/share/classes/javax/swing/TransferHandler.java index 4854fdc75bf37bb4fe45db65d171c247e25d6d16..eb7f8d1a644a3678d3bb7e5374d2b92e780f8619 100644 --- a/src/share/classes/javax/swing/TransferHandler.java +++ b/src/share/classes/javax/swing/TransferHandler.java @@ -344,7 +344,7 @@ public class TransferHandler implements Serializable { * * @return the drop location * @throws IllegalStateException if this is not a drop - * @see #isDrop + * @see #isDrop() */ public DropLocation getDropLocation() { assureIsDrop(); @@ -380,7 +380,7 @@ public class TransferHandler implements Serializable { * * @param showDropLocation whether or not to indicate the drop location * @throws IllegalStateException if this is not a drop - * @see #isDrop + * @see #isDrop() */ public void setShowDropLocation(boolean showDropLocation) { assureIsDrop(); @@ -406,7 +406,7 @@ public class TransferHandler implements Serializable { * @see #getDropAction * @see #getUserDropAction * @see #getSourceDropActions - * @see #isDrop + * @see #isDrop() */ public void setDropAction(int dropAction) { assureIsDrop(); @@ -440,7 +440,7 @@ public class TransferHandler implements Serializable { * @throws IllegalStateException if this is not a drop * @see #setDropAction * @see #getUserDropAction - * @see #isDrop + * @see #isDrop() */ public int getDropAction() { return dropAction == -1 ? getUserDropAction() : dropAction; @@ -468,7 +468,7 @@ public class TransferHandler implements Serializable { * @throws IllegalStateException if this is not a drop * @see #setDropAction * @see #getDropAction - * @see #isDrop + * @see #isDrop() */ public int getUserDropAction() { assureIsDrop(); @@ -501,7 +501,7 @@ public class TransferHandler implements Serializable { * * @return the drag source's supported drop actions * @throws IllegalStateException if this is not a drop - * @see #isDrop + * @see #isDrop() */ public int getSourceDropActions() { assureIsDrop(); diff --git a/src/share/classes/javax/swing/event/InternalFrameAdapter.java b/src/share/classes/javax/swing/event/InternalFrameAdapter.java index 071942e8ca7786672509c8b39a8b78dc814963c4..47ed2c69c9588aff68808f9550072d3595041193 100644 --- a/src/share/classes/javax/swing/event/InternalFrameAdapter.java +++ b/src/share/classes/javax/swing/event/InternalFrameAdapter.java @@ -32,8 +32,7 @@ package javax.swing.event; * equivalent to the WindowAdapter class in the AWT. *

    * See How to Write an Internal Frame Listener - * in The Java Tutorial and - * The Java Class Libraries (update) + * in The Java Tutorial * * @see InternalFrameEvent * @see InternalFrameListener diff --git a/src/share/classes/javax/swing/event/InternalFrameListener.java b/src/share/classes/javax/swing/event/InternalFrameListener.java index 22258be8b8b093fa7bc2b9725c6029b7b12af4f2..c156767725fe81adf395f21c355ffcbc610c7de5 100644 --- a/src/share/classes/javax/swing/event/InternalFrameListener.java +++ b/src/share/classes/javax/swing/event/InternalFrameListener.java @@ -33,9 +33,7 @@ import java.util.EventListener; * in the AWT. *

    * See How to Write an Internal Frame Listener - * in The Java Tutorial and - * The Java Class Libraries (update) - * for further documentation. + * in The Java Tutorial for further documentation. * * @see java.awt.event.WindowListener * diff --git a/src/share/classes/javax/swing/plaf/multi/doc-files/multi_tsc.html b/src/share/classes/javax/swing/plaf/multi/doc-files/multi_tsc.html index c86476b19c4a3b989090fc53e434956e7a4af80a..5160494f7506027034149098e0f9530de03f110a 100644 --- a/src/share/classes/javax/swing/plaf/multi/doc-files/multi_tsc.html +++ b/src/share/classes/javax/swing/plaf/multi/doc-files/multi_tsc.html @@ -66,7 +66,7 @@ This document has the following sections: Before reading further, you should be familiar with the concept of pluggable look and feels. For basic information, see -Choosing the Look and Feel, +How to Set the Look and Feel, a section in The Java Tutorial. For architectural details, you can read diff --git a/src/share/classes/javax/swing/plaf/synth/doc-files/synthFileFormat.html b/src/share/classes/javax/swing/plaf/synth/doc-files/synthFileFormat.html index f5f66a2d2a1fddd60a042ea53cc85807fc600261..dfb99f4ef50700f79a77f4aee8a31285cb2ab66a 100644 --- a/src/share/classes/javax/swing/plaf/synth/doc-files/synthFileFormat.html +++ b/src/share/classes/javax/swing/plaf/synth/doc-files/synthFileFormat.html @@ -91,7 +91,7 @@ div.example {

     <!ELEMENT style (property | defaultsProperty | state | font | graphicsUtils |
    -                 insets | painter | imagePainter | opaque | (%beansPersistance;) |
    +                 insets | painter | imagePainter | opaque | (%beansPersistance;) |
                      imageIcon)*>
     <!ATTLIST style
               id              ID          #IMPLIED
    @@ -250,8 +250,8 @@ div.example {
         

    Defines the font for the current state, or style. You must - specify either an idref or a - name and size. + specify either an idref or a + name and size.

    The following example creates a style with a Font of @@ -797,7 +797,7 @@ div.example { path CDATA #REQUIRED sourceInsets CDATA #IMPLIED destinationInsets CDATA #IMPLIED - paintCenter (true|false) "true" + paintCenter (true|false) "true" stretch (true|false) "true" center (true|false) "false" > diff --git a/src/share/classes/javax/swing/text/AsyncBoxView.java b/src/share/classes/javax/swing/text/AsyncBoxView.java index 00cd059cc2395d472f630360e97bf2499fc85c51..ab3f9c34d1e88ef0af4301aa0a63e18a59ed1451 100644 --- a/src/share/classes/javax/swing/text/AsyncBoxView.java +++ b/src/share/classes/javax/swing/text/AsyncBoxView.java @@ -384,7 +384,7 @@ public class AsyncBoxView extends View { /** * Loads all of the children to initialize the view. - * This is called by the setParent + * This is called by the {@link #setParent setParent} * method. Subclasses can reimplement this to initialize * their child views in a different manner. The default * implementation creates a child view for each diff --git a/src/share/classes/javax/swing/text/DefaultCaret.java b/src/share/classes/javax/swing/text/DefaultCaret.java index 7a3a2807bbbeccd5351ac3c12d833d6019be9678..b51cd4012c896fe897016fb61efd0cb1e563aa14 100644 --- a/src/share/classes/javax/swing/text/DefaultCaret.java +++ b/src/share/classes/javax/swing/text/DefaultCaret.java @@ -70,7 +70,7 @@ import sun.swing.SwingUtilities2; * will render a solid color as specified in the associated text component * in the SelectionColor property. This can easily be changed * by reimplementing the - * getSelectionHighlighter + * {@link #getSelectionPainter getSelectionPainter} * method. *

    * A customized caret appearance can be achieved by reimplementing diff --git a/src/share/classes/javax/swing/text/TableView.java b/src/share/classes/javax/swing/text/TableView.java index 3c15ba0f41d9c2a9cf81341db8ee439730a3344c..bab545c7af5f9a79e7c4b3b5a96e304a8f101d76 100644 --- a/src/share/classes/javax/swing/text/TableView.java +++ b/src/share/classes/javax/swing/text/TableView.java @@ -315,7 +315,7 @@ public abstract class TableView extends BoxView { * updated along the minor axis. *

    * This is implemented to call the - * layoutColumns method, and then + * {@link #layoutColumns layoutColumns} method, and then * forward to the superclass to actually carry out the layout * of the tables rows. * diff --git a/src/share/classes/javax/swing/text/View.java b/src/share/classes/javax/swing/text/View.java index 369907d2e634d03b97e368b643a46050945d0666..38573feba176514cb19d7e1d61072b5d94b29281 100644 --- a/src/share/classes/javax/swing/text/View.java +++ b/src/share/classes/javax/swing/text/View.java @@ -117,7 +117,7 @@ A view has the following responsibilities: what it is prepared to deal with.

  • The coordinate system is the same as the hosting Component (i.e. the Component returned by the - getContainer method). + {@link #getContainer getContainer} method). This means a child view lives in the same coordinate system as the parent view unless the parent has explicitly changed the coordinate system. To schedule itself to be repainted a view can call repaint on the hosting @@ -180,9 +180,9 @@ A view has the following responsibilities: starting from the root of the view hierarchy. The methods for doing this are:

    @@ -497,6 +497,10 @@ public abstract class View implements SwingConstants { public int getNextVisualPositionFrom(int pos, Position.Bias b, Shape a, int direction, Position.Bias[] biasRet) throws BadLocationException { + if (pos < -1) { + // -1 is a reserved value, see the code below + throw new BadLocationException("Invalid position", pos); + } biasRet[0] = Position.Bias.Forward; switch (direction) { @@ -670,15 +674,15 @@ public abstract class View implements SwingConstants { * spread out into the following calls that subclasses can * reimplement: *

      - *
    1. updateChildren is called + *
    2. {@link #updateChildren updateChildren} is called * if there were any changes to the element this view is * responsible for. If this view has child views that are * represent the child elements, then this method should do * whatever is necessary to make sure the child views correctly * represent the model. - *
    3. forwardUpdate is called + *
    4. {@link #forwardUpdate forwardUpdate} is called * to forward the DocumentEvent to the appropriate child views. - *
    5. updateLayout is called to + *
    6. {@link #updateLayout updateLayout} is called to * give the view a chance to either repair its layout, to reschedule * layout, or do nothing. *
    @@ -711,15 +715,15 @@ public abstract class View implements SwingConstants { * spread out into the following calls that subclasses can * reimplement: *
      - *
    1. updateChildren is called + *
    2. {@link #updateChildren updateChildren} is called * if there were any changes to the element this view is * responsible for. If this view has child views that are * represent the child elements, then this method should do * whatever is necessary to make sure the child views correctly * represent the model. - *
    3. forwardUpdate is called + *
    4. {@link #forwardUpdate forwardUpdate} is called * to forward the DocumentEvent to the appropriate child views. - *
    5. updateLayout is called to + *
    6. {@link #updateLayout updateLayout} is called to * give the view a chance to either repair its layout, to reschedule * layout, or do nothing. *
    @@ -752,15 +756,15 @@ public abstract class View implements SwingConstants { * spread out into the following calls that subclasses can * reimplement: *
      - *
    1. updateChildren is called + *
    2. {@link #updateChildren updateChildren} is called * if there were any changes to the element this view is * responsible for. If this view has child views that are * represent the child elements, then this method should do * whatever is necessary to make sure the child views correctly * represent the model. - *
    3. forwardUpdate is called + *
    4. {@link #forwardUpdate forwardUpdate} is called * to forward the DocumentEvent to the appropriate child views. - *
    5. updateLayout is called to + *
    6. {@link #updateLayout updateLayout} is called to * give the view a chance to either repair its layout, to reschedule * layout, or do nothing. *
    @@ -1186,7 +1190,7 @@ public abstract class View implements SwingConstants { * simply messages the view with a call to insertUpdate, * removeUpdate, or changedUpdate depending * upon the type of the event. This is called by - * forwardUpdate to forward + * {@link #forwardUpdate forwardUpdate} to forward * the event to children that need it. * * @param v the child view to forward the event to diff --git a/src/share/classes/javax/swing/text/html/HTMLEditorKit.java b/src/share/classes/javax/swing/text/html/HTMLEditorKit.java index f9642c7bdd75488221443683b66305e8edf2b94c..1c5275e77a3871807183e963bfd7d31e5b8ffc61 100644 --- a/src/share/classes/javax/swing/text/html/HTMLEditorKit.java +++ b/src/share/classes/javax/swing/text/html/HTMLEditorKit.java @@ -123,7 +123,7 @@ import java.lang.ref.*; * to load. By default, this kit produces documents that will be * loaded asynchronously if loaded using JEditorPane.setPage. * This is controlled by a property on the document. The method - * createDefaultDocument can + * {@link #createDefaultDocument createDefaultDocument} can * be overriden to change this. The batching of work is done * by the HTMLDocument.HTMLReader class. The actual * work is done by the DefaultStyledDocument and @@ -558,7 +558,7 @@ public class HTMLEditorKit extends StyledEditorKit implements Accessible { * automatically or only FormSubmitEvent is fired. * By default it is set to true. * - * @see #isAutoFormSubmission + * @see #isAutoFormSubmission() * @see FormSubmitEvent * @since 1.5 */ diff --git a/src/share/classes/javax/swing/text/html/ParagraphView.java b/src/share/classes/javax/swing/text/html/ParagraphView.java index f0ee60ea700d3a4c53aa413c593c78453343bbbf..e180e0e112eb7b9a3c1e3905a3e9f2ef8003bd64 100644 --- a/src/share/classes/javax/swing/text/html/ParagraphView.java +++ b/src/share/classes/javax/swing/text/html/ParagraphView.java @@ -61,7 +61,7 @@ public class ParagraphView extends javax.swing.text.ParagraphView { *

    * This is implemented * to forward to the superclass as well as call the - * setPropertiesFromAttributes + * {@link #setPropertiesFromAttributes setPropertiesFromAttributes} * method to set the paragraph properties from the css * attributes. The call is made at this time to ensure * the ability to resolve upward through the parents diff --git a/src/share/classes/javax/swing/text/html/StyleSheet.java b/src/share/classes/javax/swing/text/html/StyleSheet.java index 8d5bab2151577819ebdc9bdabe05b13bc006e0f4..e82a5dc8ac9858ac7fa8cb29fd95b2c7e8514467 100644 --- a/src/share/classes/javax/swing/text/html/StyleSheet.java +++ b/src/share/classes/javax/swing/text/html/StyleSheet.java @@ -51,7 +51,7 @@ import javax.swing.text.*; *

    * The primary entry point for HTML View implementations * to get their attributes is the - * getViewAttributes + * {@link #getViewAttributes getViewAttributes} * method. This should be implemented to establish the * desired policy used to associate attributes with the view. * Each HTMLEditorKit (i.e. and therefore each associated diff --git a/src/share/classes/javax/swing/text/html/parser/ParserDelegator.java b/src/share/classes/javax/swing/text/html/parser/ParserDelegator.java index 06b53483dc082b91319b9502eeba04a6c3d0c645..f8aa19f9b0378f4775937bcfa9457887d78b2bca 100644 --- a/src/share/classes/javax/swing/text/html/parser/ParserDelegator.java +++ b/src/share/classes/javax/swing/text/html/parser/ParserDelegator.java @@ -48,7 +48,11 @@ public class ParserDelegator extends HTMLEditorKit.Parser implements Serializabl private static final Object DTD_KEY = new Object(); - protected static synchronized void setDefaultDTD() { + protected static void setDefaultDTD() { + getDefaultDTD(); + } + + private static synchronized DTD getDefaultDTD() { AppContext appContext = AppContext.getAppContext(); DTD dtd = (DTD) appContext.get(DTD_KEY); @@ -67,6 +71,8 @@ public class ParserDelegator extends HTMLEditorKit.Parser implements Serializabl appContext.put(DTD_KEY, dtd); } + + return dtd; } protected static DTD createDTD(DTD dtd, String name) { @@ -92,7 +98,7 @@ public class ParserDelegator extends HTMLEditorKit.Parser implements Serializabl } public void parse(Reader r, HTMLEditorKit.ParserCallback cb, boolean ignoreCharSet) throws IOException { - new DocumentParser((DTD) AppContext.getAppContext().get(DTD_KEY)).parse(r, cb, ignoreCharSet); + new DocumentParser(getDefaultDTD()).parse(r, cb, ignoreCharSet); } /** diff --git a/src/share/classes/sun/applet/AppletClassLoader.java b/src/share/classes/sun/applet/AppletClassLoader.java index 730134007b194da098a24eaa9b2a48ec21dc2f4a..40fd6b28903381c7a309c1fb820c613894d5885a 100644 --- a/src/share/classes/sun/applet/AppletClassLoader.java +++ b/src/share/classes/sun/applet/AppletClassLoader.java @@ -663,13 +663,15 @@ public class AppletClassLoader extends URLClassLoader { // set the context class loader to the AppletClassLoader. creatorThread.setContextClassLoader(AppletClassLoader.this); - synchronized(creatorThread.syncObject) { - creatorThread.start(); - try { - creatorThread.syncObject.wait(); - } catch (InterruptedException e) { } - appContext = creatorThread.appContext; - } + creatorThread.start(); + try { + synchronized(creatorThread.syncObject) { + while (!creatorThread.created) { + creatorThread.syncObject.wait(); + } + } + } catch (InterruptedException e) { } + appContext = creatorThread.appContext; return null; } }); @@ -854,14 +856,16 @@ public void grab() { class AppContextCreator extends Thread { Object syncObject = new Object(); AppContext appContext = null; + volatile boolean created = false; AppContextCreator(ThreadGroup group) { super(group, "AppContextCreator"); } public void run() { - synchronized(syncObject) { - appContext = SunToolkit.createNewAppContext(); + appContext = SunToolkit.createNewAppContext(); + created = true; + synchronized(syncObject) { syncObject.notifyAll(); } } // run() diff --git a/src/share/classes/sun/awt/SunToolkit.java b/src/share/classes/sun/awt/SunToolkit.java index 0442aeeaba61a4ab268516ffd2769104fe63469b..b3067aeba2e03fd7501e75be508d62bcfe26813d 100644 --- a/src/share/classes/sun/awt/SunToolkit.java +++ b/src/share/classes/sun/awt/SunToolkit.java @@ -696,7 +696,9 @@ public abstract class SunToolkit extends Toolkit synchronized (lock) { executeOnEventHandlerThread(event); - lock.wait(); + while(!event.isDispatched()) { + lock.wait(); + } } Throwable eventThrowable = event.getThrowable(); diff --git a/src/share/classes/sun/awt/image/ImageFetcher.java b/src/share/classes/sun/awt/image/ImageFetcher.java index 083ba79841b01bfd990a1e5299f0cfeedcdc4289..5b1293fb04368b2b41adc08a7da93a94f4d9d972 100644 --- a/src/share/classes/sun/awt/image/ImageFetcher.java +++ b/src/share/classes/sun/awt/image/ImageFetcher.java @@ -61,8 +61,10 @@ class ImageFetcher extends Thread { /** * Adds an ImageFetchable to the queue of items to fetch. Instantiates * a new ImageFetcher if it's reasonable to do so. + * If there is no available fetcher to process an ImageFetchable, then + * reports failure to caller. */ - public static void add(ImageFetchable src) { + public static boolean add(ImageFetchable src) { final FetcherInfo info = FetcherInfo.getFetcherInfo(); synchronized(info.waitList) { if (!info.waitList.contains(src)) { @@ -71,9 +73,23 @@ class ImageFetcher extends Thread { info.numFetchers < info.fetchers.length) { createFetchers(info); } - info.waitList.notify(); + /* Creation of new fetcher may fail due to high vm load + * or some other reason. + * If there is already exist, but busy, fetcher, we leave + * the src in queue (it will be handled by existing + * fetcher later). + * Otherwise, we report failure: there is no fetcher + * to handle the src. + */ + if (info.numFetchers > 0) { + info.waitList.notify(); + } else { + info.waitList.removeElement(src); + return false; + } } } + return true; } /** @@ -291,11 +307,15 @@ class ImageFetcher extends Thread { public Object run() { for (int i = 0; i < info.fetchers.length; i++) { if (info.fetchers[i] == null) { - info.fetchers[i] = new ImageFetcher( + ImageFetcher f = new ImageFetcher( fetcherGroup, i); - info.fetchers[i].start(); - info.numFetchers++; - break; + try { + f.start(); + info.fetchers[i] = f; + info.numFetchers++; + break; + } catch (Error e) { + } } } return null; diff --git a/src/share/classes/sun/awt/image/InputStreamImageSource.java b/src/share/classes/sun/awt/image/InputStreamImageSource.java index e2aecb3073c44e58afbb95c8fa70d4b4bc9e776b..7d0b7eaf43b734c8002830674a42fccabd178ea9 100644 --- a/src/share/classes/sun/awt/image/InputStreamImageSource.java +++ b/src/share/classes/sun/awt/image/InputStreamImageSource.java @@ -164,8 +164,13 @@ public abstract class InputStreamImageSource implements ImageProducer, private synchronized void startProduction() { if (!awaitingFetch) { - ImageFetcher.add(this); - awaitingFetch = true; + if (ImageFetcher.add(this)) { + awaitingFetch = true; + } else { + ImageConsumerQueue cq = consumers; + consumers = null; + errorAllConsumers(cq, false); + } } } diff --git a/src/share/classes/sun/font/FontUtilities.java b/src/share/classes/sun/font/FontUtilities.java index ef53c60de0866de3c70d6d132e1925f92998afc8..6f3c6d12a14d6fab2af8324b6ff0063eca4580cb 100644 --- a/src/share/classes/sun/font/FontUtilities.java +++ b/src/share/classes/sun/font/FontUtilities.java @@ -30,6 +30,8 @@ import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.InputStreamReader; +import java.lang.ref.SoftReference; +import java.util.concurrent.ConcurrentHashMap; import java.security.AccessController; import java.security.PrivilegedAction; @@ -383,6 +385,10 @@ public final class FontUtilities { * } * return fuir; */ + private static volatile + SoftReference> + compMapRef = new SoftReference(null); + public static FontUIResource getCompositeFontUIResource(Font font) { FontUIResource fuir = new FontUIResource(font); @@ -402,12 +408,22 @@ public final class FontUtilities { FontManager fm = FontManagerFactory.getInstance(); CompositeFont dialog2D = - (CompositeFont) fm.findFont2D("dialog", font.getStyle(), FontManager.NO_FALLBACK); + (CompositeFont) fm.findFont2D("dialog", font.getStyle(), + FontManager.NO_FALLBACK); if (dialog2D == null) { /* shouldn't happen */ return fuir; } PhysicalFont physicalFont = (PhysicalFont)font2D; - CompositeFont compFont = new CompositeFont(physicalFont, dialog2D); + ConcurrentHashMap compMap = compMapRef.get(); + if (compMap == null) { // Its been collected. + compMap = new ConcurrentHashMap(); + compMapRef = new SoftReference(compMap); + } + CompositeFont compFont = compMap.get(physicalFont); + if (compFont == null) { + compFont = new CompositeFont(physicalFont, dialog2D); + compMap.put(physicalFont, compFont); + } FontAccess.getFontAccess().setFont2D(fuir, compFont.handle); /* marking this as a created font is needed as only created fonts * copy their creator's handles. diff --git a/src/share/classes/sun/java2d/pisces/Curve.java b/src/share/classes/sun/java2d/pisces/Curve.java index e613a264cbfe8a5dcbbf05a9e7eab9900eecee35..0cd59fba3b756ad72a46f8ef68614c92687570ba 100644 --- a/src/share/classes/sun/java2d/pisces/Curve.java +++ b/src/share/classes/sun/java2d/pisces/Curve.java @@ -27,7 +27,7 @@ package sun.java2d.pisces; import java.util.Iterator; -class Curve { +final class Curve { float ax, ay, bx, by, cx, cy, dx, dy; float dax, day, dbx, dby; @@ -101,14 +101,6 @@ class Curve { return t * (t * day + dby) + cy; } - private float ddxat(float t) { - return 2 * dax * t + dbx; - } - - private float ddyat(float t) { - return 2 * day * t + dby; - } - int dxRoots(float[] roots, int off) { return Helpers.quadraticRoots(dax, dbx, cx, roots, off); } @@ -131,17 +123,17 @@ class Curve { // finds points where the first and second derivative are // perpendicular. This happens when g(t) = f'(t)*f''(t) == 0 (where // * is a dot product). Unfortunately, we have to solve a cubic. - private int perpendiculardfddf(float[] pts, int off, final float err) { + private int perpendiculardfddf(float[] pts, int off) { assert pts.length >= off + 4; - // these are the coefficients of g(t): + // these are the coefficients of some multiple of g(t) (not g(t), + // because the roots of a polynomial are not changed after multiplication + // by a constant, and this way we save a few multiplications). final float a = 2*(dax*dax + day*day); final float b = 3*(dax*dbx + day*dby); final float c = 2*(dax*cx + day*cy) + dbx*dbx + dby*dby; final float d = dbx*cx + dby*cy; - // TODO: We might want to divide the polynomial by a to make the - // coefficients smaller. This won't change the roots. - return Helpers.cubicRootsInAB(a, b, c, d, pts, off, err, 0f, 1f); + return Helpers.cubicRootsInAB(a, b, c, d, pts, off, 0f, 1f); } // Tries to find the roots of the function ROC(t)-w in [0, 1). It uses @@ -161,7 +153,7 @@ class Curve { // no OOB exception, because by now off<=6, and roots.length >= 10 assert off <= 6 && roots.length >= 10; int ret = off; - int numPerpdfddf = perpendiculardfddf(roots, off, err); + int numPerpdfddf = perpendiculardfddf(roots, off); float t0 = 0, ft0 = ROCsq(t0) - w*w; roots[off + numPerpdfddf] = 1f; // always check interval end points numPerpdfddf++; @@ -189,8 +181,9 @@ class Curve { // A slight modification of the false position algorithm on wikipedia. // This only works for the ROCsq-x functions. It might be nice to have // the function as an argument, but that would be awkward in java6. - // It is something to consider for java7, depending on how closures - // and function objects turn out. Same goes for the newton's method + // TODO: It is something to consider for java8 (or whenever lambda + // expressions make it into the language), depending on how closures + // and turn out. Same goes for the newton's method // algorithm in Helpers.java private float falsePositionROCsqMinusX(float x0, float x1, final float x, final float err) @@ -203,7 +196,7 @@ class Curve { for (int i = 0; i < iterLimit && Math.abs(t - s) > err * Math.abs(t + s); i++) { r = (fs * t - ft * s) / (fs - ft); fr = ROCsq(r) - x; - if (fr * ft > 0) {// have the same sign + if (sameSign(fr, ft)) { ft = fr; t = r; if (side < 0) { fs /= (1 << (-side)); @@ -226,55 +219,65 @@ class Curve { return r; } + private static boolean sameSign(double x, double y) { + // another way is to test if x*y > 0. This is bad for small x, y. + return (x < 0 && y < 0) || (x > 0 && y > 0); + } + // returns the radius of curvature squared at t of this curve // see http://en.wikipedia.org/wiki/Radius_of_curvature_(applications) private float ROCsq(final float t) { - final float dx = dxat(t); - final float dy = dyat(t); - final float ddx = ddxat(t); - final float ddy = ddyat(t); + // dx=xat(t) and dy=yat(t). These calls have been inlined for efficiency + final float dx = t * (t * dax + dbx) + cx; + final float dy = t * (t * day + dby) + cy; + final float ddx = 2 * dax * t + dbx; + final float ddy = 2 * day * t + dby; final float dx2dy2 = dx*dx + dy*dy; final float ddx2ddy2 = ddx*ddx + ddy*ddy; final float ddxdxddydy = ddx*dx + ddy*dy; - float ret = ((dx2dy2*dx2dy2) / (dx2dy2 * ddx2ddy2 - ddxdxddydy*ddxdxddydy))*dx2dy2; - return ret; + return dx2dy2*((dx2dy2*dx2dy2) / (dx2dy2 * ddx2ddy2 - ddxdxddydy*ddxdxddydy)); } - // curve to be broken should be in pts[0] - // this will change the contents of both pts and Ts + // curve to be broken should be in pts + // this will change the contents of pts but not Ts // TODO: There's no reason for Ts to be an array. All we need is a sequence // of t values at which to subdivide. An array statisfies this condition, // but is unnecessarily restrictive. Ts should be an Iterator instead. // Doing this will also make dashing easier, since we could easily make // LengthIterator an Iterator and feed it to this function to simplify // the loop in Dasher.somethingTo. - static Iterator breakPtsAtTs(final float[][] pts, final int type, + static Iterator breakPtsAtTs(final float[] pts, final int type, final float[] Ts, final int numTs) { - assert pts.length >= 2 && pts[0].length >= 8 && numTs <= Ts.length; - return new Iterator() { - int nextIdx = 0; + assert pts.length >= 2*type && numTs <= Ts.length; + return new Iterator() { + // these prevent object creation and destruction during autoboxing. + // Because of this, the compiler should be able to completely + // eliminate the boxing costs. + final Integer i0 = 0; + final Integer itype = type; int nextCurveIdx = 0; + Integer curCurveOff = i0; float prevT = 0; @Override public boolean hasNext() { return nextCurveIdx < numTs + 1; } - @Override public float[] next() { - float[] ret; + @Override public Integer next() { + Integer ret; if (nextCurveIdx < numTs) { float curT = Ts[nextCurveIdx]; float splitT = (curT - prevT) / (1 - prevT); Helpers.subdivideAt(splitT, - pts[nextIdx], 0, - pts[nextIdx], 0, - pts[1-nextIdx], 0, type); - updateTs(Ts, Ts[nextCurveIdx], nextCurveIdx + 1, numTs - nextCurveIdx - 1); - ret = pts[nextIdx]; - nextIdx = 1 - nextIdx; + pts, curCurveOff, + pts, 0, + pts, type, type); + prevT = curT; + ret = i0; + curCurveOff = itype; } else { - ret = pts[nextIdx]; + ret = curCurveOff; } nextCurveIdx++; return ret; @@ -283,12 +286,5 @@ class Curve { @Override public void remove() {} }; } - - // precondition: ts[off]...ts[off+len-1] must all be greater than t. - private static void updateTs(float[] ts, final float t, final int off, final int len) { - for (int i = off; i < off + len; i++) { - ts[i] = (ts[i] - t) / (1 - t); - } - } } diff --git a/src/share/classes/sun/java2d/pisces/Dasher.java b/src/share/classes/sun/java2d/pisces/Dasher.java index 0dd75a3c0a9bb9e7574d4c138faabe561447b861..533375b5fe369f43ffc42c5c759f9ed7146ad001 100644 --- a/src/share/classes/sun/java2d/pisces/Dasher.java +++ b/src/share/classes/sun/java2d/pisces/Dasher.java @@ -38,7 +38,7 @@ import sun.awt.geom.PathConsumer2D; * semantics are unclear. * */ -public class Dasher implements sun.awt.geom.PathConsumer2D { +final class Dasher implements sun.awt.geom.PathConsumer2D { private final PathConsumer2D out; private final float[] dash; @@ -169,7 +169,7 @@ public class Dasher implements sun.awt.geom.PathConsumer2D { float dx = x1 - x0; float dy = y1 - y0; - float len = (float) Math.hypot(dx, dy); + float len = (float) Math.sqrt(dx*dx + dy*dy); if (len == 0) { return; @@ -226,7 +226,7 @@ public class Dasher implements sun.awt.geom.PathConsumer2D { return; } if (li == null) { - li = new LengthIterator(4, 0.0001f); + li = new LengthIterator(4, 0.01f); } li.initializeIterationOnCurve(curCurvepts, type); @@ -237,9 +237,9 @@ public class Dasher implements sun.awt.geom.PathConsumer2D { while ((t = li.next(leftInThisDashSegment)) < 1) { if (t != 0) { Helpers.subdivideAt((t - lastSplitT) / (1 - lastSplitT), - curCurvepts, curCurveoff, - curCurvepts, 0, - curCurvepts, type, type); + curCurvepts, curCurveoff, + curCurvepts, 0, + curCurvepts, type, type); lastSplitT = t; goTo(curCurvepts, 2, type); curCurveoff = type; @@ -307,6 +307,11 @@ public class Dasher implements sun.awt.geom.PathConsumer2D { private int recLevel; private boolean done; + // the lengths of the lines of the control polygon. Only its first + // curveType/2 - 1 elements are valid. This is an optimization. See + // next(float) for more detail. + private float[] curLeafCtrlPolyLengths = new float[3]; + public LengthIterator(int reclimit, float err) { this.limit = reclimit; this.minTincrement = 1f / (1 << limit); @@ -344,11 +349,52 @@ public class Dasher implements sun.awt.geom.PathConsumer2D { this.lastSegLen = 0; } + // 0 == false, 1 == true, -1 == invalid cached value. + private int cachedHaveLowAcceleration = -1; + + private boolean haveLowAcceleration(float err) { + if (cachedHaveLowAcceleration == -1) { + final float len1 = curLeafCtrlPolyLengths[0]; + final float len2 = curLeafCtrlPolyLengths[1]; + // the test below is equivalent to !within(len1/len2, 1, err). + // It is using a multiplication instead of a division, so it + // should be a bit faster. + if (!Helpers.within(len1, len2, err*len2)) { + cachedHaveLowAcceleration = 0; + return false; + } + if (curveType == 8) { + final float len3 = curLeafCtrlPolyLengths[2]; + // if len1 is close to 2 and 2 is close to 3, that probably + // means 1 is close to 3 so the second part of this test might + // not be needed, but it doesn't hurt to include it. + if (!(Helpers.within(len2, len3, err*len3) && + Helpers.within(len1, len3, err*len3))) { + cachedHaveLowAcceleration = 0; + return false; + } + } + cachedHaveLowAcceleration = 1; + return true; + } + + return (cachedHaveLowAcceleration == 1); + } + + // we want to avoid allocations/gc so we keep this array so we + // can put roots in it, + private float[] nextRoots = new float[4]; + + // caches the coefficients of the current leaf in its flattened + // form (see inside next() for what that means). The cache is + // invalid when it's third element is negative, since in any + // valid flattened curve, this would be >= 0. + private float[] flatLeafCoefCache = new float[] {0, 0, -1, 0}; // returns the t value where the remaining curve should be split in // order for the left subdivided curve to have length len. If len // is >= than the length of the uniterated curve, it returns 1. - public float next(float len) { - float targetLength = lenAtLastSplit + len; + public float next(final float len) { + final float targetLength = lenAtLastSplit + len; while(lenAtNextT < targetLength) { if (done) { lastSegLen = lenAtNextT - lenAtLastSplit; @@ -357,8 +403,46 @@ public class Dasher implements sun.awt.geom.PathConsumer2D { goToNextLeaf(); } lenAtLastSplit = targetLength; - float t = binSearchForLen(lenAtLastSplit - lenAtLastT, - recCurveStack[recLevel], curveType, lenAtNextT - lenAtLastT, ERR); + final float leaflen = lenAtNextT - lenAtLastT; + float t = (targetLength - lenAtLastT) / leaflen; + + // cubicRootsInAB is a fairly expensive call, so we just don't do it + // if the acceleration in this section of the curve is small enough. + if (!haveLowAcceleration(0.05f)) { + // We flatten the current leaf along the x axis, so that we're + // left with a, b, c which define a 1D Bezier curve. We then + // solve this to get the parameter of the original leaf that + // gives us the desired length. + + if (flatLeafCoefCache[2] < 0) { + float x = 0+curLeafCtrlPolyLengths[0], + y = x+curLeafCtrlPolyLengths[1]; + if (curveType == 8) { + float z = y + curLeafCtrlPolyLengths[2]; + flatLeafCoefCache[0] = 3*(x - y) + z; + flatLeafCoefCache[1] = 3*(y - 2*x); + flatLeafCoefCache[2] = 3*x; + flatLeafCoefCache[3] = -z; + } else if (curveType == 6) { + flatLeafCoefCache[0] = 0f; + flatLeafCoefCache[1] = y - 2*x; + flatLeafCoefCache[2] = 2*x; + flatLeafCoefCache[3] = -y; + } + } + float a = flatLeafCoefCache[0]; + float b = flatLeafCoefCache[1]; + float c = flatLeafCoefCache[2]; + float d = t*flatLeafCoefCache[3]; + + // we use cubicRootsInAB here, because we want only roots in 0, 1, + // and our quadratic root finder doesn't filter, so it's just a + // matter of convenience. + int n = Helpers.cubicRootsInAB(a, b, c, d, nextRoots, 0, 0, 1); + if (n == 1 && !Float.isNaN(nextRoots[0])) { + t = nextRoots[0]; + } + } // t is relative to the current leaf, so we must make it a valid parameter // of the original curve. t = t * (nextT - lastT) + lastT; @@ -379,36 +463,6 @@ public class Dasher implements sun.awt.geom.PathConsumer2D { return lastSegLen; } - // Returns t such that if leaf is subdivided at t the left - // curve will have length len. leafLen must be the length of leaf. - private static Curve bsc = new Curve(); - private static float binSearchForLen(float len, float[] leaf, int type, - float leafLen, float err) - { - assert len <= leafLen; - bsc.set(leaf, type); - float errBound = err*len; - float left = 0, right = 1; - while (left < right) { - float m = (left + right) / 2; - if (m == left || m == right) { - return m; - } - float x = bsc.xat(m); - float y = bsc.yat(m); - float leftLen = Helpers.linelen(leaf[0], leaf[1], x, y); - if (Math.abs(leftLen - len) < errBound) { - return m; - } - if (leftLen < len) { - left = m; - } else { - right = m; - } - } - return left; - } - // go to the next leaf (in an inorder traversal) in the recursion tree // preconditions: must be on a leaf, and that leaf must not be the root. private void goToNextLeaf() { @@ -437,6 +491,9 @@ public class Dasher implements sun.awt.geom.PathConsumer2D { lenAtLastT = lenAtNextT; nextT += (1 << (limit - recLevel)) * minTincrement; lenAtNextT += len; + // invalidate caches + flatLeafCoefCache[2] = -1; + cachedHaveLowAcceleration = -1; } else { Helpers.subdivide(recCurveStack[recLevel], 0, recCurveStack[recLevel+1], 0, @@ -450,11 +507,24 @@ public class Dasher implements sun.awt.geom.PathConsumer2D { // this is a bit of a hack. It returns -1 if we're not on a leaf, and // the length of the leaf if we are on a leaf. private float onLeaf() { - float polylen = Helpers.polyLineLength(recCurveStack[recLevel], 0, curveType); - float linelen = Helpers.linelen(recCurveStack[recLevel][0], recCurveStack[recLevel][1], - recCurveStack[recLevel][curveType - 2], recCurveStack[recLevel][curveType - 1]); - return (polylen - linelen < ERR || recLevel == limit) ? - (polylen + linelen)/2 : -1; + float[] curve = recCurveStack[recLevel]; + float polyLen = 0; + + float x0 = curve[0], y0 = curve[1]; + for (int i = 2; i < curveType; i += 2) { + final float x1 = curve[i], y1 = curve[i+1]; + final float len = Helpers.linelen(x0, y0, x1, y1); + polyLen += len; + curLeafCtrlPolyLengths[i/2 - 1] = len; + x0 = x1; + y0 = y1; + } + + final float lineLen = Helpers.linelen(curve[0], curve[1], curve[curveType-2], curve[curveType-1]); + if (polyLen - lineLen < ERR || recLevel == limit) { + return (polyLen + lineLen)/2; + } + return -1; } } diff --git a/src/share/classes/sun/java2d/pisces/Helpers.java b/src/share/classes/sun/java2d/pisces/Helpers.java index c803f1726882122aa423b9ac20cf3844aeaa34b5..b91bc6a400a3740f179403d5a639f7a194dab452 100644 --- a/src/share/classes/sun/java2d/pisces/Helpers.java +++ b/src/share/classes/sun/java2d/pisces/Helpers.java @@ -26,6 +26,12 @@ package sun.java2d.pisces; import java.util.Arrays; +import static java.lang.Math.PI; +import static java.lang.Math.cos; +import static java.lang.Math.sqrt; +import static java.lang.Math.cbrt; +import static java.lang.Math.acos; + final class Helpers { private Helpers() { @@ -75,100 +81,74 @@ final class Helpers { return ret - off; } - // find the roots of g(t) = a*t^3 + b*t^2 + c*t + d in [A,B) - // We will not use Cardano's method, since it is complicated and - // involves too many square and cubic roots. We will use Newton's method. - // TODO: this should probably return ALL roots. Then the user can do - // his own filtering of roots outside [A,B). - static int cubicRootsInAB(final float a, final float b, - final float c, final float d, - float[] pts, final int off, final float E, + // find the roots of g(t) = d*t^3 + a*t^2 + b*t + c in [A,B) + static int cubicRootsInAB(float d, float a, float b, float c, + float[] pts, final int off, final float A, final float B) { - if (a == 0) { - return quadraticRoots(b, c, d, pts, off); - } - // the coefficients of g'(t). no dc variable because dc=c - // we use these to get the critical points of g(t), which - // we then use to chose starting points for Newton's method. These - // should be very close to the actual roots. - final float da = 3 * a; - final float db = 2 * b; - int numCritPts = quadraticRoots(da, db, c, pts, off+1); - numCritPts = filterOutNotInAB(pts, off+1, numCritPts, A, B) - off - 1; - // need them sorted. - if (numCritPts == 2 && pts[off+1] > pts[off+2]) { - float tmp = pts[off+1]; - pts[off+1] = pts[off+2]; - pts[off+2] = tmp; + if (d == 0) { + int num = quadraticRoots(a, b, c, pts, off); + return filterOutNotInAB(pts, off, num, A, B) - off; } + // From Graphics Gems: + // http://tog.acm.org/resources/GraphicsGems/gems/Roots3And4.c + // (also from awt.geom.CubicCurve2D. But here we don't need as + // much accuracy and we don't want to create arrays so we use + // our own customized version). - int ret = off; + /* normal form: x^3 + ax^2 + bx + c = 0 */ + a /= d; + b /= d; + c /= d; - // we don't actually care much about the extrema themselves. We - // only use them to ensure that g(t) is monotonic in each - // interval [pts[i],pts[i+1] (for i in off...off+numCritPts+1). - // This will allow us to determine intervals containing exactly - // one root. - // The end points of the interval are always local extrema. - pts[off] = A; - pts[off + numCritPts + 1] = B; - numCritPts += 2; - - float x0 = pts[off], fx0 = evalCubic(a, b, c, d, x0); - for (int i = off; i < off + numCritPts - 1; i++) { - float x1 = pts[i+1], fx1 = evalCubic(a, b, c, d, x1); - if (fx0 == 0f) { - pts[ret++] = x0; - } else if (fx1 * fx0 < 0f) { // have opposite signs - pts[ret++] = CubicNewton(a, b, c, d, - x0 + fx0 * (x1 - x0) / (fx0 - fx1), E); - } - x0 = x1; - fx0 = fx1; - } - return ret - off; - } + // substitute x = y - A/3 to eliminate quadratic term: + // x^3 +Px + Q = 0 + // + // Since we actually need P/3 and Q/2 for all of the + // calculations that follow, we will calculate + // p = P/3 + // q = Q/2 + // instead and use those values for simplicity of the code. + double sq_A = a * a; + double p = 1.0/3 * (-1.0/3 * sq_A + b); + double q = 1.0/2 * (2.0/27 * a * sq_A - 1.0/3 * a * b + c); - // precondition: the polynomial to be evaluated must not be 0 at x0. - static float CubicNewton(final float a, final float b, - final float c, final float d, - float x0, final float err) - { - // considering how this function is used, 10 should be more than enough - final int itlimit = 10; - float fx0 = evalCubic(a, b, c, d, x0); - float x1; - int count = 0; - while(true) { - x1 = x0 - (fx0 / evalCubic(0, 3 * a, 2 * b, c, x0)); - if (Math.abs(x1 - x0) < err * Math.abs(x1 + x0) || count == itlimit) { - break; - } - x0 = x1; - fx0 = evalCubic(a, b, c, d, x0); - count++; - } - return x1; - } + /* use Cardano's formula */ - // fills the input array with numbers 0, INC, 2*INC, ... - static void fillWithIdxes(final float[] data, final int[] idxes) { - if (idxes.length > 0) { - idxes[0] = 0; - for (int i = 1; i < idxes.length; i++) { - idxes[i] = idxes[i-1] + (int)data[idxes[i-1]]; + double cb_p = p * p * p; + double D = q * q + cb_p; + + int num; + if (D < 0) { + // see: http://en.wikipedia.org/wiki/Cubic_function#Trigonometric_.28and_hyperbolic.29_method + final double phi = 1.0/3 * acos(-q / sqrt(-cb_p)); + final double t = 2 * sqrt(-p); + + pts[ off+0 ] = (float)( t * cos(phi)); + pts[ off+1 ] = (float)(-t * cos(phi + PI / 3)); + pts[ off+2 ] = (float)(-t * cos(phi - PI / 3)); + num = 3; + } else { + final double sqrt_D = sqrt(D); + final double u = cbrt(sqrt_D - q); + final double v = - cbrt(sqrt_D + q); + + pts[ off ] = (float)(u + v); + num = 1; + + if (within(D, 0, 1e-8)) { + pts[off+1] = -(pts[off] / 2); + num = 2; } } - } - static void fillWithIdxes(final int[] idxes, final int inc) { - if (idxes.length > 0) { - idxes[0] = 0; - for (int i = 1; i < idxes.length; i++) { - idxes[i] = idxes[i-1] + inc; - } + final float sub = 1.0f/3 * a; + + for (int i = 0; i < num; ++i) { + pts[ off+i ] -= sub; } + + return filterOutNotInAB(pts, off, num, A, B) - off; } // These use a hardcoded factor of 2 for increasing sizes. Perhaps this @@ -182,6 +162,7 @@ final class Helpers { } return Arrays.copyOf(in, 2 * (cursize + numToAdd)); } + static int[] widenArray(int[] in, final int cursize, final int numToAdd) { if (in.length >= cursize + numToAdd) { return in; @@ -208,7 +189,7 @@ final class Helpers { { int ret = off; for (int i = off; i < off + len; i++) { - if (nums[i] > a && nums[i] < b) { + if (nums[i] >= a && nums[i] < b) { nums[ret++] = nums[i]; } } @@ -225,7 +206,9 @@ final class Helpers { } static float linelen(float x1, float y1, float x2, float y2) { - return (float)Math.hypot(x2 - x1, y2 - y1); + final float dx = x2 - x1; + final float dy = y2 - y1; + return (float)Math.sqrt(dx*dx + dy*dy); } static void subdivide(float[] src, int srcoff, float[] left, int leftoff, diff --git a/src/share/classes/sun/java2d/pisces/PiscesCache.java b/src/share/classes/sun/java2d/pisces/PiscesCache.java index 05243190ec9ec12202602feba152aa42751c6397..1620db570412916e0ffd62d9428a97aa5fe5f312 100644 --- a/src/share/classes/sun/java2d/pisces/PiscesCache.java +++ b/src/share/classes/sun/java2d/pisces/PiscesCache.java @@ -32,7 +32,7 @@ import java.util.Arrays; * * @see PiscesRenderer#render */ -public final class PiscesCache { +final class PiscesCache { final int bboxX0, bboxY0, bboxX1, bboxY1; diff --git a/src/share/classes/sun/java2d/pisces/PiscesRenderingEngine.java b/src/share/classes/sun/java2d/pisces/PiscesRenderingEngine.java index 9684edc502326cd6072e3234b22b042fd9eb3c38..84b0cad820091e6282d3b3a78997b5228910379f 100644 --- a/src/share/classes/sun/java2d/pisces/PiscesRenderingEngine.java +++ b/src/share/classes/sun/java2d/pisces/PiscesRenderingEngine.java @@ -27,7 +27,6 @@ package sun.java2d.pisces; import java.awt.Shape; import java.awt.BasicStroke; -import java.awt.geom.NoninvertibleTransformException; import java.awt.geom.Path2D; import java.awt.geom.AffineTransform; import java.awt.geom.PathIterator; @@ -250,7 +249,7 @@ public class PiscesRenderingEngine extends RenderingEngine { float dashphase, PathConsumer2D pc2d) { - // We use inat and outat so that in Stroker and Dasher we can work only + // We use strokerat and outat so that in Stroker and Dasher we can work only // with the pre-transformation coordinates. This will repeat a lot of // computations done in the path iterator, but the alternative is to // work with transformed paths and compute untransformed coordinates @@ -265,7 +264,7 @@ public class PiscesRenderingEngine extends RenderingEngine { // transformation after the path processing has been done. // We can't do this if normalization is on, because it isn't a good // idea to normalize before the transformation is applied. - AffineTransform inat = null; + AffineTransform strokerat = null; AffineTransform outat = null; PathIterator pi = null; @@ -284,9 +283,9 @@ public class PiscesRenderingEngine extends RenderingEngine { // again so, nothing can be drawn. // Every path needs an initial moveTo and a pathDone. If these - // aren't there this causes a SIGSEV in libawt.so (at the time + // are not there this causes a SIGSEGV in libawt.so (at the time // of writing of this comment (September 16, 2010)). Actually, - // I'm not sure if the moveTo is necessary to avoid the SIGSEV + // I am not sure if the moveTo is necessary to avoid the SIGSEGV // but the pathDone is definitely needed. pc2d.moveTo(0, 0); pc2d.pathDone(); @@ -313,25 +312,32 @@ public class PiscesRenderingEngine extends RenderingEngine { if (normalize != NormMode.OFF) { pi = new NormalizingPathIterator(pi, normalize); } - // leave inat and outat null. + // by now strokerat == null && outat == null. Input paths to + // stroker (and maybe dasher) will have the full transform at + // applied to them and nothing will happen to the output paths. } else { - // We only need the inverse if normalization is on. Otherwise - // we just don't transform the input paths, do all the stroking - // and then transform out output (instead of making PathIterator - // apply the transformation, us applying the inverse, and then - // us applying the transform again to our output). - outat = at; if (normalize != NormMode.OFF) { - try { - inat = outat.createInverse(); - } catch (NoninvertibleTransformException e) { - // we made sure this can't happen - e.printStackTrace(); - } + strokerat = at; pi = src.getPathIterator(at); pi = new NormalizingPathIterator(pi, normalize); + // by now strokerat == at && outat == null. Input paths to + // stroker (and maybe dasher) will have the full transform at + // applied to them, then they will be normalized, and then + // the inverse of *only the non translation part of at* will + // be applied to the normalized paths. This won't cause problems + // in stroker, because, suppose at = T*A, where T is just the + // translation part of at, and A is the rest. T*A has already + // been applied to Stroker/Dasher's input. Then Ainv will be + // applied. Ainv*T*A is not equal to T, but it is a translation, + // which means that none of stroker's assumptions about its + // input will be violated. After all this, A will be applied + // to stroker's output. } else { + outat = at; pi = src.getPathIterator(null); + // outat == at && strokerat == null. This is because if no + // normalization is done, we can just apply all our + // transformations to stroker's output. } } } else { @@ -343,13 +349,17 @@ public class PiscesRenderingEngine extends RenderingEngine { } } + // by now, at least one of outat and strokerat will be null. Unless at is not + // a constant multiple of an orthogonal transformation, they will both be + // null. In other cases, outat == at if normalization is off, and if + // normalization is on, strokerat == at. pc2d = TransformingPathConsumer2D.transformConsumer(pc2d, outat); + pc2d = TransformingPathConsumer2D.deltaTransformConsumer(pc2d, strokerat); pc2d = new Stroker(pc2d, width, caps, join, miterlimit); if (dashes != null) { pc2d = new Dasher(pc2d, dashes, dashphase); } - pc2d = TransformingPathConsumer2D.transformConsumer(pc2d, inat); - + pc2d = TransformingPathConsumer2D.inverseDeltaTransformConsumer(pc2d, strokerat); pathTo(pi, pc2d); } @@ -588,9 +598,9 @@ public class PiscesRenderingEngine extends RenderingEngine { } Renderer r = new Renderer(3, 3, - clip.getLoX(), clip.getLoY(), - clip.getWidth(), clip.getHeight(), - PathIterator.WIND_EVEN_ODD); + clip.getLoX(), clip.getLoY(), + clip.getWidth(), clip.getHeight(), + PathIterator.WIND_EVEN_ODD); r.moveTo((float) x, (float) y); r.lineTo((float) (x+dx1), (float) (y+dy1)); diff --git a/src/share/classes/sun/java2d/pisces/PiscesTileGenerator.java b/src/share/classes/sun/java2d/pisces/PiscesTileGenerator.java index e2779b8fe0393002c50842540b7b4bc2fd761939..ba91edb9819b99e3a05a3b4e278ff6e7f70e05f2 100644 --- a/src/share/classes/sun/java2d/pisces/PiscesTileGenerator.java +++ b/src/share/classes/sun/java2d/pisces/PiscesTileGenerator.java @@ -30,7 +30,7 @@ import java.util.concurrent.ConcurrentHashMap; import sun.java2d.pipe.AATileGenerator; -public final class PiscesTileGenerator implements AATileGenerator { +final class PiscesTileGenerator implements AATileGenerator { public static final int TILE_SIZE = PiscesCache.TILE_SIZE; // perhaps we should be using weak references here, but right now diff --git a/src/share/classes/sun/java2d/pisces/Renderer.java b/src/share/classes/sun/java2d/pisces/Renderer.java index 782d9e4f30becf53f43e051a700e3df701a9794b..cbfa2897d941d36c409701950110ded3b51a22b4 100644 --- a/src/share/classes/sun/java2d/pisces/Renderer.java +++ b/src/share/classes/sun/java2d/pisces/Renderer.java @@ -25,12 +25,9 @@ package sun.java2d.pisces; -import java.util.Arrays; -import java.util.Iterator; - import sun.awt.geom.PathConsumer2D; -public class Renderer implements PathConsumer2D { +final class Renderer implements PathConsumer2D { private class ScanlineIterator { @@ -39,115 +36,81 @@ public class Renderer implements PathConsumer2D { // crossing bounds. The bounds are not necessarily tight (the scan line // at minY, for example, might have no crossings). The x bounds will // be accumulated as crossings are computed. - private int minY, maxY; + private final int maxY; private int nextY; // indices into the segment pointer lists. They indicate the "active" // sublist in the segment lists (the portion of the list that contains // all the segments that cross the next scan line). - private int elo, ehi; - private final int[] edgePtrs; - private int qlo, qhi; - private final int[] quadPtrs; - private int clo, chi; - private final int[] curvePtrs; + private int edgeCount; + private int[] edgePtrs; private static final int INIT_CROSSINGS_SIZE = 10; private ScanlineIterator() { crossings = new int[INIT_CROSSINGS_SIZE]; - - edgePtrs = new int[numEdges]; - Helpers.fillWithIdxes(edgePtrs, SIZEOF_EDGE); - qsort(edges, edgePtrs, YMIN, 0, numEdges - 1); - - quadPtrs = new int[numQuads]; - Helpers.fillWithIdxes(quadPtrs, SIZEOF_QUAD); - qsort(quads, quadPtrs, YMIN, 0, numQuads - 1); - - curvePtrs = new int[numCurves]; - Helpers.fillWithIdxes(curvePtrs, SIZEOF_CURVE); - qsort(curves, curvePtrs, YMIN, 0, numCurves - 1); + edgePtrs = new int[INIT_CROSSINGS_SIZE]; // We don't care if we clip some of the line off with ceil, since // no scan line crossings will be eliminated (in fact, the ceil is // the y of the first scan line crossing). - nextY = minY = Math.max(boundsMinY, (int)Math.ceil(edgeMinY)); - maxY = Math.min(boundsMaxY, (int)Math.ceil(edgeMaxY)); - - for (elo = 0; elo < numEdges && edges[edgePtrs[elo]+YMAX] <= minY; elo++) - ; - // the active list is *edgePtrs[lo] (inclusive) *edgePtrs[hi] (exclusive) - for (ehi = elo; ehi < numEdges && edges[edgePtrs[ehi]+YMIN] <= minY; ehi++) - edgeSetCurY(edgePtrs[ehi], minY);// TODO: make minY a float to avoid casts - - for (qlo = 0; qlo < numQuads && quads[quadPtrs[qlo]+YMAX] <= minY; qlo++) - ; - for (qhi = qlo; qhi < numQuads && quads[quadPtrs[qhi]+YMIN] <= minY; qhi++) - quadSetCurY(quadPtrs[qhi], minY); - - for (clo = 0; clo < numCurves && curves[curvePtrs[clo]+YMAX] <= minY; clo++) - ; - for (chi = clo; chi < numCurves && curves[curvePtrs[chi]+YMIN] <= minY; chi++) - curveSetCurY(curvePtrs[chi], minY); + final int minY = getFirstScanLineCrossing(); + nextY = minY; + maxY = getScanLineCrossingEnd()-1; + edgeCount = 0; } private int next() { - // we go through the active lists and remove segments that don't cross - // the nextY scanline. - int crossingIdx = 0; - for (int i = elo; i < ehi; i++) { - if (edges[edgePtrs[i]+YMAX] <= nextY) { - edgePtrs[i] = edgePtrs[elo++]; - } - } - for (int i = qlo; i < qhi; i++) { - if (quads[quadPtrs[i]+YMAX] <= nextY) { - quadPtrs[i] = quadPtrs[qlo++]; - } - } - for (int i = clo; i < chi; i++) { - if (curves[curvePtrs[i]+YMAX] <= nextY) { - curvePtrs[i] = curvePtrs[clo++]; + int cury = nextY++; + int bucket = cury - boundsMinY; + int count = this.edgeCount; + int ptrs[] = this.edgePtrs; + int bucketcount = edgeBucketCounts[bucket]; + if ((bucketcount & 0x1) != 0) { + int newCount = 0; + for (int i = 0; i < count; i++) { + int ecur = ptrs[i]; + if (edges[ecur+YMAX] > cury) { + ptrs[newCount++] = ecur; + } } + count = newCount; } - - crossings = Helpers.widenArray(crossings, 0, ehi-elo+qhi-qlo+chi-clo); - - // Now every edge between lo and hi crosses nextY. Compute it's - // crossing and put it in the crossings array. - for (int i = elo; i < ehi; i++) { - int ptr = edgePtrs[i]; - addCrossing(nextY, (int)edges[ptr+CURX], edges[ptr+OR], crossingIdx); - edgeGoToNextY(ptr); - crossingIdx++; - } - for (int i = qlo; i < qhi; i++) { - int ptr = quadPtrs[i]; - addCrossing(nextY, (int)quads[ptr+CURX], quads[ptr+OR], crossingIdx); - quadGoToNextY(ptr); - crossingIdx++; + ptrs = Helpers.widenArray(ptrs, count, bucketcount >> 1); + for (int ecur = edgeBuckets[bucket]; ecur != NULL; ecur = (int)edges[ecur+NEXT]) { + ptrs[count++] = ecur; + // REMIND: Adjust start Y if necessary } - for (int i = clo; i < chi; i++) { - int ptr = curvePtrs[i]; - addCrossing(nextY, (int)curves[ptr+CURX], curves[ptr+OR], crossingIdx); - curveGoToNextY(ptr); - crossingIdx++; + this.edgePtrs = ptrs; + this.edgeCount = count; +// if ((count & 0x1) != 0) { +// System.out.println("ODD NUMBER OF EDGES!!!!"); +// } + int xings[] = this.crossings; + if (xings.length < count) { + this.crossings = xings = new int[ptrs.length]; } - - nextY++; - // Expand active lists to include new edges. - for (; ehi < numEdges && edges[edgePtrs[ehi]+YMIN] <= nextY; ehi++) { - edgeSetCurY(edgePtrs[ehi], nextY); - } - for (; qhi < numQuads && quads[quadPtrs[qhi]+YMIN] <= nextY; qhi++) { - quadSetCurY(quadPtrs[qhi], nextY); - } - for (; chi < numCurves && curves[curvePtrs[chi]+YMIN] <= nextY; chi++) { - curveSetCurY(curvePtrs[chi], nextY); + for (int i = 0; i < count; i++) { + int ecur = ptrs[i]; + float curx = edges[ecur+CURX]; + int cross = ((int) curx) << 1; + edges[ecur+CURX] = curx + edges[ecur+SLOPE]; + if (edges[ecur+OR] > 0) { + cross |= 1; + } + int j = i; + while (--j >= 0) { + int jcross = xings[j]; + if (jcross <= cross) { + break; + } + xings[j+1] = jcross; + ptrs[j+1] = ptrs[j]; + } + xings[j+1] = cross; + ptrs[j+1] = ecur; } - Arrays.sort(crossings, 0, crossingIdx); - return crossingIdx; + return count; } private boolean hasNext() { @@ -157,51 +120,7 @@ public class Renderer implements PathConsumer2D { private int curY() { return nextY - 1; } - - private void addCrossing(int y, int x, float or, int idx) { - x <<= 1; - crossings[idx] = ((or > 0) ? (x | 0x1) : x); - } - } - // quicksort implementation for sorting the edge indices ("pointers") - // by increasing y0. first, last are indices into the "pointer" array - // It sorts the pointer array from first (inclusive) to last (inclusive) - private static void qsort(final float[] data, final int[] ptrs, - final int fieldForCmp, int first, int last) - { - if (last > first) { - int p = partition(data, ptrs, fieldForCmp, first, last); - if (first < p - 1) { - qsort(data, ptrs, fieldForCmp, first, p - 1); - } - if (p < last) { - qsort(data, ptrs, fieldForCmp, p, last); - } - } - } - - // i, j are indices into edgePtrs. - private static int partition(final float[] data, final int[] ptrs, - final int fieldForCmp, int i, int j) - { - int pivotValFieldForCmp = ptrs[i]+fieldForCmp; - while (i <= j) { - // edges[edgePtrs[i]+1] is equivalent to (*(edgePtrs[i])).y0 in C - while (data[ptrs[i]+fieldForCmp] < data[pivotValFieldForCmp]) - i++; - while (data[ptrs[j]+fieldForCmp] > data[pivotValFieldForCmp]) - j--; - if (i <= j) { - int tmp = ptrs[i]; - ptrs[i] = ptrs[j]; - ptrs[j] = tmp; - i++; - j--; - } - } - return i; } -//============================================================================ ////////////////////////////////////////////////////////////////////////////// @@ -209,269 +128,89 @@ public class Renderer implements PathConsumer2D { ////////////////////////////////////////////////////////////////////////////// // TODO(maybe): very tempting to use fixed point here. A lot of opportunities // for shifts and just removing certain operations altogether. -// TODO: it might be worth it to make an EdgeList class. It would probably -// clean things up a bit and not impact performance much. // common to all types of input path segments. - private static final int YMIN = 0; - private static final int YMAX = 1; - private static final int CURX = 2; - // this and OR are meant to be indeces into "int" fields, but arrays must + private static final int YMAX = 0; + private static final int CURX = 1; + // NEXT and OR are meant to be indices into "int" fields, but arrays must // be homogenous, so every field is a float. However floats can represent // exactly up to 26 bit ints, so we're ok. - private static final int CURY = 3; - private static final int OR = 4; - - // for straight lines only: - private static final int SLOPE = 5; - - // for quads and cubics: - private static final int X0 = 5; - private static final int Y0 = 6; - private static final int XL = 7; - private static final int COUNT = 8; - private static final int CURSLOPE = 9; - private static final int DX = 10; - private static final int DY = 11; - private static final int DDX = 12; - private static final int DDY = 13; - - // for cubics only - private static final int DDDX = 14; - private static final int DDDY = 15; + private static final int OR = 2; + private static final int SLOPE = 3; + private static final int NEXT = 4; private float edgeMinY = Float.POSITIVE_INFINITY; private float edgeMaxY = Float.NEGATIVE_INFINITY; private float edgeMinX = Float.POSITIVE_INFINITY; private float edgeMaxX = Float.NEGATIVE_INFINITY; - private static final int SIZEOF_EDGE = 6; + private static final int SIZEOF_EDGE = 5; + // don't just set NULL to -1, because we want NULL+NEXT to be negative. + private static final int NULL = -SIZEOF_EDGE; private float[] edges = null; + private int[] edgeBuckets = null; + private int[] edgeBucketCounts = null; // 2*newedges + (1 if pruning needed) private int numEdges; - // these are static because we need them to be usable from ScanlineIterator - private void edgeSetCurY(final int idx, int y) { - edges[idx+CURX] += (y - edges[idx+CURY]) * edges[idx+SLOPE]; - edges[idx+CURY] = y; - } - private void edgeGoToNextY(final int idx) { - edges[idx+CURY] += 1; - edges[idx+CURX] += edges[idx+SLOPE]; - } - - - private static final int SIZEOF_QUAD = 14; - private float[] quads = null; - private int numQuads; - // This function should be called exactly once, to set the first scanline - // of the curve. Before it is called, the curve should think its first - // scanline is CEIL(YMIN). - private void quadSetCurY(final int idx, final int y) { - assert y < quads[idx+YMAX]; - assert (quads[idx+CURY] > y); - assert (quads[idx+CURY] == Math.ceil(quads[idx+CURY])); - - while (quads[idx+CURY] < ((float)y)) { - quadGoToNextY(idx); - } - } - private void quadGoToNextY(final int idx) { - quads[idx+CURY] += 1; - // this will get overriden if the while executes. - quads[idx+CURX] += quads[idx+CURSLOPE]; - int count = (int)quads[idx+COUNT]; - // this loop should never execute more than once because our - // curve is monotonic in Y. Still we put it in because you can - // never be too sure when dealing with floating point. - while(quads[idx+CURY] >= quads[idx+Y0] && count > 0) { - float x0 = quads[idx+X0], y0 = quads[idx+Y0]; - count = executeQuadAFDIteration(idx); - float x1 = quads[idx+X0], y1 = quads[idx+Y0]; - // our quads are monotonic, so this shouldn't happen, but - // it is conceivable that for very flat quads with different - // y values at their endpoints AFD might give us a horizontal - // segment. - if (y1 == y0) { - continue; - } - quads[idx+CURSLOPE] = (x1 - x0) / (y1 - y0); - quads[idx+CURX] = x0 + (quads[idx+CURY] - y0) * quads[idx+CURSLOPE]; - } - } - - private static final int SIZEOF_CURVE = 16; - private float[] curves = null; - private int numCurves; - private void curveSetCurY(final int idx, final int y) { - assert y < curves[idx+YMAX]; - assert (curves[idx+CURY] > y); - assert (curves[idx+CURY] == Math.ceil(curves[idx+CURY])); + private static final float DEC_BND = 20f; + private static final float INC_BND = 8f; - while (curves[idx+CURY] < ((float)y)) { - curveGoToNextY(idx); - } - } - private void curveGoToNextY(final int idx) { - curves[idx+CURY] += 1; - // this will get overriden if the while executes. - curves[idx+CURX] += curves[idx+CURSLOPE]; - int count = (int)curves[idx+COUNT]; - // this loop should never execute more than once because our - // curve is monotonic in Y. Still we put it in because you can - // never be too sure when dealing with floating point. - while(curves[idx+CURY] >= curves[idx+Y0] && count > 0) { - float x0 = curves[idx+X0], y0 = curves[idx+Y0]; - count = executeCurveAFDIteration(idx); - float x1 = curves[idx+X0], y1 = curves[idx+Y0]; - // our curves are monotonic, so this shouldn't happen, but - // it is conceivable that for very flat curves with different - // y values at their endpoints AFD might give us a horizontal - // segment. - if (y1 == y0) { - continue; - } - curves[idx+CURSLOPE] = (x1 - x0) / (y1 - y0); - curves[idx+CURX] = x0 + (curves[idx+CURY] - y0) * curves[idx+CURSLOPE]; - } + // each bucket is a linked list. this method adds eptr to the + // start "bucket"th linked list. + private void addEdgeToBucket(final int eptr, final int bucket) { + edges[eptr+NEXT] = edgeBuckets[bucket]; + edgeBuckets[bucket] = eptr; + edgeBucketCounts[bucket] += 2; } - - private static final float DEC_BND = 20f; - private static final float INC_BND = 8f; // Flattens using adaptive forward differencing. This only carries out // one iteration of the AFD loop. All it does is update AFD variables (i.e. // X0, Y0, D*[X|Y], COUNT; not variables used for computing scanline crossings). - private int executeQuadAFDIteration(int idx) { - int count = (int)quads[idx+COUNT]; - float ddx = quads[idx+DDX]; - float ddy = quads[idx+DDY]; - float dx = quads[idx+DX]; - float dy = quads[idx+DY]; - - while (Math.abs(ddx) > DEC_BND || Math.abs(ddy) > DEC_BND) { - ddx = ddx / 4; - ddy = ddy / 4; - dx = (dx - ddx) / 2; - dy = (dy - ddy) / 2; - count <<= 1; - } - // can only do this on even "count" values, because we must divide count by 2 - while (count % 2 == 0 && Math.abs(dx) <= INC_BND && Math.abs(dy) <= INC_BND) { - dx = 2 * dx + ddx; - dy = 2 * dy + ddy; - ddx = 4 * ddx; - ddy = 4 * ddy; - count >>= 1; - } - count--; - if (count > 0) { - quads[idx+X0] += dx; - dx += ddx; - quads[idx+Y0] += dy; - dy += ddy; - } else { - quads[idx+X0] = quads[idx+XL]; - quads[idx+Y0] = quads[idx+YMAX]; - } - quads[idx+COUNT] = count; - quads[idx+DDX] = ddx; - quads[idx+DDY] = ddy; - quads[idx+DX] = dx; - quads[idx+DY] = dy; - return count; - } - private int executeCurveAFDIteration(int idx) { - int count = (int)curves[idx+COUNT]; - float ddx = curves[idx+DDX]; - float ddy = curves[idx+DDY]; - float dx = curves[idx+DX]; - float dy = curves[idx+DY]; - float dddx = curves[idx+DDDX]; - float dddy = curves[idx+DDDY]; - - while (Math.abs(ddx) > DEC_BND || Math.abs(ddy) > DEC_BND) { - dddx /= 8; - dddy /= 8; - ddx = ddx/4 - dddx; - ddy = ddy/4 - dddy; - dx = (dx - ddx) / 2; - dy = (dy - ddy) / 2; + private void quadBreakIntoLinesAndAdd(float x0, float y0, + final Curve c, + final float x2, final float y2) { + final float QUAD_DEC_BND = 32; + final int countlg = 4; + int count = 1 << countlg; + int countsq = count * count; + float maxDD = Math.max(c.dbx / countsq, c.dby / countsq); + while (maxDD > QUAD_DEC_BND) { + maxDD /= 4; count <<= 1; } - // can only do this on even "count" values, because we must divide count by 2 - while (count % 2 == 0 && Math.abs(dx) <= INC_BND && Math.abs(dy) <= INC_BND) { - dx = 2 * dx + ddx; - dy = 2 * dy + ddy; - ddx = 4 * (ddx + dddx); - ddy = 4 * (ddy + dddy); - dddx = 8 * dddx; - dddy = 8 * dddy; - count >>= 1; - } - count--; - if (count > 0) { - curves[idx+X0] += dx; + + countsq = count * count; + final float ddx = c.dbx / countsq; + final float ddy = c.dby / countsq; + float dx = c.bx / countsq + c.cx / count; + float dy = c.by / countsq + c.cy / count; + + while (count-- > 1) { + float x1 = x0 + dx; dx += ddx; - ddx += dddx; - curves[idx+Y0] += dy; + float y1 = y0 + dy; dy += ddy; - ddy += dddy; - } else { - curves[idx+X0] = curves[idx+XL]; - curves[idx+Y0] = curves[idx+YMAX]; + addLine(x0, y0, x1, y1); + x0 = x1; + y0 = y1; } - curves[idx+COUNT] = count; - curves[idx+DDDX] = dddx; - curves[idx+DDDY] = dddy; - curves[idx+DDX] = ddx; - curves[idx+DDY] = ddy; - curves[idx+DX] = dx; - curves[idx+DY] = dy; - return count; - } - - - private void initLine(final int idx, float[] pts, int or) { - edges[idx+SLOPE] = (pts[2] - pts[0]) / (pts[3] - pts[1]); - edges[idx+CURX] = pts[0] + (edges[idx+CURY] - pts[1]) * edges[idx+SLOPE]; - } - - private void initQuad(final int idx, float[] points, int or) { - final int countlg = 3; - final int count = 1 << countlg; - - // the dx and dy refer to forward differencing variables, not the last - // coefficients of the "points" polynomial - final float ddx, ddy, dx, dy; - c.set(points, 6); - - ddx = c.dbx / (1 << (2 * countlg)); - ddy = c.dby / (1 << (2 * countlg)); - dx = c.bx / (1 << (2 * countlg)) + c.cx / (1 << countlg); - dy = c.by / (1 << (2 * countlg)) + c.cy / (1 << countlg); - - quads[idx+DDX] = ddx; - quads[idx+DDY] = ddy; - quads[idx+DX] = dx; - quads[idx+DY] = dy; - quads[idx+COUNT] = count; - quads[idx+XL] = points[4]; - quads[idx+X0] = points[0]; - quads[idx+Y0] = points[1]; - executeQuadAFDIteration(idx); - float x1 = quads[idx+X0], y1 = quads[idx+Y0]; - quads[idx+CURSLOPE] = (x1 - points[0]) / (y1 - points[1]); - quads[idx+CURX] = points[0] + (quads[idx+CURY] - points[1])*quads[idx+CURSLOPE]; + addLine(x0, y0, x2, y2); } - private void initCurve(final int idx, float[] points, int or) { + // x0, y0 and x3,y3 are the endpoints of the curve. We could compute these + // using c.xat(0),c.yat(0) and c.xat(1),c.yat(1), but this might introduce + // numerical errors, and our callers already have the exact values. + // Another alternative would be to pass all the control points, and call c.set + // here, but then too many numbers are passed around. + private void curveBreakIntoLinesAndAdd(float x0, float y0, + final Curve c, + final float x3, final float y3) { final int countlg = 3; - final int count = 1 << countlg; + int count = 1 << countlg; // the dx and dy refer to forward differencing variables, not the last // coefficients of the "points" polynomial - final float dddx, dddy, ddx, ddy, dx, dy; - c.set(points, 8); + float dddx, dddy, ddx, ddy, dx, dy; dddx = 2f * c.dax / (1 << (3 * countlg)); dddy = 2f * c.day / (1 << (3 * countlg)); @@ -480,93 +219,100 @@ public class Renderer implements PathConsumer2D { dx = c.ax / (1 << (3 * countlg)) + c.bx / (1 << (2 * countlg)) + c.cx / (1 << countlg); dy = c.ay / (1 << (3 * countlg)) + c.by / (1 << (2 * countlg)) + c.cy / (1 << countlg); - curves[idx+DDDX] = dddx; - curves[idx+DDDY] = dddy; - curves[idx+DDX] = ddx; - curves[idx+DDY] = ddy; - curves[idx+DX] = dx; - curves[idx+DY] = dy; - curves[idx+COUNT] = count; - curves[idx+XL] = points[6]; - curves[idx+X0] = points[0]; - curves[idx+Y0] = points[1]; - executeCurveAFDIteration(idx); - float x1 = curves[idx+X0], y1 = curves[idx+Y0]; - curves[idx+CURSLOPE] = (x1 - points[0]) / (y1 - points[1]); - curves[idx+CURX] = points[0] + (curves[idx+CURY] - points[1])*curves[idx+CURSLOPE]; + // we use x0, y0 to walk the line + float x1 = x0, y1 = y0; + while (count > 0) { + while (Math.abs(ddx) > DEC_BND || Math.abs(ddy) > DEC_BND) { + dddx /= 8; + dddy /= 8; + ddx = ddx/4 - dddx; + ddy = ddy/4 - dddy; + dx = (dx - ddx) / 2; + dy = (dy - ddy) / 2; + count <<= 1; + } + // can only do this on even "count" values, because we must divide count by 2 + while (count % 2 == 0 && Math.abs(dx) <= INC_BND && Math.abs(dy) <= INC_BND) { + dx = 2 * dx + ddx; + dy = 2 * dy + ddy; + ddx = 4 * (ddx + dddx); + ddy = 4 * (ddy + dddy); + dddx = 8 * dddx; + dddy = 8 * dddy; + count >>= 1; + } + count--; + if (count > 0) { + x1 += dx; + dx += ddx; + ddx += dddx; + y1 += dy; + dy += ddy; + ddy += dddy; + } else { + x1 = x3; + y1 = y3; + } + addLine(x0, y0, x1, y1); + x0 = x1; + y0 = y1; + } } - private void addPathSegment(float[] pts, final int type, final int or) { - int idx; - float[] addTo; - switch (type) { - case 4: - idx = numEdges * SIZEOF_EDGE; - addTo = edges = Helpers.widenArray(edges, numEdges*SIZEOF_EDGE, SIZEOF_EDGE); - numEdges++; - break; - case 6: - idx = numQuads * SIZEOF_QUAD; - addTo = quads = Helpers.widenArray(quads, numQuads*SIZEOF_QUAD, SIZEOF_QUAD); - numQuads++; - break; - case 8: - idx = numCurves * SIZEOF_CURVE; - addTo = curves = Helpers.widenArray(curves, numCurves*SIZEOF_CURVE, SIZEOF_CURVE); - numCurves++; - break; - default: - throw new InternalError(); + // Preconditions: y2 > y1 and the curve must cross some scanline + // i.e.: y1 <= y < y2 for some y such that boundsMinY <= y < boundsMaxY + private void addLine(float x1, float y1, float x2, float y2) { + float or = 1; // orientation of the line. 1 if y increases, 0 otherwise. + if (y2 < y1) { + or = y2; // no need to declare a temp variable. We have or. + y2 = y1; + y1 = or; + or = x2; + x2 = x1; + x1 = or; + or = 0; } - // set the common fields, except CURX, for which we must know the kind - // of curve. NOTE: this must be done before the type specific fields - // are initialized, because those depend on the common ones. - addTo[idx+YMIN] = pts[1]; - addTo[idx+YMAX] = pts[type-1]; - addTo[idx+OR] = or; - addTo[idx+CURY] = (float)Math.ceil(pts[1]); - switch (type) { - case 4: - initLine(idx, pts, or); - break; - case 6: - initQuad(idx, pts, or); - break; - case 8: - initCurve(idx, pts, or); - break; - default: - throw new InternalError(); + final int firstCrossing = Math.max((int) Math.ceil(y1), boundsMinY); + final int lastCrossing = Math.min((int)Math.ceil(y2), boundsMaxY); + if (firstCrossing >= lastCrossing) { + return; } - } - // precondition: the curve in pts must be monotonic and increasing in y. - private void somethingTo(float[] pts, final int type, final int or) { - // NOTE: it's very important that we check for or >= 0 below (as - // opposed to or == 1, or or > 0, or anything else). That's - // because if we check for or==1, when the curve being added - // is a horizontal line, or will be 0 so or==1 will be false and - // x0 and y0 will be updated to pts[0] and pts[1] instead of pts[type-2] - // and pts[type-1], which is the correct thing to do. - this.x0 = or >= 0 ? pts[type - 2] : pts[0]; - this.y0 = or >= 0 ? pts[type - 1] : pts[1]; - - float minY = pts[1], maxY = pts[type - 1]; - if (Math.ceil(minY) >= Math.ceil(maxY) || - Math.ceil(minY) >= boundsMaxY || maxY < boundsMinY) - { - return; + if (y1 < edgeMinY) { edgeMinY = y1; } + if (y2 > edgeMaxY) { edgeMaxY = y2; } + + final float slope = (x2 - x1) / (y2 - y1); + + if (slope > 0) { // <==> x1 < x2 + if (x1 < edgeMinX) { edgeMinX = x1; } + if (x2 > edgeMaxX) { edgeMaxX = x2; } + } else { + if (x2 < edgeMinX) { edgeMinX = x2; } + if (x1 > edgeMaxX) { edgeMaxX = x1; } } - if (minY < edgeMinY) { edgeMinY = minY; } - if (maxY > edgeMaxY) { edgeMaxY = maxY; } + final int ptr = numEdges * SIZEOF_EDGE; + edges = Helpers.widenArray(edges, ptr, SIZEOF_EDGE); + numEdges++; + edges[ptr+OR] = or; + edges[ptr+CURX] = x1 + (firstCrossing - y1) * slope; + edges[ptr+SLOPE] = slope; + edges[ptr+YMAX] = y2; + final int bucketIdx = firstCrossing - boundsMinY; + addEdgeToBucket(ptr, bucketIdx); + if (lastCrossing < boundsMaxY) { + edgeBucketCounts[lastCrossing - boundsMinY] |= 1; + } + } - int minXidx = (pts[0] < pts[type-2] ? 0 : type - 2); - float minX = pts[minXidx]; - float maxX = pts[type - 2 - minXidx]; - if (minX < edgeMinX) { edgeMinX = minX; } - if (maxX > edgeMaxX) { edgeMaxX = maxX; } - addPathSegment(pts, type, or); + // preconditions: should not be called before the last line has been added + // to the edge list (even though it will return a correct answer at that + // point in time, it's not meant to be used that way). + private int getFirstScanLineCrossing() { + return Math.max(boundsMinY, (int)Math.ceil(edgeMinY)); + } + private int getScanLineCrossingEnd() { + return Math.min(boundsMaxY, (int)Math.ceil(edgeMaxY)); } // END EDGE LIST @@ -619,6 +365,10 @@ public class Renderer implements PathConsumer2D { this.boundsMinY = pix_boundsY * SUBPIXEL_POSITIONS_Y; this.boundsMaxX = (pix_boundsX + pix_boundsWidth) * SUBPIXEL_POSITIONS_X; this.boundsMaxY = (pix_boundsY + pix_boundsHeight) * SUBPIXEL_POSITIONS_Y; + + edgeBuckets = new int[boundsMaxY - boundsMinY]; + java.util.Arrays.fill(edgeBuckets, NULL); + edgeBucketCounts = new int[edgeBuckets.length]; } private float tosubpixx(float pix_x) { @@ -636,74 +386,34 @@ public class Renderer implements PathConsumer2D { this.x0 = tosubpixx(pix_x0); } - public void lineJoin() { /* do nothing */ } - - private final float[][] pts = new float[2][8]; - private final float[] ts = new float[4]; - - private static void invertPolyPoints(float[] pts, int off, int type) { - for (int i = off, j = off + type - 2; i < j; i += 2, j -= 2) { - float tmp = pts[i]; - pts[i] = pts[j]; - pts[j] = tmp; - tmp = pts[i+1]; - pts[i+1] = pts[j+1]; - pts[j+1] = tmp; - } - } - - // return orientation before making the curve upright. - private static int makeMonotonicCurveUpright(float[] pts, int off, int type) { - float y0 = pts[off + 1]; - float y1 = pts[off + type - 1]; - if (y0 > y1) { - invertPolyPoints(pts, off, type); - return -1; - } else if (y0 < y1) { - return 1; - } - return 0; - } - public void lineTo(float pix_x1, float pix_y1) { - pts[0][0] = x0; pts[0][1] = y0; - pts[0][2] = tosubpixx(pix_x1); pts[0][3] = tosubpixy(pix_y1); - int or = makeMonotonicCurveUpright(pts[0], 0, 4); - somethingTo(pts[0], 4, or); + float x1 = tosubpixx(pix_x1); + float y1 = tosubpixy(pix_y1); + addLine(x0, y0, x1, y1); + x0 = x1; + y0 = y1; } Curve c = new Curve(); - private void curveOrQuadTo(int type) { - c.set(pts[0], type); - int numTs = c.dxRoots(ts, 0); - numTs += c.dyRoots(ts, numTs); - numTs = Helpers.filterOutNotInAB(ts, 0, numTs, 0, 1); - Helpers.isort(ts, 0, numTs); - - Iterator it = Curve.breakPtsAtTs(pts, type, ts, numTs); - while(it.hasNext()) { - float[] curCurve = it.next(); - int or = makeMonotonicCurveUpright(curCurve, 0, type); - somethingTo(curCurve, type, or); - } - } - @Override public void curveTo(float x1, float y1, float x2, float y2, float x3, float y3) { - pts[0][0] = x0; pts[0][1] = y0; - pts[0][2] = tosubpixx(x1); pts[0][3] = tosubpixy(y1); - pts[0][4] = tosubpixx(x2); pts[0][5] = tosubpixy(y2); - pts[0][6] = tosubpixx(x3); pts[0][7] = tosubpixy(y3); - curveOrQuadTo(8); + final float xe = tosubpixx(x3); + final float ye = tosubpixy(y3); + c.set(x0, y0, tosubpixx(x1), tosubpixy(y1), tosubpixx(x2), tosubpixy(y2), xe, ye); + curveBreakIntoLinesAndAdd(x0, y0, c, xe, ye); + x0 = xe; + y0 = ye; } @Override public void quadTo(float x1, float y1, float x2, float y2) { - pts[0][0] = x0; pts[0][1] = y0; - pts[0][2] = tosubpixx(x1); pts[0][3] = tosubpixy(y1); - pts[0][4] = tosubpixx(x2); pts[0][5] = tosubpixy(y2); - curveOrQuadTo(6); + final float xe = tosubpixx(x2); + final float ye = tosubpixy(y2); + c.set(x0, y0, tosubpixx(x1), tosubpixy(y1), xe, ye); + quadBreakIntoLinesAndAdd(x0, y0, c, xe, ye); + x0 = xe; + y0 = ye; } public void closePath() { @@ -728,9 +438,9 @@ public class Renderer implements PathConsumer2D { // 0x1 if EVEN_ODD, all bits if NON_ZERO int mask = (windingRule == WIND_EVEN_ODD) ? 0x1 : ~0x0; - // add 1 to better deal with the last pixel in a pixel row. - int width = pix_bboxx1 - pix_bboxx0 + 1; - int[] alpha = new int[width+1]; + // add 2 to better deal with the last pixel in a pixel row. + int width = pix_bboxx1 - pix_bboxx0; + int[] alpha = new int[width+2]; int bboxx0 = pix_bboxx0 << SUBPIXEL_LG_POSITIONS_X; int bboxx1 = pix_bboxx1 << SUBPIXEL_LG_POSITIONS_X; @@ -766,7 +476,8 @@ public class Renderer implements PathConsumer2D { for (int i = 0; i < numCrossings; i++) { int curxo = crossings[i]; int curx = curxo >> 1; - int crorientation = ((curxo & 0x1) == 0x1) ? 1 : -1; + // to turn {0, 1} into {-1, 1}, multiply by 2 and subtract 1. + int crorientation = ((curxo & 0x1) << 1) -1; if ((sum & mask) != 0) { int x0 = Math.max(prev, bboxx0); int x1 = Math.min(curx, bboxx1); @@ -811,26 +522,26 @@ public class Renderer implements PathConsumer2D { } public void endRendering() { - final int bminx = boundsMinX >> SUBPIXEL_LG_POSITIONS_X; - final int bmaxx = boundsMaxX >> SUBPIXEL_LG_POSITIONS_X; - final int bminy = boundsMinY >> SUBPIXEL_LG_POSITIONS_Y; - final int bmaxy = boundsMaxY >> SUBPIXEL_LG_POSITIONS_Y; - final int eminx = ((int)Math.floor(edgeMinX)) >> SUBPIXEL_LG_POSITIONS_X; - final int emaxx = ((int)Math.ceil(edgeMaxX)) >> SUBPIXEL_LG_POSITIONS_X; - final int eminy = ((int)Math.floor(edgeMinY)) >> SUBPIXEL_LG_POSITIONS_Y; - final int emaxy = ((int)Math.ceil(edgeMaxY)) >> SUBPIXEL_LG_POSITIONS_Y; - - final int minX = Math.max(bminx, eminx); - final int maxX = Math.min(bmaxx, emaxx); - final int minY = Math.max(bminy, eminy); - final int maxY = Math.min(bmaxy, emaxy); - if (minX > maxX || minY > maxY) { - this.cache = new PiscesCache(bminx, bminy, bmaxx, bmaxy); + int spminX = Math.max((int)Math.ceil(edgeMinX), boundsMinX); + int spmaxX = Math.min((int)Math.ceil(edgeMaxX), boundsMaxX); + int spminY = Math.max((int)Math.ceil(edgeMinY), boundsMinY); + int spmaxY = Math.min((int)Math.ceil(edgeMaxY), boundsMaxY); + + int pminX = spminX >> SUBPIXEL_LG_POSITIONS_X; + int pmaxX = (spmaxX + SUBPIXEL_MASK_X) >> SUBPIXEL_LG_POSITIONS_X; + int pminY = spminY >> SUBPIXEL_LG_POSITIONS_Y; + int pmaxY = (spmaxY + SUBPIXEL_MASK_Y) >> SUBPIXEL_LG_POSITIONS_Y; + + if (pminX > pmaxX || pminY > pmaxY) { + this.cache = new PiscesCache(boundsMinX >> SUBPIXEL_LG_POSITIONS_X, + boundsMinY >> SUBPIXEL_LG_POSITIONS_Y, + boundsMaxX >> SUBPIXEL_LG_POSITIONS_X, + boundsMaxY >> SUBPIXEL_LG_POSITIONS_Y); return; } - this.cache = new PiscesCache(minX, minY, maxX, maxY); - _endRendering(minX, minY, maxX, maxY); + this.cache = new PiscesCache(pminX, pminY, pmaxX, pmaxY); + _endRendering(pminX, pminY, pmaxX, pmaxY); } public PiscesCache getCache() { diff --git a/src/share/classes/sun/java2d/pisces/Stroker.java b/src/share/classes/sun/java2d/pisces/Stroker.java index 7136fd6ef92eab26332db6189c10fedeee3cac9e..b898febc4c2662d0f95c0c5eb272644f968ebb33 100644 --- a/src/share/classes/sun/java2d/pisces/Stroker.java +++ b/src/share/classes/sun/java2d/pisces/Stroker.java @@ -33,7 +33,7 @@ import sun.awt.geom.PathConsumer2D; // TODO: some of the arithmetic here is too verbose and prone to hard to // debug typos. We should consider making a small Point/Vector class that // has methods like plus(Point), minus(Point), dot(Point), cross(Point)and such -public class Stroker implements PathConsumer2D { +final class Stroker implements PathConsumer2D { private static final int MOVE_TO = 0; private static final int DRAWING_OP_TO = 1; // ie. curve, line, or quad @@ -130,7 +130,7 @@ public class Stroker implements PathConsumer2D { private static void computeOffset(final float lx, final float ly, final float w, final float[] m) { - final float len = (float)Math.hypot(lx, ly); + final float len = (float)Math.sqrt(lx*lx + ly*ly); if (len == 0) { m[0] = m[1] = 0; } else { @@ -758,7 +758,7 @@ public class Stroker implements PathConsumer2D { // This is where the curve to be processed is put. We give it // enough room to store 2 curves: one for the current subdivision, the // other for the rest of the curve. - private float[][] middle = new float[2][8]; + private float[] middle = new float[2*8]; private float[] lp = new float[8]; private float[] rp = new float[8]; private static final int MAX_N_CURVES = 11; @@ -766,55 +766,55 @@ public class Stroker implements PathConsumer2D { private void somethingTo(final int type) { // need these so we can update the state at the end of this method - final float xf = middle[0][type-2], yf = middle[0][type-1]; - float dxs = middle[0][2] - middle[0][0]; - float dys = middle[0][3] - middle[0][1]; - float dxf = middle[0][type - 2] - middle[0][type - 4]; - float dyf = middle[0][type - 1] - middle[0][type - 3]; + final float xf = middle[type-2], yf = middle[type-1]; + float dxs = middle[2] - middle[0]; + float dys = middle[3] - middle[1]; + float dxf = middle[type - 2] - middle[type - 4]; + float dyf = middle[type - 1] - middle[type - 3]; switch(type) { case 6: if ((dxs == 0f && dys == 0f) || (dxf == 0f && dyf == 0f)) { - dxs = dxf = middle[0][4] - middle[0][0]; - dys = dyf = middle[0][5] - middle[0][1]; + dxs = dxf = middle[4] - middle[0]; + dys = dyf = middle[5] - middle[1]; } break; case 8: boolean p1eqp2 = (dxs == 0f && dys == 0f); boolean p3eqp4 = (dxf == 0f && dyf == 0f); if (p1eqp2) { - dxs = middle[0][4] - middle[0][0]; - dys = middle[0][5] - middle[0][1]; + dxs = middle[4] - middle[0]; + dys = middle[5] - middle[1]; if (dxs == 0f && dys == 0f) { - dxs = middle[0][6] - middle[0][0]; - dys = middle[0][7] - middle[0][1]; + dxs = middle[6] - middle[0]; + dys = middle[7] - middle[1]; } } if (p3eqp4) { - dxf = middle[0][6] - middle[0][2]; - dyf = middle[0][7] - middle[0][3]; + dxf = middle[6] - middle[2]; + dyf = middle[7] - middle[3]; if (dxf == 0f && dyf == 0f) { - dxf = middle[0][6] - middle[0][0]; - dyf = middle[0][7] - middle[0][1]; + dxf = middle[6] - middle[0]; + dyf = middle[7] - middle[1]; } } } if (dxs == 0f && dys == 0f) { // this happens iff the "curve" is just a point - lineTo(middle[0][0], middle[0][1]); + lineTo(middle[0], middle[1]); return; } // if these vectors are too small, normalize them, to avoid future // precision problems. if (Math.abs(dxs) < 0.1f && Math.abs(dys) < 0.1f) { - double len = Math.hypot(dxs, dys); - dxs = (float)(dxs / len); - dys = (float)(dys / len); + float len = (float)Math.sqrt(dxs*dxs + dys*dys); + dxs /= len; + dys /= len; } if (Math.abs(dxf) < 0.1f && Math.abs(dyf) < 0.1f) { - double len = Math.hypot(dxf, dyf); - dxf = (float)(dxf / len); - dyf = (float)(dyf / len); + float len = (float)Math.sqrt(dxf*dxf + dyf*dyf); + dxf /= len; + dyf /= len; } computeOffset(dxs, dys, lineWidth2, offset[0]); @@ -822,20 +822,20 @@ public class Stroker implements PathConsumer2D { final float my = offset[0][1]; drawJoin(cdx, cdy, cx0, cy0, dxs, dys, cmx, cmy, mx, my); - int nSplits = findSubdivPoints(middle[0], subdivTs, type,lineWidth2); + int nSplits = findSubdivPoints(middle, subdivTs, type, lineWidth2); int kind = 0; - Iterator it = Curve.breakPtsAtTs(middle, type, subdivTs, nSplits); + Iterator it = Curve.breakPtsAtTs(middle, type, subdivTs, nSplits); while(it.hasNext()) { - float[] curCurve = it.next(); + int curCurveOff = it.next(); kind = 0; switch (type) { case 8: - kind = computeOffsetCubic(curCurve, 0, lp, rp); + kind = computeOffsetCubic(middle, curCurveOff, lp, rp); break; case 6: - kind = computeOffsetQuad(curCurve, 0, lp, rp); + kind = computeOffsetQuad(middle, curCurveOff, lp, rp); break; } if (kind != 0) { @@ -871,8 +871,7 @@ public class Stroker implements PathConsumer2D { // to get good offset curves a distance of w away from the middle curve. // Stores the points in ts, and returns how many of them there were. private static Curve c = new Curve(); - private static int findSubdivPoints(float[] pts, float[] ts, - final int type, final float w) + private static int findSubdivPoints(float[] pts, float[] ts, final int type, final float w) { final float x12 = pts[2] - pts[0]; final float y12 = pts[3] - pts[1]; @@ -919,6 +918,7 @@ public class Stroker implements PathConsumer2D { // now we must subdivide at points where one of the offset curves will have // a cusp. This happens at ts where the radius of curvature is equal to w. ret += c.rootsOfROCMinusW(ts, ret, w, 0.0001f); + ret = Helpers.filterOutNotInAB(ts, 0, ret, 0.0001f, 0.9999f); Helpers.isort(ts, 0, ret); return ret; @@ -928,10 +928,10 @@ public class Stroker implements PathConsumer2D { float x2, float y2, float x3, float y3) { - middle[0][0] = cx0; middle[0][1] = cy0; - middle[0][2] = x1; middle[0][3] = y1; - middle[0][4] = x2; middle[0][5] = y2; - middle[0][6] = x3; middle[0][7] = y3; + middle[0] = cx0; middle[1] = cy0; + middle[2] = x1; middle[3] = y1; + middle[4] = x2; middle[5] = y2; + middle[6] = x3; middle[7] = y3; somethingTo(8); } @@ -940,9 +940,9 @@ public class Stroker implements PathConsumer2D { } @Override public void quadTo(float x1, float y1, float x2, float y2) { - middle[0][0] = cx0; middle[0][1] = cy0; - middle[0][2] = x1; middle[0][3] = y1; - middle[0][4] = x2; middle[0][5] = y2; + middle[0] = cx0; middle[1] = cy0; + middle[2] = x1; middle[3] = y1; + middle[4] = x2; middle[5] = y2; somethingTo(6); } diff --git a/src/share/classes/sun/java2d/pisces/TransformingPathConsumer2D.java b/src/share/classes/sun/java2d/pisces/TransformingPathConsumer2D.java index f88fa5cc948b79193105c3cab5e17b0144956c96..21192a8c0ae12f7ed14a9988fbd9c5f735f87501 100644 --- a/src/share/classes/sun/java2d/pisces/TransformingPathConsumer2D.java +++ b/src/share/classes/sun/java2d/pisces/TransformingPathConsumer2D.java @@ -28,7 +28,7 @@ package sun.java2d.pisces; import sun.awt.geom.PathConsumer2D; import java.awt.geom.AffineTransform; -public class TransformingPathConsumer2D { +final class TransformingPathConsumer2D { public static PathConsumer2D transformConsumer(PathConsumer2D out, AffineTransform at) @@ -50,17 +50,72 @@ public class TransformingPathConsumer2D { return new TranslateFilter(out, Mxt, Myt); } } else { - return new ScaleFilter(out, Mxx, Myy, Mxt, Myt); + if (Mxt == 0f && Myt == 0f) { + return new DeltaScaleFilter(out, Mxx, Myy); + } else { + return new ScaleFilter(out, Mxx, Myy, Mxt, Myt); + } } + } else if (Mxt == 0f && Myt == 0f) { + return new DeltaTransformFilter(out, Mxx, Mxy, Myx, Myy); } else { return new TransformFilter(out, Mxx, Mxy, Mxt, Myx, Myy, Myt); } } - static class TranslateFilter implements PathConsumer2D { - PathConsumer2D out; - float tx; - float ty; + public static PathConsumer2D + deltaTransformConsumer(PathConsumer2D out, + AffineTransform at) + { + if (at == null) { + return out; + } + float Mxx = (float) at.getScaleX(); + float Mxy = (float) at.getShearX(); + float Myx = (float) at.getShearY(); + float Myy = (float) at.getScaleY(); + if (Mxy == 0f && Myx == 0f) { + if (Mxx == 1f && Myy == 1f) { + return out; + } else { + return new DeltaScaleFilter(out, Mxx, Myy); + } + } else { + return new DeltaTransformFilter(out, Mxx, Mxy, Myx, Myy); + } + } + + public static PathConsumer2D + inverseDeltaTransformConsumer(PathConsumer2D out, + AffineTransform at) + { + if (at == null) { + return out; + } + float Mxx = (float) at.getScaleX(); + float Mxy = (float) at.getShearX(); + float Myx = (float) at.getShearY(); + float Myy = (float) at.getScaleY(); + if (Mxy == 0f && Myx == 0f) { + if (Mxx == 1f && Myy == 1f) { + return out; + } else { + return new DeltaScaleFilter(out, 1.0f/Mxx, 1.0f/Myy); + } + } else { + float det = Mxx * Myy - Mxy * Myx; + return new DeltaTransformFilter(out, + Myy / det, + -Mxy / det, + -Myx / det, + Mxx / det); + } + } + + static final class TranslateFilter implements PathConsumer2D { + private final PathConsumer2D out; + private final float tx; + private final float ty; TranslateFilter(PathConsumer2D out, float tx, float ty) @@ -107,12 +162,12 @@ public class TransformingPathConsumer2D { } } - static class ScaleFilter implements PathConsumer2D { - PathConsumer2D out; - float sx; - float sy; - float tx; - float ty; + static final class ScaleFilter implements PathConsumer2D { + private final PathConsumer2D out; + private final float sx; + private final float sy; + private final float tx; + private final float ty; ScaleFilter(PathConsumer2D out, float sx, float sy, float tx, float ty) @@ -161,14 +216,14 @@ public class TransformingPathConsumer2D { } } - static class TransformFilter implements PathConsumer2D { - PathConsumer2D out; - float Mxx; - float Mxy; - float Mxt; - float Myx; - float Myy; - float Myt; + static final class TransformFilter implements PathConsumer2D { + private final PathConsumer2D out; + private final float Mxx; + private final float Mxy; + private final float Mxt; + private final float Myx; + private final float Myy; + private final float Myt; TransformFilter(PathConsumer2D out, float Mxx, float Mxy, float Mxt, @@ -226,4 +281,113 @@ public class TransformingPathConsumer2D { return 0; } } + + static final class DeltaScaleFilter implements PathConsumer2D { + private final float sx, sy; + private final PathConsumer2D out; + + public DeltaScaleFilter(PathConsumer2D out, float Mxx, float Myy) { + sx = Mxx; + sy = Myy; + this.out = out; + } + + public void moveTo(float x0, float y0) { + out.moveTo(x0 * sx, y0 * sy); + } + + public void lineTo(float x1, float y1) { + out.lineTo(x1 * sx, y1 * sy); + } + + public void quadTo(float x1, float y1, + float x2, float y2) + { + out.quadTo(x1 * sx, y1 * sy, + x2 * sx, y2 * sy); + } + + public void curveTo(float x1, float y1, + float x2, float y2, + float x3, float y3) + { + out.curveTo(x1 * sx, y1 * sy, + x2 * sx, y2 * sy, + x3 * sx, y3 * sy); + } + + public void closePath() { + out.closePath(); + } + + public void pathDone() { + out.pathDone(); + } + + public long getNativeConsumer() { + return 0; + } + } + + static final class DeltaTransformFilter implements PathConsumer2D { + private PathConsumer2D out; + private final float Mxx; + private final float Mxy; + private final float Myx; + private final float Myy; + + DeltaTransformFilter(PathConsumer2D out, + float Mxx, float Mxy, + float Myx, float Myy) + { + this.out = out; + this.Mxx = Mxx; + this.Mxy = Mxy; + this.Myx = Myx; + this.Myy = Myy; + } + + public void moveTo(float x0, float y0) { + out.moveTo(x0 * Mxx + y0 * Mxy, + x0 * Myx + y0 * Myy); + } + + public void lineTo(float x1, float y1) { + out.lineTo(x1 * Mxx + y1 * Mxy, + x1 * Myx + y1 * Myy); + } + + public void quadTo(float x1, float y1, + float x2, float y2) + { + out.quadTo(x1 * Mxx + y1 * Mxy, + x1 * Myx + y1 * Myy, + x2 * Mxx + y2 * Mxy, + x2 * Myx + y2 * Myy); + } + + public void curveTo(float x1, float y1, + float x2, float y2, + float x3, float y3) + { + out.curveTo(x1 * Mxx + y1 * Mxy, + x1 * Myx + y1 * Myy, + x2 * Mxx + y2 * Mxy, + x2 * Myx + y2 * Myy, + x3 * Mxx + y3 * Mxy, + x3 * Myx + y3 * Myy); + } + + public void closePath() { + out.closePath(); + } + + public void pathDone() { + out.pathDone(); + } + + public long getNativeConsumer() { + return 0; + } + } } diff --git a/src/share/classes/sun/launcher/LauncherHelper.java b/src/share/classes/sun/launcher/LauncherHelper.java index 3ca01da645c35c9b0b1e82d5836be7f115be5006..870ed30e9f01bc48c02dad8951cf67be35e8c6d1 100644 --- a/src/share/classes/sun/launcher/LauncherHelper.java +++ b/src/share/classes/sun/launcher/LauncherHelper.java @@ -401,6 +401,14 @@ public enum LauncherHelper { } } + + // From src/share/bin/java.c: + // enum LaunchMode { LM_UNKNOWN = 0, LM_CLASS, LM_JAR }; + + private static final int LM_UNKNOWN = 0; + private static final int LM_CLASS = 1; + private static final int LM_JAR = 2; + /** * This method does the following: * 1. gets the classname from a Jar's manifest, if necessary @@ -420,24 +428,40 @@ public enum LauncherHelper { * @return * @throws java.io.IOException */ - public static Object checkAndLoadMain(boolean printToStderr, - boolean isJar, String name) throws IOException { + public static Class checkAndLoadMain(boolean printToStderr, + int mode, + String what) throws IOException + { + + ClassLoader ld = ClassLoader.getSystemClassLoader(); + // get the class name - String classname = (isJar) ? getMainClassFromJar(name) : name; - classname = classname.replace('/', '.'); - ClassLoader loader = ClassLoader.getSystemClassLoader(); - Class clazz = null; + String cn = null; + switch (mode) { + case LM_CLASS: + cn = what; + break; + case LM_JAR: + cn = getMainClassFromJar(what); + break; + default: + throw new InternalError("" + mode + ": Unknown launch mode"); + } + cn = cn.replace('/', '.'); + PrintStream ostream = (printToStderr) ? System.err : System.out; + Class c = null; try { - clazz = loader.loadClass(classname); + c = ld.loadClass(cn); } catch (ClassNotFoundException cnfe) { - ostream.println(getLocalizedMessage("java.launcher.cls.error1", classname)); - NoClassDefFoundError ncdfe = new NoClassDefFoundError(classname); + ostream.println(getLocalizedMessage("java.launcher.cls.error1", + cn)); + NoClassDefFoundError ncdfe = new NoClassDefFoundError(cn); ncdfe.initCause(cnfe); throw ncdfe; } - signatureDiagnostic(ostream, clazz); - return clazz; + signatureDiagnostic(ostream, c); + return c; } static void signatureDiagnostic(PrintStream ostream, Class clazz) { diff --git a/src/share/classes/sun/management/ThreadImpl.java b/src/share/classes/sun/management/ThreadImpl.java index 19f4bf7a2af0405fbb33c77eb7485a3f2d4931d5..019646ad4fe7c583e2e56fe2a684d1a06339696f 100644 --- a/src/share/classes/sun/management/ThreadImpl.java +++ b/src/share/classes/sun/management/ThreadImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ package sun.management; -import java.lang.management.ThreadMXBean; import java.lang.management.ManagementFactory; import java.lang.management.ThreadInfo; @@ -39,13 +38,14 @@ import javax.management.ObjectName; * ManagementFactory.getThreadMXBean() returns an instance * of this class. */ -class ThreadImpl implements ThreadMXBean { +class ThreadImpl implements com.sun.management.ThreadMXBean { private final VMManagement jvm; // default for thread contention monitoring is disabled. private boolean contentionMonitoringEnabled = false; private boolean cpuTimeEnabled; + private boolean allocatedMemoryEnabled; /** * Constructor of ThreadImpl class. @@ -53,6 +53,7 @@ class ThreadImpl implements ThreadMXBean { ThreadImpl(VMManagement vm) { this.jvm = vm; this.cpuTimeEnabled = jvm.isThreadCpuTimeEnabled(); + this.allocatedMemoryEnabled = jvm.isThreadAllocatedMemoryEnabled(); } public int getThreadCount() { @@ -91,6 +92,10 @@ class ThreadImpl implements ThreadMXBean { return jvm.isCurrentThreadCpuTimeSupported(); } + public boolean isThreadAllocatedMemorySupported() { + return jvm.isThreadAllocatedMemorySupported(); + } + public boolean isThreadCpuTimeEnabled() { if (!isThreadCpuTimeSupported() && !isCurrentThreadCpuTimeSupported()) { @@ -100,6 +105,14 @@ class ThreadImpl implements ThreadMXBean { return cpuTimeEnabled; } + public boolean isThreadAllocatedMemoryEnabled() { + if (!isThreadAllocatedMemorySupported()) { + throw new UnsupportedOperationException( + "Thread allocated memory measurement is not supported"); + } + return allocatedMemoryEnabled; + } + public long[] getAllThreadIds() { Util.checkMonitorAccess(); @@ -114,11 +127,6 @@ class ThreadImpl implements ThreadMXBean { } public ThreadInfo getThreadInfo(long id) { - if (id <= 0) { - throw new IllegalArgumentException( - "Invalid thread ID parameter: " + id); - } - long[] ids = new long[1]; ids[0] = id; final ThreadInfo[] infos = getThreadInfo(ids, 0); @@ -126,15 +134,6 @@ class ThreadImpl implements ThreadMXBean { } public ThreadInfo getThreadInfo(long id, int maxDepth) { - if (id <= 0) { - throw new IllegalArgumentException( - "Invalid thread ID parameter: " + id); - } - if (maxDepth < 0) { - throw new IllegalArgumentException( - "Invalid maxDepth parameter: " + maxDepth); - } - long[] ids = new long[1]; ids[0] = id; final ThreadInfo[] infos = getThreadInfo(ids, maxDepth); @@ -145,11 +144,22 @@ class ThreadImpl implements ThreadMXBean { return getThreadInfo(ids, 0); } - public ThreadInfo[] getThreadInfo(long[] ids, int maxDepth) { + private void verifyThreadIds(long[] ids) { if (ids == null) { throw new NullPointerException("Null ids parameter."); } + for (int i = 0; i < ids.length; i++) { + if (ids[i] <= 0) { + throw new IllegalArgumentException( + "Invalid thread ID parameter: " + ids[i]); + } + } + } + + public ThreadInfo[] getThreadInfo(long[] ids, int maxDepth) { + verifyThreadIds(ids); + if (maxDepth < 0) { throw new IllegalArgumentException( "Invalid maxDepth parameter: " + maxDepth); @@ -157,17 +167,15 @@ class ThreadImpl implements ThreadMXBean { Util.checkMonitorAccess(); - ThreadInfo[] infos = new ThreadInfo[ids.length]; + ThreadInfo[] infos = new ThreadInfo[ids.length]; // nulls if (maxDepth == Integer.MAX_VALUE) { - getThreadInfo0(ids, -1, infos); + getThreadInfo1(ids, -1, infos); } else { - getThreadInfo0(ids, maxDepth, infos); + getThreadInfo1(ids, maxDepth, infos); } return infos; } - - public void setThreadContentionMonitoringEnabled(boolean enable) { if (!isThreadContentionMonitoringSupported()) { throw new UnsupportedOperationException( @@ -192,116 +200,169 @@ class ThreadImpl implements ThreadMXBean { } } - public long getCurrentThreadCpuTime() { + private boolean verifyCurrentThreadCpuTime() { // check if Thread CPU time measurement is supported. if (!isCurrentThreadCpuTimeSupported()) { throw new UnsupportedOperationException( "Current thread CPU time measurement is not supported."); } + return isThreadCpuTimeEnabled(); + } - if (!isThreadCpuTimeEnabled()) { - return -1; + public long getCurrentThreadCpuTime() { + if (verifyCurrentThreadCpuTime()) { + return getThreadTotalCpuTime0(0); } - - return getThreadTotalCpuTime0(0); + return -1; } public long getThreadCpuTime(long id) { + long[] ids = new long[1]; + ids[0] = id; + final long[] times = getThreadCpuTime(ids); + return times[0]; + } + + private boolean verifyThreadCpuTime(long[] ids) { + verifyThreadIds(ids); + // check if Thread CPU time measurement is supported. if (!isThreadCpuTimeSupported() && !isCurrentThreadCpuTimeSupported()) { throw new UnsupportedOperationException( - "Thread CPU Time Measurement is not supported."); + "Thread CPU time measurement is not supported."); } if (!isThreadCpuTimeSupported()) { // support current thread only - if (id != Thread.currentThread().getId()) { - throw new UnsupportedOperationException( - "Thread CPU Time Measurement is only supported" + - " for the current thread."); + for (int i = 0; i < ids.length; i++) { + if (ids[i] != Thread.currentThread().getId()) { + throw new UnsupportedOperationException( + "Thread CPU time measurement is only supported" + + " for the current thread."); + } } } - if (id <= 0) { - throw new IllegalArgumentException( - "Invalid thread ID parameter: " + id); - } + return isThreadCpuTimeEnabled(); + } - if (!isThreadCpuTimeEnabled()) { - return -1; - } + public long[] getThreadCpuTime(long[] ids) { + boolean verified = verifyThreadCpuTime(ids); - if (id == Thread.currentThread().getId()) { - // current thread - return getThreadTotalCpuTime0(0); - } else { - return getThreadTotalCpuTime0(id); + int length = ids.length; + long[] times = new long[length]; + java.util.Arrays.fill(times, -1); + + if (verified) { + if (length == 1) { + long id = ids[0]; + if (id == Thread.currentThread().getId()) { + id = 0; + } + times[0] = getThreadTotalCpuTime0(id); + } else { + getThreadTotalCpuTime1(ids, times); + } } + return times; } public long getCurrentThreadUserTime() { - // check if Thread CPU time measurement is supported. - if (!isCurrentThreadCpuTimeSupported()) { - throw new UnsupportedOperationException( - "Current thread CPU time measurement is not supported."); + if (verifyCurrentThreadCpuTime()) { + return getThreadUserCpuTime0(0); } + return -1; + } - if (!isThreadCpuTimeEnabled()) { - return -1; - } + public long getThreadUserTime(long id) { + long[] ids = new long[1]; + ids[0] = id; + final long[] times = getThreadUserTime(ids); + return times[0]; + } - return getThreadUserCpuTime0(0); + public long[] getThreadUserTime(long[] ids) { + boolean verified = verifyThreadCpuTime(ids); + + int length = ids.length; + long[] times = new long[length]; + java.util.Arrays.fill(times, -1); + + if (verified) { + if (length == 1) { + long id = ids[0]; + if (id == Thread.currentThread().getId()) { + id = 0; + } + times[0] = getThreadUserCpuTime0(id); + } else { + getThreadUserCpuTime1(ids, times); + } + } + return times; } - public long getThreadUserTime(long id) { - // check if Thread CPU time measurement is supported. + public void setThreadCpuTimeEnabled(boolean enable) { if (!isThreadCpuTimeSupported() && !isCurrentThreadCpuTimeSupported()) { throw new UnsupportedOperationException( - "Thread CPU time measurement is not supported."); + "Thread CPU time measurement is not supported"); } - if (!isThreadCpuTimeSupported()) { - // support current thread only - if (id != Thread.currentThread().getId()) { - throw new UnsupportedOperationException( - "Thread CPU time measurement is only supported" + - " for the current thread."); + Util.checkControlAccess(); + synchronized (this) { + if (cpuTimeEnabled != enable) { + // notify VM of the state change + setThreadCpuTimeEnabled0(enable); + cpuTimeEnabled = enable; } } + } - if (id <= 0) { - throw new IllegalArgumentException( - "Invalid thread ID parameter: " + id); - } + public long getThreadAllocatedBytes(long id) { + long[] ids = new long[1]; + ids[0] = id; + final long[] sizes = getThreadAllocatedBytes(ids); + return sizes[0]; + } - if (!isThreadCpuTimeEnabled()) { - return -1; - } + private boolean verifyThreadAllocatedMemory(long[] ids) { + verifyThreadIds(ids); - if (id == Thread.currentThread().getId()) { - // current thread - return getThreadUserCpuTime0(0); - } else { - return getThreadUserCpuTime0(id); + // check if Thread allocated memory measurement is supported. + if (!isThreadAllocatedMemorySupported()) { + throw new UnsupportedOperationException( + "Thread allocated memory measurement is not supported."); } + + return isThreadAllocatedMemoryEnabled(); } + public long[] getThreadAllocatedBytes(long[] ids) { + boolean verified = verifyThreadAllocatedMemory(ids); - public void setThreadCpuTimeEnabled(boolean enable) { - if (!isThreadCpuTimeSupported() && - !isCurrentThreadCpuTimeSupported()) { + long[] sizes = new long[ids.length]; + java.util.Arrays.fill(sizes, -1); + + if (verified) { + getThreadAllocatedMemory1(ids, sizes); + } + return sizes; + } + + public void setThreadAllocatedMemoryEnabled(boolean enable) { + if (!isThreadAllocatedMemorySupported()) { throw new UnsupportedOperationException( - "Thread CPU time measurement is not supported"); + "Thread allocated memory measurement is not supported."); } Util.checkControlAccess(); synchronized (this) { - if (cpuTimeEnabled != enable) { - // update VM of the state change - setThreadCpuTimeEnabled0(enable); - cpuTimeEnabled = enable; + if (allocatedMemoryEnabled != enable) { + // notify VM of the state change + setThreadAllocatedMemoryEnabled0(enable); + allocatedMemoryEnabled = enable; } } } @@ -356,49 +417,47 @@ class ThreadImpl implements ThreadMXBean { return jvm.isSynchronizerUsageSupported(); } - public ThreadInfo[] getThreadInfo(long[] ids, - boolean lockedMonitors, - boolean lockedSynchronizers) { - if (ids == null) { - throw new NullPointerException("Null ids parameter."); - } - + private void verifyDumpThreads(boolean lockedMonitors, + boolean lockedSynchronizers) { if (lockedMonitors && !isObjectMonitorUsageSupported()) { throw new UnsupportedOperationException( "Monitoring of Object Monitor Usage is not supported."); } + if (lockedSynchronizers && !isSynchronizerUsageSupported()) { throw new UnsupportedOperationException( "Monitoring of Synchronizer Usage is not supported."); } Util.checkMonitorAccess(); - return dumpThreads0(ids, lockedMonitors, lockedSynchronizers); } + public ThreadInfo[] getThreadInfo(long[] ids, + boolean lockedMonitors, + boolean lockedSynchronizers) { + verifyThreadIds(ids); + verifyDumpThreads(lockedMonitors, lockedSynchronizers); + return dumpThreads0(ids, lockedMonitors, lockedSynchronizers); + } - public ThreadInfo[] dumpAllThreads(boolean lockedMonitors, boolean lockedSynchronizers) { - if (lockedMonitors && !isObjectMonitorUsageSupported()) { - throw new UnsupportedOperationException( - "Monitoring of Object Monitor Usage is not supported."); - } - if (lockedSynchronizers && !isSynchronizerUsageSupported()) { - throw new UnsupportedOperationException( - "Monitoring of Synchronizer Usage is not supported."); - } - - Util.checkMonitorAccess(); + public ThreadInfo[] dumpAllThreads(boolean lockedMonitors, + boolean lockedSynchronizers) { + verifyDumpThreads(lockedMonitors, lockedSynchronizers); return dumpThreads0(null, lockedMonitors, lockedSynchronizers); } // VM support where maxDepth == -1 to request entire stack dump private static native Thread[] getThreads(); - private static native void getThreadInfo0(long[] ids, + private static native void getThreadInfo1(long[] ids, int maxDepth, ThreadInfo[] result); private static native long getThreadTotalCpuTime0(long id); + private static native void getThreadTotalCpuTime1(long[] ids, long[] result); private static native long getThreadUserCpuTime0(long id); + private static native void getThreadUserCpuTime1(long[] ids, long[] result); + private static native void getThreadAllocatedMemory1(long[] ids, long[] result); private static native void setThreadCpuTimeEnabled0(boolean enable); + private static native void setThreadAllocatedMemoryEnabled0(boolean enable); private static native void setThreadContentionMonitoringEnabled0(boolean enable); private static native Thread[] findMonitorDeadlockedThreads0(); private static native Thread[] findDeadlockedThreads0(); diff --git a/src/share/classes/sun/management/VMManagement.java b/src/share/classes/sun/management/VMManagement.java index 81d6e8015550ba0a08eeb0fc32e827022617e75d..607f6cf88aa03155be0720ba04112b46bdb38b71 100644 --- a/src/share/classes/sun/management/VMManagement.java +++ b/src/share/classes/sun/management/VMManagement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,6 +43,8 @@ public interface VMManagement { public boolean isBootClassPathSupported(); public boolean isObjectMonitorUsageSupported(); public boolean isSynchronizerUsageSupported(); + public boolean isThreadAllocatedMemorySupported(); + public boolean isThreadAllocatedMemoryEnabled(); // Class Loading Subsystem public long getTotalClassCount(); diff --git a/src/share/classes/sun/management/VMManagementImpl.java b/src/share/classes/sun/management/VMManagementImpl.java index fe0ec0e557c691b190ff2bb6e2f3957d0b1e4b49..d5b00ea117f61b5ca6b973de12ccfdd08e7fa8e8 100644 --- a/src/share/classes/sun/management/VMManagementImpl.java +++ b/src/share/classes/sun/management/VMManagementImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,6 +55,7 @@ class VMManagementImpl implements VMManagement { private static boolean bootClassPathSupport; private static boolean objectMonitorUsageSupport; private static boolean synchronizerUsageSupport; + private static boolean threadAllocatedMemorySupport; static { version = getVersion0(); @@ -95,9 +96,13 @@ class VMManagementImpl implements VMManagement { return synchronizerUsageSupport; } + public boolean isThreadAllocatedMemorySupported() { + return threadAllocatedMemorySupport; + } + public native boolean isThreadContentionMonitoringEnabled(); public native boolean isThreadCpuTimeEnabled(); - + public native boolean isThreadAllocatedMemoryEnabled(); // Class Loading Subsystem public int getLoadedClassCount() { diff --git a/src/share/classes/sun/misc/URLClassPath.java b/src/share/classes/sun/misc/URLClassPath.java index c828ab3e16e4ac36bed56c9063b8a7e0a0834589..d7664f1be7b25387a224c07603f444102ed05bfc 100644 --- a/src/share/classes/sun/misc/URLClassPath.java +++ b/src/share/classes/sun/misc/URLClassPath.java @@ -466,6 +466,7 @@ public class URLClassPath { */ private static class Loader implements Closeable { private final URL base; + private JarFile jarfile; // if this points to a jar file /* * Creates a new Loader for the specified URL. @@ -530,6 +531,17 @@ public class URLClassPath { } uc = url.openConnection(); InputStream in = uc.getInputStream(); + if (uc instanceof JarURLConnection) { + /* JarURLConnection.getInputStream() returns a separate + * instance on each call. So we have to close this here. + * The jar file cache will keep the file open. + * Also, need to remember the jar file so it can be closed + * in a hurry. + */ + JarURLConnection juc = (JarURLConnection)uc; + jarfile = juc.getJarFile(); + in.close(); + } } catch (Exception e) { return null; } @@ -559,7 +571,11 @@ public class URLClassPath { * close this loader and release all resources * method overridden in sub-classes */ - public void close () throws IOException {} + public void close () throws IOException { + if (jarfile != null) { + jarfile.close(); + } + } /* * Returns the local class path for this loader, or null if none. diff --git a/src/solaris/hpi/include/largefile_linux.h b/src/share/classes/sun/net/SocksProxy.java similarity index 65% rename from src/solaris/hpi/include/largefile_linux.h rename to src/share/classes/sun/net/SocksProxy.java index 580047bf49ea98c213321187eb7a44e692edfc80..90826c0f196f948513c3411c8692ddc9a46fe69f 100644 --- a/src/solaris/hpi/include/largefile_linux.h +++ b/src/share/classes/sun/net/SocksProxy.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,14 +23,27 @@ * questions. */ -#ifndef _JAVASOFT_LINUX_LARGEFILE_SUPPORT_H_ -#define _JAVASOFT_LINUX_LARGEFILE_SUPPORT_H_ +package sun.net; -/* - * For building on glibc-2.0 we need to define stat64 here. +import java.net.Proxy; +import java.net.SocketAddress; + +/** + * Proxy wrapper class so we can determine the socks protocol version. */ +public final class SocksProxy extends Proxy { + private final int version; + + private SocksProxy(SocketAddress addr, int version) { + super(Proxy.Type.SOCKS, addr); + this.version = version; + } -#include -#include + public static SocksProxy create(SocketAddress addr, int version) { + return new SocksProxy(addr, version); + } -#endif /* _JAVASOFT_LINUX_LARGEFILE_SUPPORT_H_ */ + public int protocolVersion() { + return version; + } +} diff --git a/src/share/classes/sun/net/spi/DefaultProxySelector.java b/src/share/classes/sun/net/spi/DefaultProxySelector.java index c939f9e01b89d9dbc28d86d412b8ddd7abbfc084..5b425a9d0c98fd995774bd859de894bf199662fd 100644 --- a/src/share/classes/sun/net/spi/DefaultProxySelector.java +++ b/src/share/classes/sun/net/spi/DefaultProxySelector.java @@ -25,13 +25,20 @@ package sun.net.spi; -import sun.net.NetProperties; -import java.net.*; -import java.util.*; -import java.io.*; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.ProxySelector; +import java.net.SocketAddress; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; +import java.io.IOException; import sun.misc.RegexpPool; import java.security.AccessController; import java.security.PrivilegedAction; +import sun.net.NetProperties; +import sun.net.SocksProxy; /** * Supports proxy settings using system properties This proxy selector @@ -75,6 +82,8 @@ public class DefaultProxySelector extends ProxySelector { {"socket", "socksProxy"} }; + private static final String SOCKS_PROXY_VERSION = "socksProxyVersion"; + private static boolean hasSystemProxies = false; static { @@ -287,7 +296,8 @@ public class DefaultProxySelector extends ProxySelector { saddr = InetSocketAddress.createUnresolved(phost, pport); // Socks is *always* the last on the list. if (j == (props[i].length - 1)) { - return new Proxy(Proxy.Type.SOCKS, saddr); + int version = NetProperties.getInteger(SOCKS_PROXY_VERSION, 5).intValue(); + return SocksProxy.create(saddr, version); } else { return new Proxy(Proxy.Type.HTTP, saddr); } diff --git a/src/share/classes/sun/net/www/http/KeepAliveCache.java b/src/share/classes/sun/net/www/http/KeepAliveCache.java index 4ba3d5eb24dac53c3044d882fa5a9d19cb698194..e75e294c1e224225579fd846310514564c61e23c 100644 --- a/src/share/classes/sun/net/www/http/KeepAliveCache.java +++ b/src/share/classes/sun/net/www/http/KeepAliveCache.java @@ -267,7 +267,7 @@ class ClientVector extends java.util.Stack { /* return a still valid, unused HttpClient */ synchronized void put(HttpClient h) { - if (size() > KeepAliveCache.getMaxConnections()) { + if (size() >= KeepAliveCache.getMaxConnections()) { h.closeServer(); // otherwise the connection remains in limbo } else { push(new KeepAliveEntry(h, System.currentTimeMillis())); diff --git a/src/share/classes/sun/security/acl/AclEntryImpl.java b/src/share/classes/sun/security/acl/AclEntryImpl.java index 521e73b8f9c03fbddeab050ea7d31da71185beaa..2bc035469b8efaded3304ffb6c7f2e060af78c94 100644 --- a/src/share/classes/sun/security/acl/AclEntryImpl.java +++ b/src/share/classes/sun/security/acl/AclEntryImpl.java @@ -37,7 +37,7 @@ import java.security.acl.*; */ public class AclEntryImpl implements AclEntry { private Principal user = null; - private Vector permissionSet = new Vector(10, 10); + private Vector permissionSet = new Vector<>(10, 10); private boolean negative = false; /** diff --git a/src/share/classes/sun/security/acl/AclImpl.java b/src/share/classes/sun/security/acl/AclImpl.java index 6a6da4bea854387a6cfaebdbb001fa743ce2577e..d8ea50d3fb9e2dadf1df785c6f1148c283b58059 100644 --- a/src/share/classes/sun/security/acl/AclImpl.java +++ b/src/share/classes/sun/security/acl/AclImpl.java @@ -41,15 +41,15 @@ public class AclImpl extends OwnerImpl implements Acl { // or principal. // private Hashtable allowedUsersTable = - new Hashtable(23); + new Hashtable<>(23); private Hashtable allowedGroupsTable = - new Hashtable(23); + new Hashtable<>(23); private Hashtable deniedUsersTable = - new Hashtable(23); + new Hashtable<>(23); private Hashtable deniedGroupsTable = - new Hashtable(23); + new Hashtable<>(23); private String aclName = null; - private Vector zeroSet = new Vector(1,1); + private Vector zeroSet = new Vector<>(1,1); /** @@ -294,7 +294,7 @@ public class AclImpl extends OwnerImpl implements Acl { // private static Enumeration union(Enumeration e1, Enumeration e2) { - Vector v = new Vector(20, 20); + Vector v = new Vector<>(20, 20); while (e1.hasMoreElements()) v.addElement(e1.nextElement()); @@ -313,7 +313,7 @@ public class AclImpl extends OwnerImpl implements Acl { // private Enumeration subtract(Enumeration e1, Enumeration e2) { - Vector v = new Vector(20, 20); + Vector v = new Vector<>(20, 20); while (e1.hasMoreElements()) v.addElement(e1.nextElement()); diff --git a/src/share/classes/sun/security/acl/GroupImpl.java b/src/share/classes/sun/security/acl/GroupImpl.java index e475b795c7de7b5302b44c91ee63d26d9b9d7ad9..586c705bc0cfd19b77d0ad9aa70da632cc9efb00 100644 --- a/src/share/classes/sun/security/acl/GroupImpl.java +++ b/src/share/classes/sun/security/acl/GroupImpl.java @@ -34,7 +34,7 @@ import java.security.acl.*; * @author Satish Dharmaraj */ public class GroupImpl implements Group { - private Vector groupMembers = new Vector(50, 100); + private Vector groupMembers = new Vector<>(50, 100); private String group; /** @@ -131,7 +131,7 @@ public class GroupImpl implements Group { if (groupMembers.contains(member)) { return true; } else { - Vector alreadySeen = new Vector(10); + Vector alreadySeen = new Vector<>(10); return isMemberRecurse(member, alreadySeen); } } diff --git a/src/share/classes/sun/security/jca/ProviderList.java b/src/share/classes/sun/security/jca/ProviderList.java index aae0fd2dcdeda6afed0fc74ac0bc8c6f2a848bf4..26bc91627612269efebb6320555edc8d8ee5aba8 100644 --- a/src/share/classes/sun/security/jca/ProviderList.java +++ b/src/share/classes/sun/security/jca/ProviderList.java @@ -96,7 +96,7 @@ public final class ProviderList { if (providerList.getProvider(p.getName()) != null) { return providerList; } - List list = new ArrayList + List list = new ArrayList<> (Arrays.asList(providerList.configs)); int n = list.size(); if ((position < 0) || (position > n)) { @@ -160,7 +160,7 @@ public final class ProviderList { * Return a new ProviderList parsed from the java.security Properties. */ private ProviderList() { - List configList = new ArrayList(); + List configList = new ArrayList<>(); for (int i = 1; true; i++) { String entry = Security.getProperty("security.provider." + i); if (entry == null) { @@ -200,7 +200,7 @@ public final class ProviderList { * possible recursion and deadlock during verification. */ ProviderList getJarList(String[] jarClassNames) { - List newConfigs = new ArrayList(); + List newConfigs = new ArrayList<>(); for (String className : jarClassNames) { ProviderConfig newConfig = new ProviderConfig(className); for (ProviderConfig config : configs) { @@ -356,7 +356,7 @@ public final class ProviderList { */ @Deprecated public List getServices(String type, List algorithms) { - List ids = new ArrayList(); + List ids = new ArrayList<>(); for (String alg : algorithms) { ids.add(new ServiceId(type, alg)); } diff --git a/src/share/classes/sun/security/jca/Providers.java b/src/share/classes/sun/security/jca/Providers.java index 329689f1aab6fcdde5bd517e7d9a354b5a83ed3f..c3903b7145eb95753487246bb43af8ce6c0f7f89 100644 --- a/src/share/classes/sun/security/jca/Providers.java +++ b/src/share/classes/sun/security/jca/Providers.java @@ -40,7 +40,7 @@ import java.security.Security; public class Providers { private static final ThreadLocal threadLists = - new InheritableThreadLocal(); + new InheritableThreadLocal<>(); // number of threads currently using thread-local provider lists // tracked to allow an optimization if == 0 diff --git a/src/share/classes/sun/security/krb5/Config.java b/src/share/classes/sun/security/krb5/Config.java index 272c3b1e6ca66f626ea91935a2980594ec92f3f6..09017bf7a3e65963b5a99e688395a95a31e9658b 100644 --- a/src/share/classes/sun/security/krb5/Config.java +++ b/src/share/classes/sun/security/krb5/Config.java @@ -528,7 +528,7 @@ public class Config { } }))); String Line; - Vector v = new Vector (); + Vector v = new Vector<>(); String previous = null; while ((Line = br.readLine()) != null) { // ignore comments and blank line in the configuration file. @@ -589,7 +589,7 @@ public class Config { throw new KrbException("I/O error while reading" + " configuration file."); } - Hashtable table = new Hashtable (); + Hashtable table = new Hashtable<>(); for (int i = 0; i < v.size(); i++) { String line = v.elementAt(i).trim(); if (line.equalsIgnoreCase("[realms]")) { @@ -598,7 +598,7 @@ public class Config { if ((count == v.size()) || (v.elementAt(count).startsWith("["))) { Hashtable>> temp = - new Hashtable>>(); + new Hashtable<>(); temp = parseRealmField(v, i + 1, count); table.put("realms", temp); i = count - 1; @@ -611,7 +611,7 @@ public class Config { if ((count == v.size()) || (v.elementAt(count).startsWith("["))) { Hashtable>> temp = - new Hashtable>>(); + new Hashtable<>(); temp = parseRealmField(v, i + 1, count); table.put("capaths", temp); i = count - 1; @@ -729,7 +729,7 @@ public class Config { * Parses key-value pairs under a stanza name. */ private Hashtable parseField(Vector v, int start, int end) { - Hashtable table = new Hashtable (); + Hashtable table = new Hashtable<>(); String line; for (int i = start; i < end; i++) { line = v.elementAt(i); @@ -751,7 +751,7 @@ public class Config { * information for the realm given within a pair of braces. */ private Hashtable>> parseRealmField(Vector v, int start, int end) { - Hashtable>> table = new Hashtable>> (); + Hashtable>> table = new Hashtable<>(); String line; for (int i = start; i < end; i++) { line = v.elementAt(i).trim(); @@ -791,10 +791,9 @@ public class Config { * Parses key-value pairs within each braces under [realms]. */ private Hashtable> parseRealmFieldEx(Vector v, int start, int end) { - Hashtable> table = - new Hashtable> (); - Vector keyVector = new Vector (); - Vector nameVector = new Vector (); + Hashtable> table = new Hashtable<>(); + Vector keyVector = new Vector<>(); + Vector nameVector = new Vector<>(); String line = ""; String key; for (int i = start; i < end; i++) { @@ -899,7 +898,7 @@ public class Config { } st = new StringTokenizer(default_enctypes, delim); int len = st.countTokens(); - ArrayList ls = new ArrayList (len); + ArrayList ls = new ArrayList<>(len); int type; for (int i = 0; i < len; i++) { type = getType(st.nextToken()); diff --git a/src/share/classes/sun/security/krb5/KdcComm.java b/src/share/classes/sun/security/krb5/KdcComm.java index 22e54afe5e86aeaf30200df1aed85f11ee31ded0..bb113392db17ab989a77dcaefa71d3f25abcb4bd 100644 --- a/src/share/classes/sun/security/krb5/KdcComm.java +++ b/src/share/classes/sun/security/krb5/KdcComm.java @@ -462,7 +462,7 @@ public final class KdcComm { */ static class KdcAccessibility { // Known bad KDCs - private static Set bads = new HashSet(); + private static Set bads = new HashSet<>(); private static synchronized void addBad(String kdc) { if (DEBUG) { @@ -492,9 +492,9 @@ public final class KdcComm { // Returns a preferred KDC list by putting the bad ones at the end private static synchronized String[] list(String kdcList) { StringTokenizer st = new StringTokenizer(kdcList); - List list = new ArrayList(); + List list = new ArrayList<>(); if (badPolicy == BpType.TRY_LAST) { - List badkdcs = new ArrayList(); + List badkdcs = new ArrayList<>(); while (st.hasMoreTokens()) { String t = st.nextToken(); if (bads.contains(t)) badkdcs.add(t); diff --git a/src/share/classes/sun/security/krb5/PrincipalName.java b/src/share/classes/sun/security/krb5/PrincipalName.java index 647f7199b3fd6b5f8d84ad1e58329a9285e3e2ce..11d11dbfa0e08e67303b7fb6d51c0ca3d7b8451d 100644 --- a/src/share/classes/sun/security/krb5/PrincipalName.java +++ b/src/share/classes/sun/security/krb5/PrincipalName.java @@ -244,7 +244,7 @@ public class PrincipalName if (subDer.getTag() != DerValue.tag_SequenceOf) { throw new Asn1Exception(Krb5.ASN1_BAD_ID); } - Vector v = new Vector (); + Vector v = new Vector<>(); DerValue subSubDer; while(subDer.getData().available() > 0) { subSubDer = subDer.getData().getDerValue(); @@ -299,7 +299,7 @@ public class PrincipalName // Code repetition, realm parsed again by class Realm protected static String[] parseName(String name) { - Vector tempStrings = new Vector (); + Vector tempStrings = new Vector<>(); String temp = name; int i = 0; int componentStart = 0; diff --git a/src/share/classes/sun/security/krb5/Realm.java b/src/share/classes/sun/security/krb5/Realm.java index 88f679de7a5e4bd0f07ea08eba1e6e564719164e..f7b450ec6be87b3ccfecd33e90be8f1b8da3a6e4 100644 --- a/src/share/classes/sun/security/krb5/Realm.java +++ b/src/share/classes/sun/security/krb5/Realm.java @@ -359,12 +359,12 @@ public class Realm implements Cloneable { } String tempTarget = null, tempRealm = null; - Stack iStack = new Stack (); + Stack iStack = new Stack<>(); /* * I don't expect any more than a handful of intermediaries. */ - Vector tempList = new Vector (8, 8); + Vector tempList = new Vector<>(8, 8); /* * The initiator at first location. diff --git a/src/share/classes/sun/security/krb5/internal/Authenticator.java b/src/share/classes/sun/security/krb5/internal/Authenticator.java index 28a44cc514c841791033b8a959d906fcf2edf440..67f70387a9902d0eed337d74f19ff8bd502a5c37 100644 --- a/src/share/classes/sun/security/krb5/internal/Authenticator.java +++ b/src/share/classes/sun/security/krb5/internal/Authenticator.java @@ -176,7 +176,7 @@ public class Authenticator { * @exception IOException if an I/O error occurs while reading encoded data. */ public byte[] asn1Encode() throws Asn1Exception, IOException { - Vector v = new Vector(); + Vector v = new Vector<>(); DerOutputStream temp = new DerOutputStream(); temp.putInteger(BigInteger.valueOf(authenticator_vno)); v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x00), temp.toByteArray())); diff --git a/src/share/classes/sun/security/krb5/internal/AuthorizationData.java b/src/share/classes/sun/security/krb5/internal/AuthorizationData.java index bbec348c1467bd81991a4706e20cb7bc68b33dc5..9a9de81932f30af321fb83c6c2a4153193856bcd 100644 --- a/src/share/classes/sun/security/krb5/internal/AuthorizationData.java +++ b/src/share/classes/sun/security/krb5/internal/AuthorizationData.java @@ -99,8 +99,7 @@ public class AuthorizationData implements Cloneable { * @exception IOException if an I/O error occurs while reading encoded data. */ public AuthorizationData(DerValue der) throws Asn1Exception, IOException { - Vector v = - new Vector(); + Vector v = new Vector<>(); if (der.getTag() != DerValue.tag_Sequence) { throw new Asn1Exception(Krb5.ASN1_BAD_ID); } diff --git a/src/share/classes/sun/security/krb5/internal/EncAPRepPart.java b/src/share/classes/sun/security/krb5/internal/EncAPRepPart.java index f8fb0aead5bee68a67f6dd80c340ba60762f7c6e..fdebf1de98021403b8100dfc2f5be3c6cc283fc8 100644 --- a/src/share/classes/sun/security/krb5/internal/EncAPRepPart.java +++ b/src/share/classes/sun/security/krb5/internal/EncAPRepPart.java @@ -133,7 +133,7 @@ public class EncAPRepPart { * @exception IOException if an I/O error occurs while reading encoded data. */ public byte[] asn1Encode() throws Asn1Exception, IOException { - Vector v = new Vector(); + Vector v = new Vector<>(); DerOutputStream temp = new DerOutputStream(); v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x00), ctime.asn1Encode())); diff --git a/src/share/classes/sun/security/krb5/internal/HostAddresses.java b/src/share/classes/sun/security/krb5/internal/HostAddresses.java index df51f3a3536a7845df01fdf6fd8d08d8f325af4c..1cd1e4ac44f630ffdb89224bb502348655b1ba11 100644 --- a/src/share/classes/sun/security/krb5/internal/HostAddresses.java +++ b/src/share/classes/sun/security/krb5/internal/HostAddresses.java @@ -179,7 +179,7 @@ public class HostAddresses implements Cloneable { */ public HostAddresses(DerValue encoding) throws Asn1Exception, IOException { - Vector tempAddresses = new Vector (); + Vector tempAddresses = new Vector<>(); DerValue der = null; while (encoding.getData().available() > 0) { der = encoding.getData().getDerValue(); @@ -265,8 +265,7 @@ public class HostAddresses implements Cloneable { if (addresses == null || addresses.length == 0) return null; - ArrayList ipAddrs = - new ArrayList (addresses.length); + ArrayList ipAddrs = new ArrayList<>(addresses.length); for (int i = 0; i < addresses.length; i++) { try { diff --git a/src/share/classes/sun/security/krb5/internal/KDCReq.java b/src/share/classes/sun/security/krb5/internal/KDCReq.java index 0dfd3ccf904ff06bd566bb628c2ad9d8fec5a058..16591e80404f263fa7850699d55a1f48779187c5 100644 --- a/src/share/classes/sun/security/krb5/internal/KDCReq.java +++ b/src/share/classes/sun/security/krb5/internal/KDCReq.java @@ -150,7 +150,7 @@ public class KDCReq { if (subsubDer.getTag() != DerValue.tag_SequenceOf) { throw new Asn1Exception(Krb5.ASN1_BAD_ID); } - Vector v = new Vector(); + Vector v = new Vector<>(); while (subsubDer.getData().available() > 0) { v.addElement(new PAData(subsubDer.getData().getDerValue())); } diff --git a/src/share/classes/sun/security/krb5/internal/KDCReqBody.java b/src/share/classes/sun/security/krb5/internal/KDCReqBody.java index 4af4dad0c13324932de7a22a2d542a2270055cf1..a23d452885d1c5c8144a79fbaf62880a9f2760eb 100644 --- a/src/share/classes/sun/security/krb5/internal/KDCReqBody.java +++ b/src/share/classes/sun/security/krb5/internal/KDCReqBody.java @@ -158,7 +158,7 @@ public class KDCReqBody { throw new Asn1Exception(Krb5.ASN1_BAD_ID); } der = encoding.getData().getDerValue(); - Vector v = new Vector (); + Vector v = new Vector<>(); if ((der.getTag() & (byte)0x1F) == (byte)0x08) { subDer = der.getData().getDerValue(); @@ -183,7 +183,7 @@ public class KDCReqBody { encAuthorizationData = EncryptedData.parse(encoding.getData(), (byte)0x0A, true); } if (encoding.getData().available() > 0) { - Vector tempTickets = new Vector (); + Vector tempTickets = new Vector<>(); der = encoding.getData().getDerValue(); if ((der.getTag() & (byte)0x1F) == (byte)0x0B) { subDer = der.getData().getDerValue(); @@ -216,7 +216,7 @@ public class KDCReqBody { * */ public byte[] asn1Encode(int msgType) throws Asn1Exception, IOException { - Vector v = new Vector (); + Vector v = new Vector<>(); v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x00), kdcOptions.asn1Encode())); if (msgType == Krb5.KRB_AS_REQ) { if (cname != null) { diff --git a/src/share/classes/sun/security/krb5/internal/KRBCred.java b/src/share/classes/sun/security/krb5/internal/KRBCred.java index 5fbe7ad8e03dd924f2afec08b65e6890a8c8f8fc..ff719f432c2850791a80c49324018e354748637c 100644 --- a/src/share/classes/sun/security/krb5/internal/KRBCred.java +++ b/src/share/classes/sun/security/krb5/internal/KRBCred.java @@ -134,7 +134,7 @@ public class KRBCred { if (subsubDer.getTag() != DerValue.tag_SequenceOf) { throw new Asn1Exception(Krb5.ASN1_BAD_ID); } - Vector v = new Vector(); + Vector v = new Vector<>(); while (subsubDer.getData().available() > 0) { v.addElement(new Ticket(subsubDer.getData().getDerValue())); } diff --git a/src/share/classes/sun/security/krb5/internal/KRBError.java b/src/share/classes/sun/security/krb5/internal/KRBError.java index ac8667f0686b3f48ae168de65e499e5e0887caff..ed17cd8212a0bad42c6ad457bd318b506e6559eb 100644 --- a/src/share/classes/sun/security/krb5/internal/KRBError.java +++ b/src/share/classes/sun/security/krb5/internal/KRBError.java @@ -260,7 +260,7 @@ public class KRBError implements java.io.Serializable { private void parsePAData(byte[] data) throws IOException, Asn1Exception { DerValue derPA = new DerValue(data); - List paList = new ArrayList(); + List paList = new ArrayList<>(); while (derPA.data.available() > 0) { // read the PA-DATA DerValue tmp = derPA.data.getDerValue(); diff --git a/src/share/classes/sun/security/krb5/internal/KrbCredInfo.java b/src/share/classes/sun/security/krb5/internal/KrbCredInfo.java index 7c2fbff849ddcd2d802fdebc91ea4020727b6692..63ebe03d3c64eff157a8803e839eb0b029091b36 100644 --- a/src/share/classes/sun/security/krb5/internal/KrbCredInfo.java +++ b/src/share/classes/sun/security/krb5/internal/KrbCredInfo.java @@ -157,7 +157,7 @@ public class KrbCredInfo { * @exception IOException if an I/O error occurs while reading encoded data. */ public byte[] asn1Encode() throws Asn1Exception, IOException { - Vector v = new Vector (); + Vector v = new Vector<>(); v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x00), key.asn1Encode())); if (prealm != null) v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x01), prealm.asn1Encode())); diff --git a/src/share/classes/sun/security/krb5/internal/LastReq.java b/src/share/classes/sun/security/krb5/internal/LastReq.java index 578d955f45bc874de43136c1544967cbd52e1970..45ff8a81274cb0dc9471f11ed0467910edc98bf7 100644 --- a/src/share/classes/sun/security/krb5/internal/LastReq.java +++ b/src/share/classes/sun/security/krb5/internal/LastReq.java @@ -77,7 +77,7 @@ public class LastReq { */ public LastReq(DerValue encoding) throws Asn1Exception, IOException { - Vector v= new Vector (); + Vector v= new Vector<>(); if (encoding.getTag() != DerValue.tag_Sequence) { throw new Asn1Exception(Krb5.ASN1_BAD_ID); } diff --git a/src/share/classes/sun/security/krb5/internal/ccache/FileCredentialsCache.java b/src/share/classes/sun/security/krb5/internal/ccache/FileCredentialsCache.java index 4f874903f79596516101b8cbf7331cd7c18664bf..46e5985f76f67cd2a56cbe9bda1c44680ba5d4ba 100644 --- a/src/share/classes/sun/security/krb5/internal/ccache/FileCredentialsCache.java +++ b/src/share/classes/sun/security/krb5/internal/ccache/FileCredentialsCache.java @@ -490,7 +490,7 @@ public class FileCredentialsCache extends CredentialsCache private static String exec(String c) { StringTokenizer st = new StringTokenizer(c); - Vector v = new Vector (); + Vector v = new Vector<>(); while (st.hasMoreTokens()) { v.addElement(st.nextToken()); } diff --git a/src/share/classes/sun/security/krb5/internal/crypto/EType.java b/src/share/classes/sun/security/krb5/internal/crypto/EType.java index 90c0be67dae3be1d071b8a61635a5567ec2ff36b..85ba264944def5a6a2b3d98c6f33a90c4df9f1fc 100644 --- a/src/share/classes/sun/security/krb5/internal/crypto/EType.java +++ b/src/share/classes/sun/security/krb5/internal/crypto/EType.java @@ -257,7 +257,7 @@ public abstract class EType { + configName); } - List list = new ArrayList (answer.length); + List list = new ArrayList<>(answer.length); for (int i = 0; i < answer.length; i++) { if (EncryptionKey.findKey(answer[i], keys) != null) { list.add(answer[i]); diff --git a/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java b/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java index e0624e4db03d46389c0c202cfcb1c688eb56306c..3c680fde16606bff898c25628de7be1b66327a8c 100644 --- a/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java +++ b/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java @@ -57,7 +57,7 @@ public class KeyTab implements KeyTabConstants { private static KeyTab singleton = null; private static final boolean DEBUG = Krb5.DEBUG; private static String name; - private Vector entries = new Vector (); + private Vector entries = new Vector<>(); private KeyTab(String filename) throws IOException, RealmException { init(filename); @@ -240,7 +240,7 @@ public class KeyTab implements KeyTabConstants { KeyTabEntry entry; EncryptionKey key; int size = entries.size(); - ArrayList keys = new ArrayList (size); + ArrayList keys = new ArrayList<>(size); for (int i = size-1; i >= 0; i--) { entry = entries.elementAt(i); diff --git a/src/share/classes/sun/security/provider/PolicyFile.java b/src/share/classes/sun/security/provider/PolicyFile.java index 739c375796f5cbb8b67c6b1f0027501959d82c4d..7112a7f60c53f3200ac6776523bfacfab77d178a 100644 --- a/src/share/classes/sun/security/provider/PolicyFile.java +++ b/src/share/classes/sun/security/provider/PolicyFile.java @@ -299,8 +299,7 @@ public class PolicyFile extends java.security.Policy { private static final int DEFAULT_CACHE_SIZE = 1; // contains the policy grant entries, PD cache, and alias mapping - private AtomicReference policyInfo = - new AtomicReference(); + private AtomicReference policyInfo = new AtomicReference<>(); private boolean constructed = false; private boolean expandProperties = true; @@ -1334,8 +1333,7 @@ public class PolicyFile extends java.security.Policy { List entryPs = entry.getPrincipals(); if (debug != null) { - ArrayList accPs = - new ArrayList(); + ArrayList accPs = new ArrayList<>(); if (principals != null) { for (int i = 0; i < principals.length; i++) { accPs.add(new PolicyParser.PrincipalEntry @@ -1416,8 +1414,7 @@ public class PolicyFile extends java.security.Policy { // check if the PrincipalComparator // implies the current thread's principals - Set pSet = - new HashSet(principals.length); + Set pSet = new HashSet<>(principals.length); for (int j = 0; j < principals.length; j++) { pSet.add(principals[j]); } @@ -1700,7 +1697,7 @@ public class PolicyFile extends java.security.Policy { // build an info array for every principal // in the current domain which has a principal class // that is equal to policy entry principal class name - List plist = new ArrayList(); + List plist = new ArrayList<>(); for (int i = 0; i < pdp.length; i++) { if(pe.principalClass.equals(pdp[i].getClass().getName())) plist.add(pdp[i]); @@ -1770,7 +1767,7 @@ public class PolicyFile extends java.security.Policy { // Done return certs; - ArrayList userCertList = new ArrayList(); + ArrayList userCertList = new ArrayList<>(); i = 0; while (i < certs.length) { userCertList.add(certs[i]); @@ -2234,7 +2231,7 @@ public class PolicyFile extends java.security.Policy { if (this.certs == null) { // extract the signer certs ArrayList signerCerts = - new ArrayList(); + new ArrayList<>(); i = 0; while (i < certs.length) { signerCerts.add(certs[i]); diff --git a/src/share/classes/sun/security/provider/Sun.java b/src/share/classes/sun/security/provider/Sun.java index e2fed0363a2609ad17f0e0f2e93ee96a6d3069ad..078bef6cdf1cce7f2c9e874ae674f3ab2a5cee04 100644 --- a/src/share/classes/sun/security/provider/Sun.java +++ b/src/share/classes/sun/security/provider/Sun.java @@ -55,7 +55,7 @@ public final class Sun extends Provider { SunEntries.putEntries(this); } else { // use LinkedHashMap to preserve the order of the PRNGs - Map map = new LinkedHashMap(); + Map map = new LinkedHashMap<>(); SunEntries.putEntries(map); AccessController.doPrivileged(new PutAllAction(this, map)); } diff --git a/src/share/classes/sun/security/provider/VerificationProvider.java b/src/share/classes/sun/security/provider/VerificationProvider.java index 18af2e88f6f5878af532dae54968aed6b50f6e75..86801228abee8d83f12ec0f6820773c0304e89ba 100644 --- a/src/share/classes/sun/security/provider/VerificationProvider.java +++ b/src/share/classes/sun/security/provider/VerificationProvider.java @@ -76,7 +76,7 @@ public final class VerificationProvider extends Provider { SunRsaSignEntries.putEntries(this); } else { // use LinkedHashMap to preserve the order of the PRNGs - Map map = new LinkedHashMap(); + Map map = new LinkedHashMap<>(); SunEntries.putEntries(map); SunRsaSignEntries.putEntries(map); AccessController.doPrivileged(new PutAllAction(this, map)); diff --git a/src/share/classes/sun/security/provider/X509Factory.java b/src/share/classes/sun/security/provider/X509Factory.java index e785b655a2ebe75412abe6ac7b599f3960122b95..8ec0cbe594199e4bc602332a4bb40f115b5ded61 100644 --- a/src/share/classes/sun/security/provider/X509Factory.java +++ b/src/share/classes/sun/security/provider/X509Factory.java @@ -409,10 +409,10 @@ public class X509Factory extends CertificateFactorySpi { parseX509orPKCS7Cert(InputStream is) throws CertificateException, IOException { - Collection coll = new ArrayList(); + Collection coll = new ArrayList<>(); byte[] data = readOneBlock(is); if (data == null) { - return new ArrayList(0); + return new ArrayList<>(0); } try { PKCS7 pkcs7 = new PKCS7(data); @@ -422,7 +422,7 @@ public class X509Factory extends CertificateFactorySpi { return Arrays.asList(certs); } else { // no crls provided - return new ArrayList(0); + return new ArrayList<>(0); } } catch (ParsingException e) { while (data != null) { @@ -442,10 +442,10 @@ public class X509Factory extends CertificateFactorySpi { parseX509orPKCS7CRL(InputStream is) throws CRLException, IOException { - Collection coll = new ArrayList(); + Collection coll = new ArrayList<>(); byte[] data = readOneBlock(is); if (data == null) { - return new ArrayList(0); + return new ArrayList<>(0); } try { PKCS7 pkcs7 = new PKCS7(data); @@ -455,7 +455,7 @@ public class X509Factory extends CertificateFactorySpi { return Arrays.asList(crls); } else { // no crls provided - return new ArrayList(0); + return new ArrayList<>(0); } } catch (ParsingException e) { while (data != null) { diff --git a/src/share/classes/sun/security/rsa/RSACore.java b/src/share/classes/sun/security/rsa/RSACore.java index 4b3ec9afa284f27127e39e4fc41a10705ed56123..42ebc3c1a48cb63aec2c847667b08141b9e9c91c 100644 --- a/src/share/classes/sun/security/rsa/RSACore.java +++ b/src/share/classes/sun/security/rsa/RSACore.java @@ -215,11 +215,11 @@ public final class RSACore { // value suggested by Paul Kocher (quoted by NSS) private final static int BLINDING_MAX_REUSE = 50; - // cache for blinding parameters. Map + // cache for blinding parameters. Map // use a weak hashmap so that cached values are automatically cleared // when the modulus is GC'ed - private final static Map blindingCache = - new WeakHashMap(); + private final static Map blindingCache = + new WeakHashMap<>(); /** * Set of blinding parameters for a given RSA key. diff --git a/src/share/classes/sun/security/rsa/SunRsaSign.java b/src/share/classes/sun/security/rsa/SunRsaSign.java index 20e56311eb817c0284f2f729c74cee38c6e921ec..b48882c2824a6bf795f6d8e438ff1e2e74887bd8 100644 --- a/src/share/classes/sun/security/rsa/SunRsaSign.java +++ b/src/share/classes/sun/security/rsa/SunRsaSign.java @@ -52,7 +52,7 @@ public final class SunRsaSign extends Provider { SunRsaSignEntries.putEntries(this); } else { // use LinkedHashMap to preserve the order of the PRNGs - Map map = new HashMap(); + Map map = new HashMap<>(); SunRsaSignEntries.putEntries(map); AccessController.doPrivileged(new PutAllAction(this, map)); } diff --git a/src/share/classes/sun/security/ssl/CipherSuite.java b/src/share/classes/sun/security/ssl/CipherSuite.java index 06351cec6946e8a5201154ac0812b29f0d1f7126..08146df7621fe73ec68a44ce1080c49417e073b9 100644 --- a/src/share/classes/sun/security/ssl/CipherSuite.java +++ b/src/share/classes/sun/security/ssl/CipherSuite.java @@ -393,7 +393,7 @@ final class CipherSuite implements Comparable { // Map BulkCipher -> Boolean(available) private final static Map availableCache = - new HashMap(8); + new HashMap<>(8); // descriptive name including key size, e.g. AES/128 final String description; diff --git a/src/share/classes/sun/security/ssl/CipherSuiteList.java b/src/share/classes/sun/security/ssl/CipherSuiteList.java index 93bfb15a02feede4d0da166e95cdd1ab430eb8ad..43750203b36aa8af214467dc327c7352ad387bde 100644 --- a/src/share/classes/sun/security/ssl/CipherSuiteList.java +++ b/src/share/classes/sun/security/ssl/CipherSuiteList.java @@ -221,7 +221,7 @@ final class CipherSuiteList { private static CipherSuiteList buildAvailableCache(int minPriority) { // SortedSet automatically arranges ciphersuites in default // preference order - Set cipherSuites = new TreeSet(); + Set cipherSuites = new TreeSet<>(); Collection allowedCipherSuites = CipherSuite.allowedCipherSuites(); for (CipherSuite c : allowedCipherSuites) { diff --git a/src/share/classes/sun/security/ssl/ClientHandshaker.java b/src/share/classes/sun/security/ssl/ClientHandshaker.java index 81cdfd1e5b86172dbf3b90ad6887a6a2bf4e6150..3920b35c37a5c943277985c51fb98002ebb13549 100644 --- a/src/share/classes/sun/security/ssl/ClientHandshaker.java +++ b/src/share/classes/sun/security/ssl/ClientHandshaker.java @@ -655,7 +655,7 @@ final class ClientHandshaker extends Handshaker { if (certRequest != null) { X509ExtendedKeyManager km = sslContext.getX509KeyManager(); - ArrayList keytypesTmp = new ArrayList(4); + ArrayList keytypesTmp = new ArrayList<>(4); for (int i = 0; i < certRequest.types.length; i++) { String typeName; @@ -1174,8 +1174,7 @@ final class ClientHandshaker extends Handshaker { "Can't reuse existing SSL client session"); } - Collection cipherList = - new ArrayList(2); + Collection cipherList = new ArrayList<>(2); cipherList.add(sessionSuite); if (!secureRenegotiation && cipherSuites.contains(CipherSuite.C_SCSV)) { @@ -1193,7 +1192,7 @@ final class ClientHandshaker extends Handshaker { // exclude SCSV for secure renegotiation if (secureRenegotiation && cipherSuites.contains(CipherSuite.C_SCSV)) { Collection cipherList = - new ArrayList(cipherSuites.size() - 1); + new ArrayList<>(cipherSuites.size() - 1); for (CipherSuite suite : cipherSuites.collection()) { if (suite != CipherSuite.C_SCSV) { cipherList.add(suite); diff --git a/src/share/classes/sun/security/ssl/DefaultSSLContextImpl.java b/src/share/classes/sun/security/ssl/DefaultSSLContextImpl.java index 5ec2cb834c3a6153acc8decca4c5662c4d02b571..f4c6e160200452b6cf999ee1d2f93b53b80857ce 100644 --- a/src/share/classes/sun/security/ssl/DefaultSSLContextImpl.java +++ b/src/share/classes/sun/security/ssl/DefaultSSLContextImpl.java @@ -98,7 +98,7 @@ public final class DefaultSSLContextImpl extends SSLContextImpl { return defaultKeyManagers; } - final Map props = new HashMap(); + final Map props = new HashMap<>(); AccessController.doPrivileged( new PrivilegedExceptionAction() { public Object run() throws Exception { diff --git a/src/share/classes/sun/security/ssl/HandshakeMessage.java b/src/share/classes/sun/security/ssl/HandshakeMessage.java index c10aa17a44203a429232cbcd37763e846e83006a..f5f84c1ef9db15eb961c0463ddfb768ea73e9423 100644 --- a/src/share/classes/sun/security/ssl/HandshakeMessage.java +++ b/src/share/classes/sun/security/ssl/HandshakeMessage.java @@ -258,7 +258,7 @@ static final class ClientHello extends HandshakeMessage { // add server_name extension void addServerNameIndicationExtension(String hostname) { // We would have checked that the hostname ia a FQDN. - ArrayList hostnames = new ArrayList(1); + ArrayList hostnames = new ArrayList<>(1); hostnames.add(hostname); try { @@ -434,7 +434,7 @@ class CertificateMsg extends HandshakeMessage CertificateMsg(HandshakeInStream input) throws IOException { int chainLen = input.getInt24(); - List v = new ArrayList(4); + List v = new ArrayList<>(4); CertificateFactory cf = null; while (chainLen > 0) { @@ -1328,7 +1328,7 @@ class CertificateRequest extends HandshakeMessage // read the certificate_authorities int len = input.getInt16(); - ArrayList v = new ArrayList(); + ArrayList v = new ArrayList<>(); while (len >= 3) { DistinguishedName dn = new DistinguishedName(input); v.add(dn); @@ -1719,7 +1719,7 @@ static final class CertificateVerify extends HandshakeMessage { // Note that this will prevent the Spi classes from being GC'd. We assume // that is not a problem. private final static Map methodCache = - new ConcurrentHashMap(); + new ConcurrentHashMap<>(); private static void digestKey(MessageDigest md, SecretKey key) { try { diff --git a/src/share/classes/sun/security/ssl/Handshaker.java b/src/share/classes/sun/security/ssl/Handshaker.java index fb090b739c8827c128f22beed40af16426ebd1f0..050355cf7b8e71e4843abbc7e481fc0504005184 100644 --- a/src/share/classes/sun/security/ssl/Handshaker.java +++ b/src/share/classes/sun/security/ssl/Handshaker.java @@ -569,7 +569,7 @@ abstract class Handshaker { activeProtocols = getActiveProtocols(); } - ArrayList suites = new ArrayList(); + ArrayList suites = new ArrayList<>(); if (!(activeProtocols.collection().isEmpty()) && activeProtocols.min.v != ProtocolVersion.NONE.v) { for (CipherSuite suite : enabledCipherSuites.collection()) { @@ -614,8 +614,7 @@ abstract class Handshaker { */ ProtocolList getActiveProtocols() { if (activeProtocols == null) { - ArrayList protocols = - new ArrayList(4); + ArrayList protocols = new ArrayList<>(4); for (ProtocolVersion protocol : enabledProtocols.collection()) { boolean found = false; for (CipherSuite suite : enabledCipherSuites.collection()) { diff --git a/src/share/classes/sun/security/ssl/HelloExtensions.java b/src/share/classes/sun/security/ssl/HelloExtensions.java index 94858b0ef0a17949d2743653fbb1c8d19241566c..cbd320188c27ea211c444c095dd05787a4c4f8b1 100644 --- a/src/share/classes/sun/security/ssl/HelloExtensions.java +++ b/src/share/classes/sun/security/ssl/HelloExtensions.java @@ -169,8 +169,7 @@ final class ExtensionType { return name; } - static List knownExtensions = - new ArrayList(9); + static List knownExtensions = new ArrayList<>(9); static ExtensionType get(int id) { for (ExtensionType ext : knownExtensions) { @@ -674,7 +673,7 @@ final class SupportedEllipticPointFormatsExtension extends HelloExtension { } public String toString() { - List list = new ArrayList(); + List list = new ArrayList<>(); for (byte format : formats) { list.add(toString(format)); } diff --git a/src/share/classes/sun/security/ssl/ProtocolList.java b/src/share/classes/sun/security/ssl/ProtocolList.java index 0b3a71b21603468bc757a6ae3e0602d0e87a3272..6f41e4efa3daed3dd921ac80f5ffb05aec91cb47 100644 --- a/src/share/classes/sun/security/ssl/ProtocolList.java +++ b/src/share/classes/sun/security/ssl/ProtocolList.java @@ -83,7 +83,7 @@ final class ProtocolList { throw new IllegalArgumentException("Protocols may not be null"); } - ArrayList versions = new ArrayList(3); + ArrayList versions = new ArrayList<>(3); for (int i = 0; i < names.length; i++ ) { ProtocolVersion version = ProtocolVersion.valueOf(names[i]); if (versions.contains(version) == false) { diff --git a/src/share/classes/sun/security/ssl/SSLAlgorithmConstraints.java b/src/share/classes/sun/security/ssl/SSLAlgorithmConstraints.java index 07bf58379b022632d9aa5cd641196b8becd85c30..8914cf6aa17d013fb486fc7e95379ab4461f61c9 100644 --- a/src/share/classes/sun/security/ssl/SSLAlgorithmConstraints.java +++ b/src/share/classes/sun/security/ssl/SSLAlgorithmConstraints.java @@ -261,7 +261,7 @@ final class SSLAlgorithmConstraints implements AlgorithmConstraints { protected Set decomposes(KeyExchange keyExchange, boolean forCertPathOnly) { - Set components = new HashSet(); + Set components = new HashSet<>(); switch (keyExchange) { case K_NULL: if (!forCertPathOnly) { @@ -356,7 +356,7 @@ final class SSLAlgorithmConstraints implements AlgorithmConstraints { } protected Set decomposes(BulkCipher bulkCipher) { - Set components = new HashSet(); + Set components = new HashSet<>(); if (bulkCipher.transformation != null) { components.addAll(super.decomposes(bulkCipher.transformation)); @@ -366,7 +366,7 @@ final class SSLAlgorithmConstraints implements AlgorithmConstraints { } protected Set decomposes(MacAlg macAlg) { - Set components = new HashSet(); + Set components = new HashSet<>(); if (macAlg == CipherSuite.M_MD5) { components.add("MD5"); @@ -407,7 +407,7 @@ final class SSLAlgorithmConstraints implements AlgorithmConstraints { } if (cipherSuite != null) { - Set components = new HashSet(); + Set components = new HashSet<>(); if(cipherSuite.keyExchange != null) { components.addAll( @@ -448,7 +448,7 @@ final class SSLAlgorithmConstraints implements AlgorithmConstraints { } if (cipherSuite != null) { - Set components = new HashSet(); + Set components = new HashSet<>(); if(cipherSuite.keyExchange != null) { components.addAll( diff --git a/src/share/classes/sun/security/ssl/SSLSessionImpl.java b/src/share/classes/sun/security/ssl/SSLSessionImpl.java index 05288538e6c2d03a8bb8d7b2942878b13c27fbb3..f68b14be9c2b543dedc1f3b1cc9c5ef38a1ce542 100644 --- a/src/share/classes/sun/security/ssl/SSLSessionImpl.java +++ b/src/share/classes/sun/security/ssl/SSLSessionImpl.java @@ -618,8 +618,7 @@ final class SSLSessionImpl extends ExtendedSSLSession { * key and the calling security context. This is important since * sessions can be shared across different protection domains. */ - private Hashtable table = - new Hashtable(); + private Hashtable table = new Hashtable<>(); /** * Assigns a session value. Session change events are given if @@ -687,7 +686,7 @@ final class SSLSessionImpl extends ExtendedSSLSession { */ public String[] getValueNames() { Enumeration e; - Vector v = new Vector(); + Vector v = new Vector<>(); SecureKey key; Object securityCtx = SecureKey.getCurrentSecurityContext(); diff --git a/src/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java b/src/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java index 4e968c3e3914e9f88fbb65790da8648417e44b58..4b1dee8f68229bfd086c38a57ffb0de591e245fb 100644 --- a/src/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java +++ b/src/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java @@ -153,8 +153,7 @@ final class SignatureAndHashAlgorithm { static Collection getSupportedAlgorithms(AlgorithmConstraints constraints) { - Collection supported = - new ArrayList(); + Collection supported = new ArrayList<>(); synchronized (priorityMap) { for (SignatureAndHashAlgorithm sigAlg : priorityMap.values()) { if (sigAlg.priority <= SUPPORTED_ALG_PRIORITY_MAX_NUM && @@ -171,8 +170,7 @@ final class SignatureAndHashAlgorithm { // Get supported algorithm collection from an untrusted collection static Collection getSupportedAlgorithms( Collection algorithms ) { - Collection supported = - new ArrayList(); + Collection supported = new ArrayList<>(); for (SignatureAndHashAlgorithm sigAlg : algorithms) { if (sigAlg.priority <= SUPPORTED_ALG_PRIORITY_MAX_NUM) { supported.add(sigAlg); @@ -184,7 +182,7 @@ final class SignatureAndHashAlgorithm { static String[] getAlgorithmNames( Collection algorithms) { - ArrayList algorithmNames = new ArrayList(); + ArrayList algorithmNames = new ArrayList<>(); if (algorithms != null) { for (SignatureAndHashAlgorithm sigAlg : algorithms) { algorithmNames.add(sigAlg.algorithm); @@ -197,7 +195,7 @@ final class SignatureAndHashAlgorithm { static Set getHashAlgorithmNames( Collection algorithms) { - Set algorithmNames = new HashSet(); + Set algorithmNames = new HashSet<>(); if (algorithms != null) { for (SignatureAndHashAlgorithm sigAlg : algorithms) { if (sigAlg.hash.value > 0) { diff --git a/src/share/classes/sun/security/ssl/SunX509KeyManagerImpl.java b/src/share/classes/sun/security/ssl/SunX509KeyManagerImpl.java index 0b0e6b5f0b00651e739233b7cad65188e2edec4f..5c2d09c4db53fcca012b69fe3183f319c18715e0 100644 --- a/src/share/classes/sun/security/ssl/SunX509KeyManagerImpl.java +++ b/src/share/classes/sun/security/ssl/SunX509KeyManagerImpl.java @@ -337,7 +337,7 @@ final class SunX509KeyManagerImpl extends X509ExtendedKeyManager { X500Principal[] x500Issuers = (X500Principal[])issuers; // the algorithm below does not produce duplicates, so avoid Set - List aliases = new ArrayList(); + List aliases = new ArrayList<>(); for (Map.Entry entry : credentialsMap.entrySet()) { @@ -397,7 +397,7 @@ final class SunX509KeyManagerImpl extends X509ExtendedKeyManager { * possible. Principals that cannot be converted are ignored. */ private static X500Principal[] convertPrincipals(Principal[] principals) { - List list = new ArrayList(principals.length); + List list = new ArrayList<>(principals.length); for (int i = 0; i < principals.length; i++) { Principal p = principals[i]; if (p instanceof X500Principal) { diff --git a/src/share/classes/sun/security/ssl/TrustManagerFactoryImpl.java b/src/share/classes/sun/security/ssl/TrustManagerFactoryImpl.java index 0fae6ce4a0165dfb51f17763ace31f5d523a1a46..3e758f64c253d430119f2f2ef4fcd393971a5135 100644 --- a/src/share/classes/sun/security/ssl/TrustManagerFactoryImpl.java +++ b/src/share/classes/sun/security/ssl/TrustManagerFactoryImpl.java @@ -134,7 +134,7 @@ abstract class TrustManagerFactoryImpl extends TrustManagerFactorySpi { FileInputStream fis = null; String defaultTrustStoreType; String defaultTrustStoreProvider; - final HashMap props = new HashMap(); + final HashMap props = new HashMap<>(); final String sep = File.separator; KeyStore ks = null; diff --git a/src/share/classes/sun/security/ssl/X509KeyManagerImpl.java b/src/share/classes/sun/security/ssl/X509KeyManagerImpl.java index d563d2d37de0504ec3f1b4fea98758313f55f13e..0d3731f2ba4ecbb2668d8477e98095788455a642 100644 --- a/src/share/classes/sun/security/ssl/X509KeyManagerImpl.java +++ b/src/share/classes/sun/security/ssl/X509KeyManagerImpl.java @@ -307,7 +307,7 @@ final class X509KeyManagerImpl extends X509ExtendedKeyManager (keyTypes.length == 0) || (keyTypes[0] == null)) { return null; } - List list = new ArrayList(keyTypes.length); + List list = new ArrayList<>(keyTypes.length); for (String keyType : keyTypes) { list.add(new KeyType(keyType)); } @@ -429,7 +429,7 @@ final class X509KeyManagerImpl extends X509ExtendedKeyManager // make a Set out of the array private Set getIssuerSet(Principal[] issuers) { if ((issuers != null) && (issuers.length != 0)) { - return new HashSet(Arrays.asList(issuers)); + return new HashSet<>(Arrays.asList(issuers)); } else { return null; } diff --git a/src/share/classes/sun/security/tools/JarSigner.java b/src/share/classes/sun/security/tools/JarSigner.java index 03809d37812182380d614733938569d2c8a36b52..42d3bf57fd8d04b63e19affa053fcb4b2f527d81 100644 --- a/src/share/classes/sun/security/tools/JarSigner.java +++ b/src/share/classes/sun/security/tools/JarSigner.java @@ -123,19 +123,19 @@ public class JarSigner { // or the default keystore, never null String keystore; // key store file - List crlfiles = new ArrayList(); // CRL files to add + List crlfiles = new ArrayList<>(); // CRL files to add boolean nullStream = false; // null keystore input stream (NONE) boolean token = false; // token-based keystore String jarfile; // jar files to sign or verify String alias; // alias to sign jar with - List ckaliases = new ArrayList(); // aliases in -verify + List ckaliases = new ArrayList<>(); // aliases in -verify char[] storepass; // keystore password boolean protectedPath; // protected authentication path String storetype; // keystore type String providerName; // provider name Vector providers = null; // list of providers // arguments for provider constructors - HashMap providerArgs = new HashMap(); + HashMap providerArgs = new HashMap<>(); char[] keypass; // private key password String sigfile; // name of .SF file String sigalg; // name of signature algorithm @@ -236,7 +236,7 @@ public class JarSigner { if (crlfiles.size() > 0 || autoCRL) { CertificateFactory fac = CertificateFactory.getInstance("X509"); - List list = new ArrayList(); + List list = new ArrayList<>(); for (String file: crlfiles) { Collection tmp = KeyTool.loadCRLs(file); for (CRL crl: tmp) { @@ -606,7 +606,7 @@ public class JarSigner { try { jf = new JarFile(jarName, true); - Vector entriesVec = new Vector(); + Vector entriesVec = new Vector<>(); byte[] buffer = new byte[8192]; Enumeration entries = jf.entries(); @@ -633,8 +633,7 @@ public class JarSigner { // The map to record display info, only used when -verbose provided // key: signer info string // value: the list of files with common key - Map> output = - new LinkedHashMap>(); + Map> output = new LinkedHashMap<>(); if (man != null) { if (verbose != null) System.out.println(); @@ -1000,8 +999,7 @@ public class JarSigner { .append(signTimeForm.format(source)).append("]").toString(); } - private Map cacheForInKS = - new IdentityHashMap(); + private Map cacheForInKS = new IdentityHashMap<>(); private int inKeyStoreForOneSigner(CodeSigner signer) { if (cacheForInKS.containsKey(signer)) { @@ -1044,8 +1042,7 @@ public class JarSigner { return result; } - Hashtable storeHash = - new Hashtable(); + Hashtable storeHash = new Hashtable<>(); int inKeyStore(CodeSigner[] signers) { @@ -1175,7 +1172,7 @@ public class JarSigner { * generated one. (This may invalidate existing signatures!) */ BASE64Encoder encoder = new JarBASE64Encoder(); - Vector mfFiles = new Vector(); + Vector mfFiles = new Vector<>(); boolean wasSigned = false; @@ -1531,7 +1528,7 @@ public class JarSigner { return false; } - Map cacheForSignerInfo = new IdentityHashMap(); + Map cacheForSignerInfo = new IdentityHashMap<>(); /** * Returns a string of singer info, with a newline at the end @@ -1655,7 +1652,7 @@ public class JarSigner { } } } - Set tas = new HashSet(); + Set tas = new HashSet<>(); try { KeyStore caks = KeyTool.getCacertsKeyStore(); if (caks != null) { diff --git a/src/share/classes/sun/security/tools/KeyTool.java b/src/share/classes/sun/security/tools/KeyTool.java index 5ce08316f357c22cf16ee6d26a07bb96054151f2..897d407a1c2039bc26e4540282cb864839aa74e5 100644 --- a/src/share/classes/sun/security/tools/KeyTool.java +++ b/src/share/classes/sun/security/tools/KeyTool.java @@ -153,11 +153,11 @@ public final class KeyTool { private KeyStore caks = null; // "cacerts" keystore private char[] srcstorePass = null; private String srcstoretype = null; - private Set passwords = new HashSet (); + private Set passwords = new HashSet<>(); private String startDate = null; - private List ids = new ArrayList (); // used in GENCRL - private List v3ext = new ArrayList (); + private List ids = new ArrayList<>(); // used in GENCRL + private List v3ext = new ArrayList<>(); enum Command { CERTREQ("Generates.a.certificate.request", @@ -2091,7 +2091,7 @@ public final class KeyTool { */ public static List readCRLsFromCert(X509Certificate cert) throws Exception { - List crls = new ArrayList(); + List crls = new ArrayList<>(); CRLDistributionPointsExtension ext = X509CertImpl.toImpl(cert).getCRLDistributionPointsExtension(); if (ext == null) return crls; @@ -2258,7 +2258,7 @@ public final class KeyTool { if (jarfile != null) { JarFile jf = new JarFile(jarfile, true); Enumeration entries = jf.entries(); - Set ss = new HashSet(); + Set ss = new HashSet<>(); byte[] buffer = new byte[8192]; int pos = 0; while (entries.hasMoreElements()) { @@ -3347,7 +3347,7 @@ public final class KeyTool { } // start building chain - Vector chain = new Vector(2); + Vector chain = new Vector<>(2); if (buildChain((X509Certificate)certToVerify, chain, certs)) { Certificate[] newChain = new Certificate[chain.size()]; // buildChain() returns chain with self-signed root-cert first and @@ -3873,8 +3873,7 @@ public final class KeyTool { break; case 2: // EKU if(value != null) { - Vector v = - new Vector (); + Vector v = new Vector<>(); for (String s: value.split(",")) { int p = oneOf(s, "anyExtendedKeyUsage", @@ -3944,7 +3943,7 @@ public final class KeyTool { } if(value != null) { List accessDescriptions = - new ArrayList(); + new ArrayList<>(); String[] ps = value.split(","); for(String item: ps) { colonpos = item.indexOf(':'); @@ -4228,7 +4227,7 @@ class Pair { } public static Pair of(A a, B b) { - return new Pair(a,b); + return new Pair<>(a,b); } } diff --git a/src/share/classes/sun/security/tools/policytool/PolicyTool.java b/src/share/classes/sun/security/tools/policytool/PolicyTool.java index f310504a2047b1dbc2ad6a80fe32bf9cd182197b..cc40a08e5946bfe3bb04266dbad1e89f469da035 100644 --- a/src/share/classes/sun/security/tools/policytool/PolicyTool.java +++ b/src/share/classes/sun/security/tools/policytool/PolicyTool.java @@ -643,7 +643,7 @@ public class PolicyTool { Class pc = Class.forName(type, true, Thread.currentThread().getContextClassLoader()); Constructor c = null; - Vector objects = new Vector(2); + Vector objects = new Vector<>(2); if (name != null) objects.add(name); if (actions != null) objects.add(actions); switch (objects.size()) { @@ -1722,8 +1722,7 @@ class ToolDialog extends Dialog { new PolicyParser.GrantEntry(signedby, codebase); // get the new Principals - LinkedList prins = - new LinkedList(); + LinkedList prins = new LinkedList<>(); TaggedList prinList = (TaggedList)getComponent(PE_PRIN_LIST); for (int i = 0; i < prinList.getItemCount(); i++) { prins.add((PolicyParser.PrincipalEntry)prinList.getObject(i)); @@ -1731,8 +1730,7 @@ class ToolDialog extends Dialog { ge.principals = prins; // get the new Permissions - Vector perms = - new Vector(); + Vector perms = new Vector<>(); TaggedList permList = (TaggedList)getComponent(PE_PERM_LIST); for (int i = 0; i < permList.getItemCount(); i++) { perms.addElement((PolicyParser.PermissionEntry)permList.getObject(i)); @@ -3649,7 +3647,7 @@ class NoDisplayException extends RuntimeException { * This is a java.awt.List that bind an Object to each String it holds. */ class TaggedList extends List { - private java.util.List data = new LinkedList(); + private java.util.List data = new LinkedList<>(); public TaggedList(int i, boolean b) { super(i, b); } diff --git a/src/share/demo/jvmti/index.html b/src/share/demo/jvmti/index.html index b3efe373d4569d57a09e5dad5f971657a600c147..6ef96bb64b827f5576007038e3d6833b676899c3 100644 --- a/src/share/demo/jvmti/index.html +++ b/src/share/demo/jvmti/index.html @@ -389,10 +389,9 @@ Library: Use /opt:REF when building the dll.
  • MS DLL Runtime: Use the /MD /D _STATIC_CPPLIB option.
    -This causes your dll to become dependent on MSVCRT.DLL and/or -the newer C++ runtime MSVCR71.DLL. +This causes your dll to become dependent on just MSVCR*.DLL. The option /D _STATIC_CPPLIB prevents you from becoming dependent on the -C++ library MSVCP71.DLL. +C++ library MSVCP*.DLL. This is what we use in the JDK, but there are probably many combinations that you could safely use, unfortunately there are many combinations of runtimes that will not work. diff --git a/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java b/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java index 21094011c01be0c31af45821ee912b9a0a425610..1cd59db8bc12440211c0683259754f66c2cd7bd0 100644 --- a/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java +++ b/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java @@ -78,7 +78,6 @@ public class ZipFileSystem extends FileSystem { // configurable by env map private final String defaultDir; // default dir for the file system private final String nameEncoding; // default encoding for name/comment - private final boolean buildDirTree; // build a dir tree for directoryStream ops private final boolean useTempFile; // use a temp file for newOS, default // is to use BAOS for better performance private final boolean createNew; // create a new zip if not exists @@ -94,7 +93,6 @@ public class ZipFileSystem extends FileSystem { this.createNew = "true".equals(env.get("create")); this.nameEncoding = env.containsKey("encoding") ? (String)env.get("encoding") : "UTF-8"; - this.buildDirTree = TRUE.equals(env.get("buildDirTreea")); this.useTempFile = TRUE.equals(env.get("useTempFile")); this.defaultDir = env.containsKey("default.dir") ? (String)env.get("default.dir") : "/"; @@ -290,28 +288,16 @@ public class ZipFileSystem extends FileSystem { try { ensureOpen(); e = getEntry0(path); - } finally { - endRead(); - } - if (e == null) { - if (path.length == 0) { - e = new Entry(new byte[0]); // root - } else if (buildDirTree) { - IndexNode inode = getDirs().get(IndexNode.keyOf(path)); + if (e == null) { + IndexNode inode = getInode(path); if (inode == null) return null; - e = new Entry(inode.name); - } else { - return null; + e = new Entry(inode.name); // pseudo directory + e.method = METHOD_STORED; // STORED for dir + e.mtime = e.atime = e.ctime = -1;// -1 for all times } - e.method = METHOD_STORED; // STORED for dir - BasicFileAttributes bfas = Attributes.readBasicFileAttributes(zfpath); - if (bfas.lastModifiedTime() != null) - e.mtime = bfas.lastModifiedTime().toMillis(); - if (bfas.lastAccessTime() != null) - e.atime = bfas.lastAccessTime().toMillis(); - if (bfas.creationTime() != null) - e.ctime = bfas.creationTime().toMillis(); + } finally { + endRead(); } return new ZipFileAttributes(e); } @@ -346,7 +332,7 @@ public class ZipFileSystem extends FileSystem { beginRead(); try { ensureOpen(); - return getEntry0(path) != null; + return getInode(path) != null; } finally { endRead(); } @@ -355,13 +341,10 @@ public class ZipFileSystem extends FileSystem { boolean isDirectory(byte[] path) throws IOException { - if (buildDirTree) - return getDirs().containsKey(IndexNode.keyOf(path)); - beginRead(); try { - Entry e = getEntry0(path); - return (e != null && e.isDir()) || path.length == 0; + IndexNode n = getInode(path); + return n != null && n.isDir(); } finally { endRead(); } @@ -383,39 +366,16 @@ public class ZipFileSystem extends FileSystem { beginWrite(); // iteration of inodes needs exclusive lock try { ensureOpen(); - if (buildDirTree) { - IndexNode inode = getDirs().get(IndexNode.keyOf(path)); - if (inode == null) - throw new NotDirectoryException(getString(path)); - List list = new ArrayList<>(); - IndexNode child = inode.child; - while (child != null) { - ZipPath zp = toZipPath(child.name); - if (filter == null || filter.accept(zp)) - list.add(zp); - child = child.sibling; - } - return list.iterator(); - } - - if (!isDirectory(path)) + IndexNode inode = getInode(path); + if (inode == null) throw new NotDirectoryException(getString(path)); List list = new ArrayList<>(); - path = toDirectoryPath(path); - for (IndexNode key : inodes.keySet()) { - if (!isParentOf(path, key.name)) // is "path" the parent of "name" - continue; - int off = path.length; - while (off < key.name.length) { - if (key.name[off] == '/') - break; - off++; - } - if (off < (key.name.length - 1)) - continue; - ZipPath zp = toZipPath(key.name); + IndexNode child = inode.child; + while (child != null) { + ZipPath zp = toZipPath(child.name); if (filter == null || filter.accept(zp)) list.add(zp); + child = child.sibling; } return list.iterator(); } finally { @@ -433,7 +393,6 @@ public class ZipFileSystem extends FileSystem { ensureOpen(); if (dir.length == 0 || exists(dir)) // root dir, or exiting dir throw new FileAlreadyExistsException(getString(dir)); - checkParents(dir); Entry e = new Entry(dir, Entry.NEW); e.method = METHOD_STORED; // STORED for dir @@ -476,7 +435,7 @@ public class ZipFileSystem extends FileSystem { checkParents(dst); } Entry u = new Entry(eSrc, Entry.COPY); // copy eSrc entry - u.name = dst; // change name + u.name(dst); // change name if (eSrc.type == Entry.NEW || eSrc.type == Entry.FILECH) { u.type = eSrc.type; // make it the same type @@ -518,7 +477,7 @@ public class ZipFileSystem extends FileSystem { if (opt == APPEND) hasAppend = true; } - beginRead(); // only need a readlock, the "update()" will + beginRead(); // only need a readlock, the "update()" will try { // try to obtain a writelock when the os is ensureOpen(); // being closed. Entry e = getEntry0(path); @@ -869,43 +828,27 @@ public class ZipFileSystem extends FileSystem { private void checkParents(byte[] path) throws IOException { beginRead(); try { - while ((path = getParent(path)) != null) { - if (!inodes.containsKey(IndexNode.keyOf(path))) + while ((path = getParent(path)) != null && path.length != 0) { + if (!inodes.containsKey(IndexNode.keyOf(path))) { throw new NoSuchFileException(getString(path)); + } } } finally { endRead(); } } + private static byte[] ROOTPATH = new byte[0]; private static byte[] getParent(byte[] path) { int off = path.length - 1; if (off > 0 && path[off] == '/') // isDirectory off--; while (off > 0 && path[off] != '/') { off--; } - if (off == 0) - return null; // top entry + if (off <= 0) + return ROOTPATH; return Arrays.copyOf(path, off + 1); } - // If "starter" is the parent directory of "path" - private static boolean isParentOf(byte[] p, byte[] c) { - final int plen = p.length; - if (plen == 0) // root dir - return true; - if (plen >= c.length) - return false; - int n = 0; - while (n < plen) { - if (p[n] != c[n]) - return false; - n++; - } - if (p[n - 1] != '/' && (c[n] != '/' || n == c.length - 1)) - return false; - return true; - } - private final void beginWrite() { rwlock.writeLock().lock(); } @@ -926,7 +869,7 @@ public class ZipFileSystem extends FileSystem { private volatile boolean isOpen = true; private final SeekableByteChannel ch; // channel to the zipfile - final byte[] cen; // CEN & ENDHDR + final byte[] cen; // CEN & ENDHDR private END end; private long locpos; // position of first LOC header (usually 0) @@ -1058,6 +1001,7 @@ public class ZipFileSystem extends FileSystem { if (end.endpos == 0) { inodes = new LinkedHashMap<>(10); locpos = 0; + buildNodeTree(); return null; // only END header present } if (end.cenlen > end.endpos) @@ -1101,6 +1045,7 @@ public class ZipFileSystem extends FileSystem { if (pos + ENDHDR != cen.length) { zerror("invalid CEN header (bad header size)"); } + buildNodeTree(); return cen; } @@ -1125,12 +1070,15 @@ public class ZipFileSystem extends FileSystem { private boolean hasUpdate = false; + // shared key. consumer guarantees the "writeLock" before use it. + private final IndexNode LOOKUPKEY = IndexNode.keyOf(null); + private void updateDelete(Entry e) { beginWrite(); try { - inodes.remove(IndexNode.keyOf(e.name)); //inodes.remove(e.name); + removeFromTree(e); + inodes.remove(e); hasUpdate = true; - dirs = null; } finally { endWrite(); } @@ -1139,9 +1087,16 @@ public class ZipFileSystem extends FileSystem { private void update(Entry e) { beginWrite(); try { - inodes.put(IndexNode.keyOf(e.name), e); //inodes.put(e, e); + IndexNode old = inodes.put(e, e); + if (old != null) { + removeFromTree(old); + } + if (e.type == Entry.NEW || e.type == Entry.FILECH) { + IndexNode parent = inodes.get(LOOKUPKEY.as(getParent(e.name))); + e.sibling = parent.child; + parent.child = e; + } hasUpdate = true; - dirs = null; } finally { endWrite(); } @@ -1229,7 +1184,7 @@ public class ZipFileSystem extends FileSystem { // ext) without enflating/deflating from the old zip // file LOC entry. written += copyLOCEntry(e, true, os, written, buf); - } else { // NEW or FILECH + } else { // NEW, FILECH or CEN e.locoff = written; written += e.writeLOC(os); // write loc header if (e.bytes != null) { // in-memory, deflated @@ -1265,7 +1220,10 @@ public class ZipFileSystem extends FileSystem { } catch (IOException x) { x.printStackTrace(); // skip any in-accurate entry } - } else { // unchanged inode + } else { // unchanged inode + if (inode.pos == -1) { + continue; // pseudo directory node + } e = Entry.readCEN(this, inode.pos); try { written += copyLOCEntry(e, false, os, written, buf); @@ -1318,36 +1276,30 @@ public class ZipFileSystem extends FileSystem { //System.out.printf("->sync(%s) done!%n", toString()); } - private Entry getEntry0(byte[] path) throws IOException { + private IndexNode getInode(byte[] path) { if (path == null) throw new NullPointerException("path"); - if (path.length == 0) - return null; - IndexNode inode = null; IndexNode key = IndexNode.keyOf(path); - if ((inode = inodes.get(key)) == null) { - if (path[path.length -1] == '/') // already has a slash - return null; + IndexNode inode = inodes.get(key); + if (inode == null && + (path.length == 0 || path[path.length -1] != '/')) { + // if does not ends with a slash path = Arrays.copyOf(path, path.length + 1); path[path.length - 1] = '/'; - if ((inode = inodes.get(key.as(path))) == null) - return null; + inode = inodes.get(key.as(path)); } + return inode; + } + + private Entry getEntry0(byte[] path) throws IOException { + IndexNode inode = getInode(path); if (inode instanceof Entry) return (Entry)inode; + if (inode == null || inode.pos == -1) + return null; return Entry.readCEN(this, inode.pos); } - // Test if the "name" a parent directory of any entry (dir empty) - boolean isAncestor(byte[] name) { - for (Map.Entry entry : inodes.entrySet()) { - byte[] ename = entry.getKey().name; - if (isParentOf(name, ename)) - return true; - } - return false; - } - public void deleteFile(byte[] path, boolean failIfNotExists) throws IOException { @@ -1359,7 +1311,7 @@ public class ZipFileSystem extends FileSystem { if (failIfNotExists) throw new NoSuchFileException(getString(path)); } else { - if (e.isDir() && isAncestor(path)) + if (e.isDir() && e.child != null) throw new DirectoryNotEmptyException(getString(path)); updateDelete(e); } @@ -1539,7 +1491,6 @@ public class ZipFileSystem extends FileSystem { public int available() { return rem > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) rem; } - public long size() { return size; } @@ -1762,7 +1713,7 @@ public class ZipFileSystem extends FileSystem { int pos = -1; // postion in cen table, -1 menas the // entry does not exists in zip file IndexNode(byte[] name, int pos) { - as(name); + name(name); this.pos = pos; } @@ -1770,15 +1721,25 @@ public class ZipFileSystem extends FileSystem { return new IndexNode(name, -1); } - final IndexNode as(byte[] name) { // reuse the node, mostly - this.name = name; // as a lookup "key" + final void name(byte[] name) { + this.name = name; this.hashcode = Arrays.hashCode(name); + } + + final IndexNode as(byte[] name) { // reuse the node, mostly + name(name); // as a lookup "key" return this; } + boolean isDir() { + return name != null && + (name.length == 0 || name[name.length - 1] == '/'); + } + public boolean equals(Object other) { - if (!(other instanceof IndexNode)) + if (!(other instanceof IndexNode)) { return false; + } return Arrays.equals(name, ((IndexNode)other).name); } @@ -1798,6 +1759,7 @@ public class ZipFileSystem extends FileSystem { static final int FILECH = 3; // fch update in "file" static final int COPY = 4; // copy of a CEN entry + byte[] bytes; // updated content bytes Path file; // use tmp file to store bytes; int type = CEN; // default is the entry read from cen @@ -1825,7 +1787,7 @@ public class ZipFileSystem extends FileSystem { Entry() {} Entry(byte[] name) { - this.name = name; + name(name); this.mtime = System.currentTimeMillis(); this.crc = 0; this.size = 0; @@ -1839,8 +1801,8 @@ public class ZipFileSystem extends FileSystem { } Entry (Entry e, int type) { + name(e.name); this.version = e.version; - this.name = e.name; this.ctime = e.ctime; this.atime = e.atime; this.mtime = e.mtime; @@ -1855,7 +1817,6 @@ public class ZipFileSystem extends FileSystem { this.attrsEx = e.attrsEx; this.locoff = e.locoff; this.comment = e.comment; - this.type = type; } @@ -1865,12 +1826,6 @@ public class ZipFileSystem extends FileSystem { this.method = METHOD_STORED; } - boolean isDir() { - return name != null && - (name.length == 0 || - name[name.length - 1] == '/'); - } - int version() throws ZipException { if (method == METHOD_DEFLATED) return 20; @@ -1909,7 +1864,7 @@ public class ZipFileSystem extends FileSystem { locoff = CENOFF(cen, pos); pos += CENHDR; - name = Arrays.copyOfRange(cen, pos, pos + nlen); + name(Arrays.copyOfRange(cen, pos, pos + nlen)); pos += nlen; if (elen > 0) { @@ -2132,7 +2087,8 @@ public class ZipFileSystem extends FileSystem { } writeShort(os, flag); // general purpose bit flag writeShort(os, method); // compression method - writeInt(os, mtime); // last modification time + // last modification time + writeInt(os, (int)javaToDosTime(mtime)); writeInt(os, crc); // crc-32 if (elen64 != 0) { writeInt(os, ZIP64_MINVAL); @@ -2318,50 +2274,56 @@ public class ZipFileSystem extends FileSystem { // structure. // A possible solution is to build the node tree ourself as // implemented below. - private HashMap dirs; private IndexNode root; - private IndexNode addToDir(IndexNode child) { - IndexNode cinode = dirs.get(child); - if (cinode != null) - return cinode; - - byte[] cname = child.name; - byte[] pname = getParent(cname); - IndexNode pinode; - - if (pname != null) - pinode = addToDir(IndexNode.keyOf(pname)); - else - pinode = root; - cinode = inodes.get(child); - if (cname[cname.length -1] != '/') { // not a dir - cinode.sibling = pinode.child; - pinode.child = cinode; - return null; - } - //cinode = dirs.get(child); - if (cinode == null) // pseudo directry entry - cinode = new IndexNode(cname, -1); - cinode.sibling = pinode.child; - pinode.child = cinode; - dirs.put(child, cinode); - return cinode; + private void addToTree(IndexNode inode, HashSet dirs) { + if (dirs.contains(inode)) { + return; + } + IndexNode parent; + byte[] name = inode.name; + byte[] pname = getParent(name); + if (inodes.containsKey(LOOKUPKEY.as(pname))) { + parent = inodes.get(LOOKUPKEY); + } else { // pseudo directory entry + parent = new IndexNode(pname, -1); + inodes.put(parent, parent); + } + addToTree(parent, dirs); + inode.sibling = parent.child; + parent.child = inode; + if (name[name.length -1] == '/') + dirs.add(inode); + } + + private void removeFromTree(IndexNode inode) { + IndexNode parent = inodes.get(LOOKUPKEY.as(getParent(inode.name))); + IndexNode child = parent.child; + if (child == inode) { + parent.child = child.sibling; + } else { + IndexNode last = child; + while ((child = child.sibling) != null) { + if (child == inode) { + last.sibling = child.sibling; + break; + } else { + last = child; + } + } + } } - private HashMap getDirs() - throws IOException - { + private void buildNodeTree() throws IOException { beginWrite(); try { - if (dirs != null) - return dirs; - dirs = new HashMap<>(); - root = new IndexNode(new byte[0], -1); - dirs.put(root, root); - for (IndexNode node : inodes.keySet()) - addToDir(node); - return dirs; + HashSet dirs = new HashSet<>(); + IndexNode root = new IndexNode(ROOTPATH, -1); + inodes.put(root, root); + dirs.add(root); + for (IndexNode node : inodes.keySet().toArray(new IndexNode[0])) { + addToTree(node, dirs); + } } finally { endWrite(); } diff --git a/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipPath.java b/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipPath.java index a2c766f0da2f92666f533461c4332c984f2be13d..f1617db40d206f411246d82acf9df20adcb7ffbc 100644 --- a/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipPath.java +++ b/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipPath.java @@ -157,7 +157,7 @@ public class ZipPath extends Path { @Override public ZipPath toRealPath(boolean resolveLinks) throws IOException { - ZipPath realPath = new ZipPath(zfs, getResolvedPath()); + ZipPath realPath = new ZipPath(zfs, getResolvedPath()).toAbsolutePath(); realPath.checkAccess(); return realPath; } @@ -472,8 +472,11 @@ public class ZipPath extends Path { int n = offsets[i]; int len = (i == offsets.length - 1)? (path.length - n):(offsets[i + 1] - n - 1); - if (len == 1 && path[n] == (byte)'.') + if (len == 1 && path[n] == (byte)'.') { + if (m == 0 && path[0] == '/') // absolute path + to[m++] = '/'; continue; + } if (len == 2 && path[n] == '.' && path[n + 1] == '.') { if (lastMOff >= 0) { m = lastM[lastMOff--]; // retreat @@ -726,6 +729,8 @@ public class ZipPath extends Path { @Override public boolean isSameFile(Path other) throws IOException { + if (this.equals(other)) + return true; if (other == null || this.getFileSystem() != other.getFileSystem()) return false; diff --git a/src/share/hpi/export/bool.h b/src/share/hpi/export/bool.h deleted file mode 100644 index e87c5a9e4ceb7128598830563d325cb1564a2b92..0000000000000000000000000000000000000000 --- a/src/share/hpi/export/bool.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 1994, 1998, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#ifndef _JAVASOFT_BOOL_H_ -#define _JAVASOFT_BOOL_H_ - -#undef TRUE -#undef FALSE - -typedef enum { - FALSE = 0, - TRUE = 1 -} bool_t; - -#endif /* !_JAVASOFT_BOOL_H_ */ diff --git a/src/share/hpi/export/dll.h b/src/share/hpi/export/dll.h deleted file mode 100644 index 76403eef6d3128067cba550b407d2075420b71b8..0000000000000000000000000000000000000000 --- a/src/share/hpi/export/dll.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#ifndef _JAVASOFT_DLL_H_ -#define _JAVASOFT_DLL_H_ - -#include - -/* DLL.H: A common interface for helper DLLs loaded by the VM. - * Each library exports the main entry point "DLL_Initialize". Through - * that function the programmer can obtain a function pointer which has - * type "GetInterfaceFunc." Through the function pointer the programmer - * can obtain other interfaces supported in the DLL. - */ -#ifdef __cplusplus -extern "C" { -#endif - -typedef jint (JNICALL * GetInterfaceFunc) - (void **intfP, const char *name, jint ver); - -jint JNICALL DLL_Initialize(GetInterfaceFunc *, void *args); - -#ifdef __cplusplus -} -#endif - -#endif /* !_JAVASOFT_DLL_H_ */ diff --git a/src/share/hpi/export/hpi.h b/src/share/hpi/export/hpi.h deleted file mode 100644 index 6fb6be845786f22db314dac67ca904552be77a35..0000000000000000000000000000000000000000 --- a/src/share/hpi/export/hpi.h +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Host Porting Interface. This defines the "porting layer" for - * POSIX.1 compliant operating systems. - */ - -#ifndef _JAVASOFT_HPI_H_ -#define _JAVASOFT_HPI_H_ - -#include -#include - -#include "jni.h" -#include "bool.h" -#include "hpi_md.h" -#include "dll.h" - -#ifdef __solaris__ -#define SSIZE_T ssize_t -#else -#ifdef _LP64 -#define SSIZE_T ssize_t -#else -#define SSIZE_T int -#endif -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * memory allocations - */ -typedef struct { - /* - * Malloc must return a unique pointer if size == 0. - */ - void * (*Malloc)(size_t size); - void * (*Realloc)(void *ptr, size_t new_size); - /* - * Free must allow ptr == NULL to be a no-op. - */ - void (*Free)(void *ptr); - /* - * Calloc must return a unique pointer for if - * n_item == 0 || item_size == 0. - */ - void * (*Calloc)(size_t n_item, size_t item_size); - char * (*Strdup)(const char *str); - - void * (*MapMem)(size_t req_size, size_t *maped_size); - void * (*UnmapMem)(void *req_addr, size_t req_size, size_t *unmap_size); - /* - * CommitMem should round the ptr down to the nearest page and - * round the size up to the nearest page so that the committed - * region is at least as large as the requested region. - */ - void * (*CommitMem)(void *ptr, size_t size, size_t *actual); - /* - * sysDecommitMem should round the ptr up to the nearest page and - * round the size down to the nearest page so that the decommitted - * region is no greater than the requested region. - */ - void * (*DecommitMem)(void *ptr, size_t size, size_t *actual); - -#define HPI_PAGE_ALIGNMENT (64 * 1024) - - void * (*AllocBlock)(size_t size, void **headP); - void (*FreeBlock)(void *head); -} HPI_MemoryInterface; - -/* - * dynamic linking libraries - */ -typedef struct { - void (*BuildLibName)(char *buf, int buf_len, char *path, char *name); - int (*BuildFunName)(char *name, int name_len, int arg_size, int en_idx); - - void * (*LoadLibrary)(const char *name, char *err_buf, int err_buflen); - void (*UnloadLibrary)(void *lib); - void * (*FindLibraryEntry)(void *lib, const char *name); -} HPI_LibraryInterface; - -typedef void (*signal_handler_t)(int sig, void *siginfo, void *context); - -#define HPI_SIG_DFL (signal_handler_t)0 -#define HPI_SIG_ERR (signal_handler_t)-1 -#define HPI_SIG_IGN (signal_handler_t)1 - -typedef struct { - char *name; /* name such as green/native threads. */ - int isMP; -} HPI_SysInfo; - -typedef struct { - HPI_SysInfo * (*GetSysInfo)(void); - long (*GetMilliTicks)(void); - jlong (*TimeMillis)(void); - - signal_handler_t (*Signal)(int sig, signal_handler_t handler); - void (*Raise)(int sig); - void (*SignalNotify)(int sig); - int (*SignalWait)(void); - - int (*Shutdown)(void); - - int (*SetLoggingLevel)(int level); - bool_t (*SetMonitoringOn)(bool_t on); - int (*GetLastErrorString)(char *buf, int len); -} HPI_SystemInterface; - -/* - * threads and monitors - */ -typedef struct sys_thread sys_thread_t; -typedef struct sys_mon sys_mon_t; - -#define HPI_OK 0 -#define HPI_ERR -1 -#define HPI_INTRPT -2 /* Operation was interrupted */ -#define HPI_TIMEOUT -3 /* A timer ran out */ -#define HPI_NOMEM -5 /* Ran out of memory */ -#define HPI_NORESOURCE -6 /* Ran out of some system resource */ - -/* There are three basic states: RUNNABLE, MONITOR_WAIT, and CONDVAR_WAIT. - * When the thread is suspended in any of these states, the - * HPI_THREAD_SUSPENDED bit will be set - */ -enum { - HPI_THREAD_RUNNABLE = 1, - HPI_THREAD_MONITOR_WAIT, - HPI_THREAD_CONDVAR_WAIT -}; - -#define HPI_MINIMUM_PRIORITY 1 -#define HPI_MAXIMUM_PRIORITY 10 -#define HPI_NORMAL_PRIORITY 5 - -#define HPI_THREAD_SUSPENDED 0x8000 -#define HPI_THREAD_INTERRUPTED 0x4000 - -typedef struct { - sys_thread_t *owner; - long entry_count; - sys_thread_t **monitor_waiters; - sys_thread_t **condvar_waiters; - int sz_monitor_waiters; - int sz_condvar_waiters; - int n_monitor_waiters; - int n_condvar_waiters; -} sys_mon_info; - -typedef struct { - int (*ThreadBootstrap)(sys_thread_t **tidP, - sys_mon_t **qlockP, - int nReservedBytes); - int (*ThreadCreate)(sys_thread_t **tidP, - long stk_size, - void (*func)(void *), - void *arg); - sys_thread_t * (*ThreadSelf)(void); - void (*ThreadYield)(void); - int (*ThreadSuspend)(sys_thread_t *tid); - int (*ThreadResume)(sys_thread_t *tid); - int (*ThreadSetPriority)(sys_thread_t *tid, int prio); - int (*ThreadGetPriority)(sys_thread_t *tid, int *prio); - void * (*ThreadStackPointer)(sys_thread_t *tid); - void * (*ThreadStackTop)(sys_thread_t *tid); - long * (*ThreadRegs)(sys_thread_t *tid, int *regs); - int (*ThreadSingle)(void); - void (*ThreadMulti)(void); - int (*ThreadEnumerateOver)(int (*func)(sys_thread_t *, void *), - void *arg); - int (*ThreadCheckStack)(void); - void (*ThreadPostException)(sys_thread_t *tid, void *arg); - void (*ThreadInterrupt)(sys_thread_t *tid); - int (*ThreadIsInterrupted)(sys_thread_t *tid, int clear); - int (*ThreadAlloc)(sys_thread_t **tidP); - int (*ThreadFree)(void); - jlong (*ThreadCPUTime)(void); - int (*ThreadGetStatus)(sys_thread_t *tid, sys_mon_t **monitor); - void * (*ThreadInterruptEvent)(void); - void * (*ThreadNativeID)(sys_thread_t *tid); - - /* These three functions are used by the CPU time profiler. - * sysThreadIsRunning determines whether the thread is running (not just - * runnable). It is only safe to call this function after calling - * sysThreadProfSuspend. - */ - bool_t (*ThreadIsRunning)(sys_thread_t *tid); - void (*ThreadProfSuspend)(sys_thread_t *tid); - void (*ThreadProfResume)(sys_thread_t *tid); - - int (*AdjustTimeSlice)(int ms); - - size_t (*MonitorSizeof)(void); - int (*MonitorInit)(sys_mon_t *mid); - int (*MonitorDestroy)(sys_mon_t *mid); - int (*MonitorEnter)(sys_thread_t *self, sys_mon_t *mid); - bool_t (*MonitorEntered)(sys_thread_t *self, sys_mon_t *mid); - int (*MonitorExit)(sys_thread_t *self, sys_mon_t *mid); - int (*MonitorNotify)(sys_thread_t *self, sys_mon_t *mid); - int (*MonitorNotifyAll)(sys_thread_t *self, sys_mon_t *mid); - int (*MonitorWait)(sys_thread_t *self, sys_mon_t *mid, jlong ms); - bool_t (*MonitorInUse)(sys_mon_t *mid); - sys_thread_t * (*MonitorOwner)(sys_mon_t *mid); - int (*MonitorGetInfo)(sys_mon_t *mid, sys_mon_info *info); - -} HPI_ThreadInterface; - -/* - * files - */ - -#define HPI_FILETYPE_REGULAR (0) -#define HPI_FILETYPE_DIRECTORY (1) -#define HPI_FILETYPE_OTHER (2) - -typedef struct { - char * (*NativePath)(char *path); - int (*FileType)(const char *path); - int (*Open)(const char *name, int openMode, int filePerm); - int (*Close)(int fd); - jlong (*Seek)(int fd, jlong offset, int whence); - int (*SetLength)(int fd, jlong length); - int (*Sync)(int fd); - int (*Available)(int fd, jlong *bytes); - size_t (*Read)(int fd, void *buf, unsigned int nBytes); - size_t (*Write)(int fd, const void *buf, unsigned int nBytes); - int (*FileSizeFD)(int fd, jlong *size); -} HPI_FileInterface; - -/* - * sockets - */ -struct sockaddr; -struct hostent; - -typedef struct { - int (*Close)(int fd); - long (*Available)(int fd, jint *pbytes); - int (*Connect)(int fd, struct sockaddr *him, int len); - int (*Accept)(int fd, struct sockaddr *him, int *len); - SSIZE_T (*SendTo)(int fd, char *buf, int len, int flags, - struct sockaddr *to, int tolen); - SSIZE_T (*RecvFrom)(int fd, char *buf, int nbytes, int flags, - struct sockaddr *from, int *fromlen); - int (*Listen)(int fd, int count); - SSIZE_T (*Recv)(int fd, char *buf, int nBytes, int flags); - SSIZE_T (*Send)(int fd, char *buf, int nBytes, int flags); - int (*Timeout)(int fd, long timeout); - struct hostent * (*GetHostByName)(char *hostname); - int (*Socket)(int domain, int type, int protocol); - int (*SocketShutdown)(int fd, int howto); - int (*Bind)(int fd, struct sockaddr *him, int len); - int (*GetSocketName)(int fd, struct sockaddr *him, int *len); - int (*GetHostName)(char *hostname, int namelen); - struct hostent * (*GetHostByAddr)(const char *hostname, int len, int type); - int (*SocketGetOption)(int fd, int level, int optname, char *optval, int *optlen); - int (*SocketSetOption)(int fd, int level, int optname, const char *optval, int optlen); - struct protoent * (*GetProtoByName)(char* name); -} HPI_SocketInterface; - -/* - * callbacks. - */ -typedef struct vm_calls { - int (*jio_fprintf)(FILE *fp, const char *fmt, ...); - void (*panic)(const char *fmt, ...); - void (*monitorRegister)(sys_mon_t *mid, char *info_str); - - void (*monitorContendedEnter)(sys_thread_t *self, sys_mon_t *mid); - void (*monitorContendedEntered)(sys_thread_t *self, sys_mon_t *mid); - void (*monitorContendedExit)(sys_thread_t *self, sys_mon_t *mid); -} vm_calls_t; - -#ifdef __cplusplus -} -#endif - -#endif /* !_JAVASOFT_HPI_H_ */ diff --git a/src/share/hpi/include/hpi_impl.h b/src/share/hpi/include/hpi_impl.h deleted file mode 100644 index 72f8d36e2d6512e47507b30808f2d50be7597ac4..0000000000000000000000000000000000000000 --- a/src/share/hpi/include/hpi_impl.h +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#ifndef _JAVASOFT_HPI_IMPL_H_ -#define _JAVASOFT_HPI_IMPL_H_ - -#include "hpi.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#include "vm_calls.h" - -extern int nReservedBytes; -sys_thread_t *allocThreadBlock(void); -void freeThreadBlock(sys_thread_t *tid); -int threadBootstrapMD(sys_thread_t **tid, sys_mon_t **lockP, int nb); - -HPI_SysInfo *sysGetSysInfo(void); -long sysGetMilliTicks(void); -jlong sysTimeMillis(void); - -signal_handler_t sysSignal(int sig, signal_handler_t handler); -void sysRaise(int sig); -void sysSignalNotify(int sig); -int sysSignalWait(void); -int sysShutdown(void); -int sysSetLoggingLevel(int level); -bool_t sysSetMonitoringOn(bool_t on); -int sysGetLastErrorString(char *buf, int len); - -void * sysMalloc(size_t); -void * sysRealloc(void*, size_t); -void sysFree(void*); -void * sysCalloc(size_t, size_t); -char * sysStrdup(const char * string); -void * sysMapMem(size_t, size_t *); -void * sysUnmapMem(void *, size_t, size_t *); -void * sysCommitMem(void * ptr, size_t size, size_t * actual); -void * sysDecommitMem(void * ptr, size_t size, size_t * actual); -void * sysAllocBlock(size_t, void**); -void sysFreeBlock(void *); - -void sysBuildLibName(char *, int, char *, char *); -int sysBuildFunName(char *, int, int, int); -void * sysLoadLibrary(const char *, char *err_buf, int err_buflen); -void sysUnloadLibrary(void *); -void * sysFindLibraryEntry(void *, const char *); - -int sysThreadBootstrap(sys_thread_t **, sys_mon_t **, int); -int sysThreadCreate(sys_thread_t **, - long, - void (*)(void *), - void *arg); -void sysThreadExit(void); -sys_thread_t * sysThreadSelf(void); -void sysThreadYield(void); -int sysThreadSuspend(sys_thread_t *); -int sysThreadResume(sys_thread_t *); -int sysThreadSetPriority(sys_thread_t *, int); -int sysThreadGetPriority(sys_thread_t *, int *); -void * sysThreadStackPointer(sys_thread_t *); -void * sysThreadStackTop(sys_thread_t *); -long * sysThreadRegs(sys_thread_t *, int *); -int sysThreadSingle(void); -void sysThreadMulti(void); -int sysThreadEnumerateOver(int (*)(sys_thread_t *, void *), void *); -int sysThreadCheckStack(void); -void sysThreadPostException(sys_thread_t *, void *); -void sysThreadInterrupt(sys_thread_t *); -int sysThreadIsInterrupted(sys_thread_t *, int); -int sysThreadAlloc(sys_thread_t **); -int sysThreadFree(void); -size_t sysThreadSizeof(void); -jlong sysThreadCPUTime(void); -int sysThreadGetStatus(sys_thread_t *, sys_mon_t **); -int sysAdjustUserThreadCount(int delta); -bool_t sysThreadIsRunning(sys_thread_t *); -void sysThreadProfSuspend(sys_thread_t *); -void sysThreadProfResume(sys_thread_t *); -int sysAdjustTimeSlice(int); -int sysThreadEnumerateOver(int (*f)(sys_thread_t *, void *), void *arg); -void * sysThreadInterruptEvent(void); -void * sysThreadNativeID(sys_thread_t *); - -size_t sysMonitorSizeof(void); -int sysMonitorInit(sys_mon_t *); -int sysMonitorDestroy(sys_mon_t *); -int sysMonitorEnter(sys_thread_t *, sys_mon_t *); -bool_t sysMonitorEntered(sys_thread_t *, sys_mon_t *); -int sysMonitorExit(sys_thread_t *, sys_mon_t *); -int sysMonitorNotify(sys_thread_t *, sys_mon_t *); -int sysMonitorNotifyAll(sys_thread_t *, sys_mon_t *); -int sysMonitorWait(sys_thread_t *, sys_mon_t *, jlong); -bool_t sysMonitorInUse(sys_mon_t *); -sys_thread_t * sysMonitorOwner(sys_mon_t *); -int sysMonitorGetInfo(sys_mon_t *, sys_mon_info *); - -char *sysNativePath(char *path); -int sysFileType(const char *path); -int sysOpen(const char *name, int openMode, int filePerm); -int sysClose(int fd); -jlong sysSeek(int fd, jlong offset, int whence); -int sysSetLength(int fd, jlong length); -int sysSync(int fd); -int sysAvailable(int fd, jlong *bytes); -size_t sysRead(int fd, void *buf, unsigned int nBytes); -size_t sysWrite(int fd, const void *buf, unsigned int nBytes); -int sysFileSizeFD(int fd, jlong *size); - -int sysSocketClose(int fd); -int sysSocketShutdown(int fd, int howto); -long sysSocketAvailable(int fd, jint *pbytes); -int sysConnect(int fd, struct sockaddr *him, int len); -int sysBind(int fd, struct sockaddr *him, int len); -int sysAccept(int fd, struct sockaddr *him, int *len); -int sysGetSockName(int fd, struct sockaddr *him, int *len); -#ifdef _LP64 -ssize_t sysSendTo(int fd, char *buf, int len, int flags, struct sockaddr *to, - int tolen); -ssize_t sysRecvFrom(int fd, char *buf, int nbytes, int flags, - struct sockaddr *from, int *fromlen); -ssize_t sysRecv(int fd, char *buf, int nBytes, int flags); -ssize_t sysSend(int fd, char *buf, int nBytes, int flags); -#else -int sysSendTo(int fd, char *buf, int len, int flags, struct sockaddr *to, - int tolen); -int sysRecvFrom(int fd, char *buf, int nbytes, int flags, - struct sockaddr *from, int *fromlen); -int sysRecv(int fd, char *buf, int nBytes, int flags); -int sysSend(int fd, char *buf, int nBytes, int flags); -#endif -int sysListen(int fd, int count); -int sysTimeout(int fd, long timeout); -int sysGetHostName(char* name, int namelen); -struct hostent *sysGetHostByAddr(const char* name, int len, int type); -struct hostent *sysGetHostByName(char *hostname); -int sysSocket(int domain, int type, int protocol); -int sysGetSockOpt(int fd, int level, int optname, char *optval, int *optlen); -int sysSetSockOpt(int fd, int level, int optname, const char *optval, int optlen); -struct protoent * sysGetProtoByName(char* name); - -#define SYS_SIG_DFL HPI_SIG_DFL -#define SYS_SIG_ERR HPI_SIG_ERR -#define SYS_SIG_IGN HPI_SIG_IGN - -#define SYS_OK HPI_OK -#define SYS_ERR HPI_ERR -#define SYS_INTRPT HPI_INTRPT -#define SYS_TIMEOUT HPI_TIMEOUT -#define SYS_NOMEM HPI_NOMEM -#define SYS_NORESOURCE HPI_NORESOURCE - -#define SYS_THREAD_RUNNABLE HPI_THREAD_RUNNABLE -#define SYS_THREAD_MONITOR_WAIT HPI_THREAD_MONITOR_WAIT -#define SYS_THREAD_CONDVAR_WAIT HPI_THREAD_CONDVAR_WAIT - -#define MinimumPriority HPI_MINIMUM_PRIORITY -#define MaximumPriority HPI_MAXIMUM_PRIORITY -#define NormalPriority HPI_NORMAL_PRIORITY - -#define SYS_THREAD_SUSPENDED HPI_THREAD_SUSPENDED - -#define PAGE_ALIGNMENT HPI_PAGE_ALIGNMENT - -#define SYS_TIMEOUT_INFINITY HPI_TIMEOUT_INFINITY - -#define SYS_FILETYPE_REGULAR HPI_FILETYPE_REGULAR -#define SYS_FILETYPE_DIRECTORY HPI_FILETYPE_DIRECTORY -#define SYS_FILETYPE_OTHER HPI_FILETYPE_OTHER - -typedef void *stackp_t; - -/* global vars */ - -extern int logging_level; -extern bool_t profiler_on; - -#ifdef __cplusplus -} -#endif - -#endif /* !_JAVASOFT_HPI_IMPL_H_ */ diff --git a/src/share/hpi/include/vm_calls.h b/src/share/hpi/include/vm_calls.h deleted file mode 100644 index 10037c4a97b6f519daf3f4b7ad47d961dcb81d48..0000000000000000000000000000000000000000 --- a/src/share/hpi/include/vm_calls.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#ifndef _JAVASOFT_VM_CALLS_H_ -#define _JAVASOFT_VM_CALLS_H_ - -/* This file defines the function table and macros exported from the VM - * for the implementation of HPI. - */ - -extern vm_calls_t *vm_calls; - -#define VM_CALLS_READY() vm_calls -#define VM_CALL(f) (vm_calls->f) - -#undef sysAssert - -#ifdef DEBUG -#define sysAssert(expression) { \ - if (!(expression)) { \ - vm_calls->panic \ - ("\"%s\", line %d: assertion failure\n", __FILE__, __LINE__); \ - } \ -} -#else -#define sysAssert(expression) ((void) 0) -#endif - -#ifdef LOGGING - -#define Log(level, message) { \ - if (vm_calls && level <= logging_level) \ - vm_calls->jio_fprintf(stderr, message); \ -} - -#define Log1(level, message, x1) { \ - if (vm_calls && level <= logging_level) \ - vm_calls->jio_fprintf(stderr, message, (x1)); \ -} - -#define Log2(level, message, x1, x2) { \ - if (vm_calls && level <= logging_level) \ - vm_calls->jio_fprintf(stderr, message, (x1), (x2)); \ -} - -#define Log3(level, message, x1, x2, x3) { \ - if (vm_calls && level <= logging_level) \ - vm_calls->jio_fprintf(stderr, message, (x1), (x2), (x3)); \ -} - -#define Log4(level, message, x1, x2, x3, x4) { \ - if (vm_calls && level <= logging_level) \ - vm_calls->jio_fprintf(stderr, message, (x1), (x2), (x3), (x4)); \ -} - -#else - -#define Log(level, message) ((void) 0) -#define Log1(level, message, x1) ((void) 0) -#define Log2(level, message, x1, x2) ((void) 0) -#define Log3(level, message, x1, x2, x3) ((void) 0) -#define Log4(level, message, x1, x2, x3, x4) ((void) 0) - -#endif /* LOGGING */ - -#endif /* !_JAVASOFT_VM_CALLS_H_ */ diff --git a/src/share/hpi/src/hpi.c b/src/share/hpi/src/hpi.c deleted file mode 100644 index 09389d3cf691b34284b32b1e41e02c7783550a55..0000000000000000000000000000000000000000 --- a/src/share/hpi/src/hpi.c +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright (c) 1998, 1999, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include - -#include "hpi_impl.h" -#include "threads_md.h" - -int logging_level = 0; -bool_t profiler_on = FALSE; - -int sysSetLoggingLevel(int level) -{ - int old = logging_level; - logging_level = level; - return old; -} - -bool_t sysSetMonitoringOn(bool_t s) -{ - bool_t old = profiler_on; - profiler_on = s; - return old; -} - -int nReservedBytes; - -sys_thread_t *allocThreadBlock() -{ - char *p = sysCalloc(nReservedBytes + sizeof(sys_thread_t), 1); - if (p == NULL) { - return NULL; - } - return (sys_thread_t *)(p + nReservedBytes); -} - -void freeThreadBlock(sys_thread_t *tid) -{ - sysFree((char *)tid - nReservedBytes); -} - -vm_calls_t *vm_calls = NULL; - -static HPI_MemoryInterface hpi_memory_interface = { - sysMalloc, - sysRealloc, - sysFree, - sysCalloc, - sysStrdup, - sysMapMem, - sysUnmapMem, - sysCommitMem, - sysDecommitMem, - sysAllocBlock, - sysFreeBlock, -}; - -static HPI_LibraryInterface hpi_library_interface = { - sysBuildLibName, - sysBuildFunName, - sysLoadLibrary, - sysUnloadLibrary, - sysFindLibraryEntry, -}; - -static HPI_SystemInterface hpi_system_interface = { - sysGetSysInfo, - sysGetMilliTicks, - sysTimeMillis, - sysSignal, - sysRaise, - sysSignalNotify, - sysSignalWait, - sysShutdown, - sysSetLoggingLevel, - sysSetMonitoringOn, - sysGetLastErrorString -}; - -static HPI_ThreadInterface hpi_thread_interface = { - sysThreadBootstrap, - sysThreadCreate, - sysThreadSelf, - sysThreadYield, - sysThreadSuspend, - sysThreadResume, - sysThreadSetPriority, - sysThreadGetPriority, - sysThreadStackPointer, - sysThreadStackTop, - sysThreadRegs, - sysThreadSingle, - sysThreadMulti, - sysThreadEnumerateOver, - sysThreadCheckStack, - sysThreadPostException, - sysThreadInterrupt, - sysThreadIsInterrupted, - sysThreadAlloc, - sysThreadFree, - sysThreadCPUTime, - sysThreadGetStatus, - sysThreadInterruptEvent, - sysThreadNativeID, - sysThreadIsRunning, - sysThreadProfSuspend, - sysThreadProfResume, - sysAdjustTimeSlice, - sysMonitorSizeof, - sysMonitorInit, - sysMonitorDestroy, - sysMonitorEnter, - sysMonitorEntered, - sysMonitorExit, - sysMonitorNotify, - sysMonitorNotifyAll, - sysMonitorWait, - sysMonitorInUse, - sysMonitorOwner, - sysMonitorGetInfo, -}; - -static HPI_FileInterface hpi_file_interface = { - sysNativePath, - sysFileType, - sysOpen, - sysClose, - sysSeek, - sysSetLength, - sysSync, - sysAvailable, - sysRead, - sysWrite, - sysFileSizeFD -}; - -static HPI_SocketInterface hpi_socket_interface = { - sysSocketClose, - sysSocketAvailable, - sysConnect, - sysAccept, - sysSendTo, - sysRecvFrom, - sysListen, - sysRecv, - sysSend, - sysTimeout, - sysGetHostByName, - sysSocket, - sysSocketShutdown, - sysBind, - sysGetSockName, - sysGetHostName, - sysGetHostByAddr, - sysGetSockOpt, - sysSetSockOpt, - sysGetProtoByName, -}; - -static jint JNICALL -GetInterface(void **intfP, const char *name, jint version) -{ - *intfP = NULL; - if (version != 1) { - return -1; - } - if (strcmp(name, "Memory") == 0) { - *intfP = &hpi_memory_interface; - return 0; - } - if (strcmp(name, "Library") == 0) { - *intfP = &hpi_library_interface; - return 0; - } - if (strcmp(name, "System") == 0) { - *intfP = &hpi_system_interface; - return 0; - } - if (strcmp(name, "Thread") == 0) { - *intfP = &hpi_thread_interface; - return 0; - } - if (strcmp(name, "File") == 0) { - *intfP = &hpi_file_interface; - return 0; - } - if (strcmp(name, "Socket") == 0) { - *intfP = &hpi_socket_interface; - return 0; - } - return -2; -} - -jint JNICALL -DLL_Initialize(GetInterfaceFunc *gi, void *args) -{ - vm_calls = args; - *gi = GetInterface; - return SYS_OK; -} diff --git a/src/share/instrument/JPLISAgent.c b/src/share/instrument/JPLISAgent.c index adc9cf13355cdbf94da3c86439df624854d710fc..7f6b2a0b67c970f506ad9a527e38f321be17cb27 100644 --- a/src/share/instrument/JPLISAgent.c +++ b/src/share/instrument/JPLISAgent.c @@ -209,7 +209,7 @@ createNewJPLISAgent(JavaVM * vm, JPLISAgent **agent_ptr) { *agent_ptr = NULL; jnierror = (*vm)->GetEnv( vm, (void **) &jvmtienv, - JVMTI_VERSION); + JVMTI_VERSION_1_1); if ( jnierror != JNI_OK ) { initerror = JPLIS_INIT_ERROR_CANNOT_CREATE_NATIVE_AGENT; } else { @@ -990,7 +990,7 @@ retransformableEnvironment(JPLISAgent * agent) { } jnierror = (*agent->mJVM)->GetEnv( agent->mJVM, (void **) &retransformerEnv, - JVMTI_VERSION); + JVMTI_VERSION_1_1); if ( jnierror != JNI_OK ) { return NULL; } diff --git a/src/share/javavm/export/jmm.h b/src/share/javavm/export/jmm.h index e25de8bbb77697883da6bdb9a44d45473c031c94..df08124e56c508bbb606a14f2c87ff230a69d519 100644 --- a/src/share/javavm/export/jmm.h +++ b/src/share/javavm/export/jmm.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,7 +60,8 @@ typedef struct { unsigned int isBootClassPathSupported : 1; unsigned int isObjectMonitorUsageSupported : 1; unsigned int isSynchronizerUsageSupported : 1; - unsigned int : 24; + unsigned int isThreadAllocatedMemorySupported : 1; + unsigned int : 23; } jmmOptionalSupport; typedef enum { @@ -105,7 +106,8 @@ typedef enum { JMM_VERBOSE_GC = 21, JMM_VERBOSE_CLASS = 22, JMM_THREAD_CONTENTION_MONITORING = 23, - JMM_THREAD_CPU_TIME = 24 + JMM_THREAD_CPU_TIME = 24, + JMM_THREAD_ALLOCATED_MEMORY = 25 } jmmBoolAttribute; @@ -213,7 +215,10 @@ typedef struct jmmInterface_1_ { jobject (JNICALL *GetMemoryPoolUsage) (JNIEnv* env, jobject pool); jobject (JNICALL *GetPeakMemoryPoolUsage) (JNIEnv* env, jobject pool); - void* reserved4; + void (JNICALL *GetThreadAllocatedMemory) + (JNIEnv *env, + jlongArray ids, + jlongArray sizeArray); jobject (JNICALL *GetMemoryUsage) (JNIEnv* env, jboolean heap); @@ -228,6 +233,8 @@ typedef struct jmmInterface_1_ { jlong* result); jobjectArray (JNICALL *FindCircularBlockedThreads) (JNIEnv *env); + + // Not used in JDK 6 or JDK 7 jlong (JNICALL *GetThreadCpuTime) (JNIEnv *env, jlong thread_id); jobjectArray (JNICALL *GetVMGlobalNames) (JNIEnv *env); @@ -262,14 +269,22 @@ typedef struct jmmInterface_1_ { void (JNICALL *GetLastGCStat) (JNIEnv *env, jobject mgr, jmmGCStat *gc_stat); - jlong (JNICALL *GetThreadCpuTimeWithKind) (JNIEnv *env, - jlong thread_id, - jboolean user_sys_cpu_time); - void* reserved5; + + jlong (JNICALL *GetThreadCpuTimeWithKind) + (JNIEnv *env, + jlong thread_id, + jboolean user_sys_cpu_time); + void (JNICALL *GetThreadCpuTimesWithKind) + (JNIEnv *env, + jlongArray ids, + jlongArray timeArray, + jboolean user_sys_cpu_time); + jint (JNICALL *DumpHeap0) (JNIEnv *env, jstring outputfile, jboolean live); - jobjectArray (JNICALL *FindDeadlocks) (JNIEnv *env, jboolean object_monitors_only); + jobjectArray (JNICALL *FindDeadlocks) (JNIEnv *env, + jboolean object_monitors_only); void (JNICALL *SetVMGlobal) (JNIEnv *env, jstring flag_name, jvalue new_value); diff --git a/src/share/javavm/export/jvmti.h b/src/share/javavm/export/jvmti.h index c235f16376bcadbbb9a47388a3ad8397f63fb3b1..7e9f2216b55055ef8eb8a803474b8a561347fe16 100644 --- a/src/share/javavm/export/jvmti.h +++ b/src/share/javavm/export/jvmti.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,8 +41,9 @@ enum { JVMTI_VERSION_1 = 0x30010000, JVMTI_VERSION_1_0 = 0x30010000, JVMTI_VERSION_1_1 = 0x30010100, + JVMTI_VERSION_1_2 = 0x30010200, - JVMTI_VERSION = 0x30000000 + (1 * 0x10000) + (1 * 0x100) + 102 /* version: 1.1.102 */ + JVMTI_VERSION = 0x30000000 + (1 * 0x10000) + (2 * 0x100) + 1 /* version: 1.2.1 */ }; JNIEXPORT jint JNICALL @@ -1774,6 +1775,12 @@ typedef struct jvmtiInterface_1_ { jobject object, jlong* size_ptr); + /* 155 : Get Local Instance */ + jvmtiError (JNICALL *GetLocalInstance) (jvmtiEnv* env, + jthread thread, + jint depth, + jobject* value_ptr); + } jvmtiInterface_1; struct _jvmtiEnv { @@ -2031,6 +2038,12 @@ struct _jvmtiEnv { return functions->GetLocalObject(this, thread, depth, slot, value_ptr); } + jvmtiError GetLocalInstance(jthread thread, + jint depth, + jobject* value_ptr) { + return functions->GetLocalInstance(this, thread, depth, value_ptr); + } + jvmtiError GetLocalInt(jthread thread, jint depth, jint slot, @@ -2518,3 +2531,4 @@ struct _jvmtiEnv { #endif /* __cplusplus */ #endif /* !_JAVA_JVMTI_H_ */ + diff --git a/src/share/native/sun/awt/image/jpeg/imageioJPEG.c b/src/share/native/sun/awt/image/jpeg/imageioJPEG.c index bfbef221dbd2bc39d03a6e96269d499ba43c9f5d..04a87fd1cac8ac663f69976e39a214547924e28a 100644 --- a/src/share/native/sun/awt/image/jpeg/imageioJPEG.c +++ b/src/share/native/sun/awt/image/jpeg/imageioJPEG.c @@ -109,8 +109,8 @@ typedef struct streamBufferStruct { jobject stream; // ImageInputStream or ImageOutputStream jbyteArray hstreamBuffer; // Handle to a Java buffer for the stream JOCTET *buf; // Pinned buffer pointer */ - int bufferOffset; // holds offset between unpin and the next pin - int bufferLength; // Allocated, nut just used + size_t bufferOffset; // holds offset between unpin and the next pin + size_t bufferLength; // Allocated, nut just used int suspendable; // Set to true to suspend input long remaining_skip; // Used only on input } streamBuffer, *streamBufferPtr; @@ -129,7 +129,7 @@ typedef struct streamBufferStruct { * Used to signal that no data need be restored from an unpin to a pin. * I.e. the buffer is empty. */ -#define NO_DATA -1 +#define NO_DATA ((size_t)-1) // Forward reference static void resetStreamBuffer(JNIEnv *env, streamBufferPtr sb); @@ -389,7 +389,6 @@ typedef struct imageIODataStruct { static imageIODataPtr initImageioData (JNIEnv *env, j_common_ptr cinfo, jobject obj) { - int i, j; imageIODataPtr data = (imageIODataPtr) malloc (sizeof(imageIOData)); if (data == NULL) { @@ -982,7 +981,7 @@ imageio_fill_suspended_buffer(j_decompress_ptr cinfo) streamBufferPtr sb = &data->streamBuf; JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); jint ret; - int offset, buflen; + size_t offset, buflen; /* * The original (jpegdecoder.c) had code here that called @@ -1520,7 +1519,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_initJPEGImageReader imageio_dispose((j_common_ptr)cinfo); return 0; } - return (jlong) ret; + return ptr_to_jlong(ret); } /* @@ -1535,7 +1534,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_setSource jlong ptr, jobject source) { - imageIODataPtr data = (imageIODataPtr) ptr; + imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr); j_common_ptr cinfo; if (data == NULL) { @@ -1574,7 +1573,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImageHeader int h_samp0, h_samp1, h_samp2; int v_samp0, v_samp1, v_samp2; jboolean retval = JNI_FALSE; - imageIODataPtr data = (imageIODataPtr) ptr; + imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr); j_decompress_ptr cinfo; struct jpeg_source_mgr *src; sun_jpeg_error_ptr jerr; @@ -1772,7 +1771,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_setOutColorSpace jlong ptr, jint code) { - imageIODataPtr data = (imageIODataPtr) ptr; + imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr); j_decompress_ptr cinfo; if (data == NULL) { @@ -1814,7 +1813,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImage struct jpeg_source_mgr *src; JSAMPROW scanLinePtr = NULL; jint bands[MAX_BANDS]; - int i, j; + int i; jint *body; int scanlineLimit; int pixelStride; @@ -1824,14 +1823,12 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImage pixelBufferPtr pb; sun_jpeg_error_ptr jerr; boolean done; - jint *bandSize; - int maxBandValue, halfMaxBandValue; boolean mustScale = FALSE; boolean progressive = FALSE; boolean orderedBands = TRUE; - imageIODataPtr data = (imageIODataPtr) ptr; + imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr); j_decompress_ptr cinfo; - unsigned int numBytes; + size_t numBytes; /* verify the inputs */ @@ -1849,7 +1846,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImage cinfo = (j_decompress_ptr) data->jpegObj; - if ((numBands < 1) || + if ((numBands < 1) || (numBands > MAX_BANDS) || (sourceXStart < 0) || (sourceXStart >= (jint)cinfo->image_width) || (sourceYStart < 0) || (sourceYStart >= (jint)cinfo->image_height) || (sourceWidth < 1) || (sourceWidth > (jint)cinfo->image_width) || @@ -1863,10 +1860,10 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImage return JNI_FALSE; } - if (stepX > cinfo->image_width) { + if (stepX > (jint)cinfo->image_width) { stepX = cinfo->image_width; } - if (stepY > cinfo->image_height) { + if (stepY > (jint)cinfo->image_height) { stepY = cinfo->image_height; } @@ -2119,7 +2116,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_abortRead jobject this, jlong ptr) { - imageIODataPtr data = (imageIODataPtr) ptr; + imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr); if (data == NULL) { JNU_ThrowByName(env, @@ -2137,7 +2134,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_resetLibraryState (JNIEnv *env, jobject this, jlong ptr) { - imageIODataPtr data = (imageIODataPtr) ptr; + imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr); j_decompress_ptr cinfo; if (data == NULL) { @@ -2159,7 +2156,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_resetReader jobject this, jlong ptr) { - imageIODataPtr data = (imageIODataPtr) ptr; + imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr); j_decompress_ptr cinfo; sun_jpeg_error_ptr jerr; @@ -2232,7 +2229,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_disposeReader jclass reader, jlong ptr) { - imageIODataPtr data = (imageIODataPtr) ptr; + imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr); j_common_ptr info = destroyImageioData(env, data); imageio_dispose(info); @@ -2317,8 +2314,8 @@ imageio_term_destination (j_compress_ptr cinfo) JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); /* find out how much needs to be written */ - jint datacount = sb->bufferLength - dest->free_in_buffer; - + /* this conversion from size_t to jint is safe, because the lenght of the buffer is limited by jint */ + jint datacount = (jint)(sb->bufferLength - dest->free_in_buffer); if (datacount != 0) { RELEASE_ARRAYS(env, data, (const JOCTET *)(dest->next_output_byte)); @@ -2485,7 +2482,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_initJPEGImageWriter imageio_dispose((j_common_ptr)cinfo); return 0; } - return (jlong) ret; + return ptr_to_jlong(ret); } JNIEXPORT void JNICALL @@ -2495,7 +2492,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_setDest jlong ptr, jobject destination) { - imageIODataPtr data = (imageIODataPtr) ptr; + imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr); j_compress_ptr cinfo; if (data == NULL) { @@ -2526,7 +2523,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_writeTables struct jpeg_destination_mgr *dest; sun_jpeg_error_ptr jerr; - imageIODataPtr data = (imageIODataPtr) ptr; + imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr); j_compress_ptr cinfo; if (data == NULL) { @@ -2625,10 +2622,11 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_writeImage jint *scanData; jint *bandSize; int maxBandValue, halfMaxBandValue; - imageIODataPtr data = (imageIODataPtr) ptr; + imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr); j_compress_ptr cinfo; UINT8** scale = NULL; + /* verify the inputs */ if (data == NULL) { @@ -2740,6 +2738,16 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_writeImage buffer); JNU_ThrowByName(env, "javax/imageio/IIOException", buffer); } + + if (scale != NULL) { + for (i = 0; i < numBands; i++) { + if (scale[i] != NULL) { + free(scale[i]); + } + } + free(scale); + } + free(scanLinePtr); return data->abortFlag; } @@ -2953,7 +2961,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_abortWrite jobject this, jlong ptr) { - imageIODataPtr data = (imageIODataPtr) ptr; + imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr); if (data == NULL) { JNU_ThrowByName(env, @@ -2970,7 +2978,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_resetWriter (JNIEnv *env, jobject this, jlong ptr) { - imageIODataPtr data = (imageIODataPtr) ptr; + imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr); j_compress_ptr cinfo; if (data == NULL) { @@ -3002,7 +3010,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_disposeWriter jclass writer, jlong ptr) { - imageIODataPtr data = (imageIODataPtr) ptr; + imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr); j_common_ptr info = destroyImageioData(env, data); imageio_dispose(info); diff --git a/src/share/native/sun/awt/image/jpeg/jdmarker.c b/src/share/native/sun/awt/image/jpeg/jdmarker.c index e52661f66458dc8033861c7ddb0f68870adddd0f..eeb9b64fd1e2808526d50b09f1b4c45a4104e5e8 100644 --- a/src/share/native/sun/awt/image/jpeg/jdmarker.c +++ b/src/share/native/sun/awt/image/jpeg/jdmarker.c @@ -1325,14 +1325,14 @@ jpeg_save_markers (j_decompress_ptr cinfo, int marker_code, unsigned int length_limit) { my_marker_ptr marker = (my_marker_ptr) cinfo->marker; - long maxlength; + size_t maxlength; jpeg_marker_parser_method processor; /* Length limit mustn't be larger than what we can allocate * (should only be a concern in a 16-bit environment). */ maxlength = cinfo->mem->max_alloc_chunk - SIZEOF(struct jpeg_marker_struct); - if (((long) length_limit) > maxlength) + if (length_limit > maxlength) length_limit = (unsigned int) maxlength; /* Choose processor routine to use. diff --git a/src/share/native/sun/awt/image/jpeg/jmemmgr.c b/src/share/native/sun/awt/image/jpeg/jmemmgr.c index 778a1f186f7566905adf04657c522186296018f6..5ee681333c1a3994f2720ddc60891597f55e747e 100644 --- a/src/share/native/sun/awt/image/jpeg/jmemmgr.c +++ b/src/share/native/sun/awt/image/jpeg/jmemmgr.c @@ -133,7 +133,7 @@ typedef struct { jvirt_barray_ptr virt_barray_list; /* This counts total space obtained from jpeg_get_small/large */ - long total_space_allocated; + size_t total_space_allocated; /* alloc_sarray and alloc_barray set this value for use by virtual * array routines. @@ -588,8 +588,8 @@ realize_virt_arrays (j_common_ptr cinfo) /* Allocate the in-memory buffers for any unrealized virtual arrays */ { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; - long space_per_minheight, maximum_space, avail_mem; - long minheights, max_minheights; + size_t space_per_minheight, maximum_space, avail_mem; + size_t minheights, max_minheights; jvirt_sarray_ptr sptr; jvirt_barray_ptr bptr; @@ -1032,7 +1032,7 @@ GLOBAL(void) jinit_memory_mgr (j_common_ptr cinfo) { my_mem_ptr mem; - long max_to_use; + size_t max_to_use; int pool; size_t test_mac; @@ -1109,8 +1109,10 @@ jinit_memory_mgr (j_common_ptr cinfo) if ((memenv = getenv("JPEGMEM")) != NULL) { char ch = 'x'; + unsigned int mem_max = 0u; - if (sscanf(memenv, "%ld%c", &max_to_use, &ch) > 0) { + if (sscanf(memenv, "%u%c", &mem_max, &ch) > 0) { + max_to_use = (size_t)mem_max; if (ch == 'm' || ch == 'M') max_to_use *= 1000L; mem->pub.max_memory_to_use = max_to_use * 1000L; diff --git a/src/share/native/sun/awt/image/jpeg/jmemnobs.c b/src/share/native/sun/awt/image/jpeg/jmemnobs.c index bf4936d02d14e3139a3f01bf35b657c2c066e6bc..884c5a16830fbba6a7953a073b24c154b12d726e 100644 --- a/src/share/native/sun/awt/image/jpeg/jmemnobs.c +++ b/src/share/native/sun/awt/image/jpeg/jmemnobs.c @@ -73,9 +73,9 @@ jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject) * Here we always say, "we got all you want bud!" */ -GLOBAL(long) -jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed, - long max_bytes_needed, long already_allocated) +GLOBAL(size_t) +jpeg_mem_available (j_common_ptr cinfo, size_t min_bytes_needed, + size_t max_bytes_needed, size_t already_allocated) { return max_bytes_needed; } @@ -100,7 +100,7 @@ jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info, * cleanup required. Here, there isn't any. */ -GLOBAL(long) +GLOBAL(size_t) jpeg_mem_init (j_common_ptr cinfo) { return 0; /* just set max_memory_to_use to 0 */ diff --git a/src/share/native/sun/awt/image/jpeg/jmemsys.h b/src/share/native/sun/awt/image/jpeg/jmemsys.h index b427da0f352602f613dfbc71a21389fbf24aac05..c5c64b3188629ef184ba35c41f968657061637dd 100644 --- a/src/share/native/sun/awt/image/jpeg/jmemsys.h +++ b/src/share/native/sun/awt/image/jpeg/jmemsys.h @@ -104,10 +104,10 @@ EXTERN(void) jpeg_free_large JPP((j_common_ptr cinfo, void FAR * object, * Conversely, zero may be returned to always use the minimum amount of memory. */ -EXTERN(long) jpeg_mem_available JPP((j_common_ptr cinfo, - long min_bytes_needed, - long max_bytes_needed, - long already_allocated)); +EXTERN(size_t) jpeg_mem_available JPP((j_common_ptr cinfo, + size_t min_bytes_needed, + size_t max_bytes_needed, + size_t already_allocated)); /* @@ -198,5 +198,5 @@ EXTERN(void) jpeg_open_backing_store JPP((j_common_ptr cinfo, * all opened backing-store objects have been closed. */ -EXTERN(long) jpeg_mem_init JPP((j_common_ptr cinfo)); +EXTERN(size_t) jpeg_mem_init JPP((j_common_ptr cinfo)); EXTERN(void) jpeg_mem_term JPP((j_common_ptr cinfo)); diff --git a/src/share/native/sun/awt/image/jpeg/jpegdecoder.c b/src/share/native/sun/awt/image/jpeg/jpegdecoder.c index d896231b5f45326e00a4b6a6dd3893f72eea2048..2b0992b5151fd6b6c8e29d33bd490497382daf9a 100644 --- a/src/share/native/sun/awt/image/jpeg/jpegdecoder.c +++ b/src/share/native/sun/awt/image/jpeg/jpegdecoder.c @@ -328,7 +328,7 @@ sun_jpeg_fill_suspended_buffer(j_decompress_ptr cinfo) if ((*env)->ExceptionOccurred(env) || !GET_ARRAYS(env, src)) { cinfo->err->error_exit((struct jpeg_common_struct *) cinfo); } - if (ret <= src->remaining_skip) { + if (ret < 0 || (unsigned int)ret <= src->remaining_skip) { return; } if (src->remaining_skip) { @@ -397,7 +397,7 @@ sun_jpeg_skip_input_data(j_decompress_ptr cinfo, long num_bytes) } num_bytes += src->remaining_skip; src->remaining_skip = 0; - ret = src->pub.bytes_in_buffer; + ret = (int)src->pub.bytes_in_buffer; /* this conversion is safe, because capacity of the buffer is limited by jnit */ if (ret >= num_bytes) { src->pub.next_input_byte += num_bytes; src->pub.bytes_in_buffer -= num_bytes; diff --git a/src/share/native/sun/awt/image/jpeg/jpeglib.h b/src/share/native/sun/awt/image/jpeg/jpeglib.h index 49c67e289358c92c4f4f7afe634e6054ef37bab4..d3821f361584538a3773d3cc1ca2f103d11482eb 100644 --- a/src/share/native/sun/awt/image/jpeg/jpeglib.h +++ b/src/share/native/sun/awt/image/jpeg/jpeglib.h @@ -800,10 +800,10 @@ struct jpeg_memory_mgr { * used for virtual-array buffers.) May be changed by outer application * after creating the JPEG object. */ - long max_memory_to_use; + size_t max_memory_to_use; /* Maximum allocation request accepted by alloc_large. */ - long max_alloc_chunk; + size_t max_alloc_chunk; }; diff --git a/src/share/native/sun/management/ThreadImpl.c b/src/share/native/sun/management/ThreadImpl.c index 7ffdb351b13b694f49c917bdf15c6101d317ad25..9e1baadf15cba64af682741e8f7d39d392b72429 100644 --- a/src/share/native/sun/management/ThreadImpl.c +++ b/src/share/native/sun/management/ThreadImpl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,9 +42,15 @@ Java_sun_management_ThreadImpl_setThreadCpuTimeEnabled0 jmm_interface->SetBoolAttribute(env, JMM_THREAD_CPU_TIME, flag); } +JNIEXPORT void JNICALL +Java_sun_management_ThreadImpl_setThreadAllocatedMemoryEnabled0 + (JNIEnv *env, jclass cls, jboolean flag) +{ + jmm_interface->SetBoolAttribute(env, JMM_THREAD_ALLOCATED_MEMORY, flag); +} JNIEXPORT void JNICALL -Java_sun_management_ThreadImpl_getThreadInfo0 +Java_sun_management_ThreadImpl_getThreadInfo1 (JNIEnv *env, jclass cls, jlongArray ids, jint maxDepth, jobjectArray infoArray) { @@ -65,6 +71,14 @@ Java_sun_management_ThreadImpl_getThreadTotalCpuTime0 return jmm_interface->GetThreadCpuTimeWithKind(env, tid, JNI_TRUE /* user+sys */); } +JNIEXPORT void JNICALL +Java_sun_management_ThreadImpl_getThreadTotalCpuTime1 + (JNIEnv *env, jclass cls, jlongArray ids, jlongArray timeArray) +{ + jmm_interface->GetThreadCpuTimesWithKind(env, ids, timeArray, + JNI_TRUE /* user+sys */); +} + JNIEXPORT jlong JNICALL Java_sun_management_ThreadImpl_getThreadUserCpuTime0 (JNIEnv *env, jclass cls, jlong tid) @@ -72,6 +86,21 @@ Java_sun_management_ThreadImpl_getThreadUserCpuTime0 return jmm_interface->GetThreadCpuTimeWithKind(env, tid, JNI_FALSE /* user */); } +JNIEXPORT void JNICALL +Java_sun_management_ThreadImpl_getThreadUserCpuTime1 + (JNIEnv *env, jclass cls, jlongArray ids, jlongArray timeArray) +{ + jmm_interface->GetThreadCpuTimesWithKind(env, ids, timeArray, + JNI_FALSE /* user */); +} + +JNIEXPORT void JNICALL +Java_sun_management_ThreadImpl_getThreadAllocatedMemory1 + (JNIEnv *env, jclass cls, jlongArray ids, jlongArray sizeArray) +{ + jmm_interface->GetThreadAllocatedMemory(env, ids, sizeArray); +} + JNIEXPORT jobjectArray JNICALL Java_sun_management_ThreadImpl_findMonitorDeadlockedThreads0 (JNIEnv *env, jclass cls) diff --git a/src/share/native/sun/management/VMManagementImpl.c b/src/share/native/sun/management/VMManagementImpl.c index a7cb4b35e658d34e7119787392d033f43838f233..295d93c34f55fc51a4ddc7a5c1e1eb912245aa8f 100644 --- a/src/share/native/sun/management/VMManagementImpl.c +++ b/src/share/native/sun/management/VMManagementImpl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -92,6 +92,9 @@ Java_sun_management_VMManagementImpl_initOptionalSupportFields setStaticBooleanField(env, cls, "objectMonitorUsageSupport", JNI_FALSE); setStaticBooleanField(env, cls, "synchronizerUsageSupport", JNI_FALSE); } + + value = mos.isThreadAllocatedMemorySupported; + setStaticBooleanField(env, cls, "threadAllocatedMemorySupport", value); } JNIEXPORT jobjectArray JNICALL @@ -201,6 +204,13 @@ Java_sun_management_VMManagementImpl_isThreadCpuTimeEnabled return jmm_interface->GetBoolAttribute(env, JMM_THREAD_CPU_TIME); } +JNIEXPORT jboolean JNICALL +Java_sun_management_VMManagementImpl_isThreadAllocatedMemoryEnabled + (JNIEnv *env, jobject dummy) +{ + return jmm_interface->GetBoolAttribute(env, JMM_THREAD_ALLOCATED_MEMORY); +} + JNIEXPORT jint JNICALL Java_sun_management_VMManagementImpl_getProcessId (JNIEnv *env, jobject dummy) diff --git a/src/solaris/classes/sun/java2d/xr/XRSurfaceData.java b/src/solaris/classes/sun/java2d/xr/XRSurfaceData.java index 0491e719c593cc79ea5763d378f32ba666b5df3e..f09d0f3de4f8d213850e8f020866597e58cf2c1d 100644 --- a/src/solaris/classes/sun/java2d/xr/XRSurfaceData.java +++ b/src/solaris/classes/sun/java2d/xr/XRSurfaceData.java @@ -479,8 +479,7 @@ public abstract class XRSurfaceData extends XSurfaceData { if (xrpipe == null) { try { SunToolkit.awtLock(); - xgc = renderQueue.createGC(xid); // TODO: GC leak? where to - // clean up? + xgc = XCreateGC(getNativeOps()); xrpipe = new XRRenderer(maskBuffer.getMaskBuffer()); xrtxpipe = new PixelToShapeConverter(xrpipe); diff --git a/src/solaris/hpi/export/byteorder_md.h b/src/solaris/hpi/export/byteorder_md.h deleted file mode 100644 index 3ba7232bb97ab3afe19d5789a3856228911b5884..0000000000000000000000000000000000000000 --- a/src/solaris/hpi/export/byteorder_md.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 1994, 1998, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Solaris-dependent byte order include - */ - -#ifndef _JAVASOFT_SOLARIS_BYTE_MD_H_ -#define _JAVASOFT_SOLARIS_BYTE_MD_H_ - -#include - -#endif /* !_JAVASOFT_SOLARIS_BYTE_MD_H_ */ diff --git a/src/solaris/hpi/export/io_md.h b/src/solaris/hpi/export/io_md.h deleted file mode 100644 index d1cc95d4938df30dd37e723b5545800a9bfcefeb..0000000000000000000000000000000000000000 --- a/src/solaris/hpi/export/io_md.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 1994, 1998, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Solaris-dependent I/O - */ - -#ifndef _JAVASOFT_SOLARIS_IO_MD_H_ -#define _JAVASOFT_SOLARIS_IO_MD_H_ - -#include -#include -#include -#include -#include -#include -#include - -#define LINE_SEPARATOR "\n" - -/* file system macros moved to sysmacros_md.h */ - -#endif /* !_JAVASOFT_SOLARIS_IO_MD_H_ */ diff --git a/src/solaris/hpi/export/path_md.h b/src/solaris/hpi/export/path_md.h deleted file mode 100644 index 3539437e34097cc33b1d399d3b87ad0b4d25055d..0000000000000000000000000000000000000000 --- a/src/solaris/hpi/export/path_md.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 1994, 1998, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Solaris-dependent search path definitions and API - */ - -#ifndef _JAVASOFT_SOLARIS_PATH_MD_H_ -#define _JAVASOFT_SOLARIS_PATH_MD_H_ - -#define PATH_SEPARATOR ":" -#define PATH_CURDIR "." - -#define DIR_SEPARATOR '/' -#define LOCAL_DIR_SEPARATOR '/' - -#endif /* !_JAVASOFT_SOLARIS_PATH_MD_H_ */ diff --git a/src/solaris/hpi/export/timeval_md.h b/src/solaris/hpi/export/timeval_md.h deleted file mode 100644 index 77148a850c4182595feadf8c2156dfe22d07da02..0000000000000000000000000000000000000000 --- a/src/solaris/hpi/export/timeval_md.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 1994, 1998, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#ifndef _JAVASOFT_SOLARIS_TIMEVAL_H_ -#define _JAVASOFT_SOLARIS_TIMEVAL_H_ - -typedef struct { - long tv_sec; /* seconds */ - long tv_usec; /* microseconds (NOT milliseconds) */ -} timeval_t; - -#endif /* !_JAVASOFT_SOLARIS_TIMEVAL_H_ */ diff --git a/src/solaris/hpi/include/interrupt.h b/src/solaris/hpi/include/interrupt.h deleted file mode 100644 index 9c273c0b8cb4d814c67da268ed14a4d235b5a6ff..0000000000000000000000000000000000000000 --- a/src/solaris/hpi/include/interrupt.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 1994, 2000, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Interrupt dispatch interface - */ - -#ifndef _JAVASOFT_INTERRUPT_H_ -#define _JAVASOFT_INTERRUPT_H_ - -/* - * Type definitions. - */ - -/*- - * A function that handles interrupt dispatch requests is of type - * intr_handler_t. This type definition is mostly for convenience. - * A declaration of a handler function, should look like this: - * - * void myHandler(int interrupt, void *siginfo, void *context, void *arg); - * - * An intr_handler_t is constrained: - * - * - It runs on the exception stack. - * - It cannot yield. - * - It cannot allocate/free memory. - * - It can only call interrupt-safe routines. - * - * "arg" is set to the "handlerArg" specified in intrRegister(). - */ -typedef void (*intr_handler_t)(int interrupt, void *siginfo, - void *context, void *arg); - -/* - * Routines. - */ - -/* Initialize the interrupt system */ -void intrInit(void); - -/* Set a handler for a particular interrupt */ -signal_handler_t intrRegister(int interrupt, intr_handler_t handler, - void *handlerArg); - -/* Dispatch an interrupt (called from the low-level handlers) */ -void intrDispatch(int interrupt, void *siginfo, void *context); - -/*- - * The target specific header file should define the following - * - * Constants - * - * N_INTERRUPTS - The number of interrupt channels. These - * are numbered from 0 to (N_INTERRUPTS - 1). - */ -#ifdef __linux__ -#define N_INTERRUPTS NSIG /* 0 to NSIG - 1*/ -#else -#define N_INTERRUPTS 32 /* 0 to 31 */ -#endif - -/*- - * Routines/Macros that control whether interrupts are enabled or - * not. - * - * void intrLock(void) - Disable all interrupts. - * void intrUnlock(void) - Enable all interrupts. - * - * Note: intrLock()/intrUnlock() pairs can be nested. - * - */ - -void intrLock(void); -void intrUnlock(void); - -/*- - * intrInitMD() -- - * Initialize the machine-dependant interrupt software. - * - * This routine should leave the all interrupts disabled as if - * one (1) intrLock() had been called. At the end of the - * bootstrap, a single intrUnlock(), will be called to turn - * interrupts on. - */ - -void intrInitMD(void); - -#if defined(__solaris__) && !defined(SA_SIGINFO) -#error signal.h has not been included? -#endif - -#ifdef SA_SIGINFO -/* Thread implementation dependent interrupt dispatcher. */ -void intrDispatchMD(int sig, siginfo_t *info, void *uc); -#else -void intrDispatchMD(int sig); -#endif - -/* Whether the signal is used by the HPI implementation */ -bool_t intrInUse(int sig); - -#endif /* !_JAVASOFT_INTERRUPT_H_ */ diff --git a/src/solaris/hpi/include/largefile.h b/src/solaris/hpi/include/largefile.h deleted file mode 100644 index 453053475886bff812c11b7c21fbe22d4025ad63..0000000000000000000000000000000000000000 --- a/src/solaris/hpi/include/largefile.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#ifndef _JAVASOFT_LARGEFILE_SUPPORT_H_ -#define _JAVASOFT_LARGEFILE_SUPPORT_H_ - -#ifdef __solaris__ -#include "largefile_solaris.h" -#endif - -#ifdef __linux__ -#include "largefile_linux.h" -#endif - -/* - * Prototypes for wrappers that we define. These wrapper functions - * are low-level I/O routines that will use 64 bit versions if - * available, else revert to the 32 bit ones. - */ -extern off64_t lseek64_w(int fd, off64_t offset, int whence); -extern int fstat64_w(int fd, struct stat *buf); -extern int ftruncate64_w(int fd, off64_t length); -extern int open64_w(const char *path, int oflag, int mode); - -/* This is defined in system_md.c */ -extern int sysFfileMode(int fd, int* mode); - -#endif /* _JAVASOFT_LARGEFILE_SUPPORT_H_ */ diff --git a/src/solaris/hpi/include/largefile_solaris.h b/src/solaris/hpi/include/largefile_solaris.h deleted file mode 100644 index b40666ffe977f1a78193477d42d1e942e1e9d426..0000000000000000000000000000000000000000 --- a/src/solaris/hpi/include/largefile_solaris.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 1998, 1999, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#ifndef _JAVASOFT_SOLARIS_LARGEFILE_SUPPORT_H_ -#define _JAVASOFT_SOLARIS_LARGEFILE_SUPPORT_H_ - -#include -#include - -/** - * This file contains the definitions for providing 64 bit File I/O support. - */ - -#if !defined(_LFS_LARGEFILE) || !_LFS_LARGEFILE - -#ifdef __GLIBC__ -typedef jlong longlong_t; -#endif - -/* - * This definition is from Solaris 2.6; it is required by systems that do not - * support large files (e.g., Solaris 2.5.1). - */ - -typedef longlong_t off64_t; /* offsets within files */ - - -#ifdef __GLIBC__ -/* Doesn't matter what these are, there is no 64 bit support. */ -typedef int u_longlong_t; -typedef int timestruc_t; -#define _ST_FSTYPSZ 1 -#endif /* __GLIBC__ */ - -/* - * The stat64 structure must be provided on systems without large file - * support (e.g., Solaris 2.5.1). These definitions are from Solaris 2.6 - * sys/stat.h and sys/types.h. - */ - -typedef u_longlong_t ino64_t; /* expanded inode type */ -typedef longlong_t blkcnt64_t; /* count of file blocks */ - -struct stat64 { - dev_t st_dev; - long st_pad1[3]; - ino64_t st_ino; - mode_t st_mode; - nlink_t st_nlink; - uid_t st_uid; - gid_t st_gid; - dev_t st_rdev; - long st_pad2[2]; - off64_t st_size; - timestruc_t st_atim; - timestruc_t st_mtim; - timestruc_t st_ctim; - long st_blksize; - blkcnt64_t st_blocks; - char st_fstype[_ST_FSTYPSZ]; - long st_pad4[8]; -}; - -#define O_LARGEFILE 0x2000 /* Solaris 2.6 sys/fcntl.h */ -#endif /* !_LFS_LARGEFILE */ - -#endif /* !_JAVASOFT_SOLARIS_LARGEFILE_SUPPORT_H_ */ diff --git a/src/solaris/hpi/native_threads/include/condvar_md.h b/src/solaris/hpi/native_threads/include/condvar_md.h deleted file mode 100644 index 0f86fbb5987775d01730780cd85039951c62fd97..0000000000000000000000000000000000000000 --- a/src/solaris/hpi/native_threads/include/condvar_md.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 1994, 1998, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Interface to condition variable HPI implementation for Solaris - */ - -#ifndef _JAVASOFT_CONDVAR_MD_H_ -#define _JAVASOFT_CONDVAR_MD_H_ - -#include "threads_md.h" - -typedef struct condvar { - cond_t cond; /* Manual-reset event for notifications */ - unsigned int counter; /* Current number of notifications */ -} condvar_t; - -int condvarInit(condvar_t *); -int condvarDestroy(condvar_t *); -int condvarWait(condvar_t *, mutex_t *, thread_state_t wtype); -int condvarTimedWait(condvar_t *, mutex_t *, jlong millis, thread_state_t wtype); -int condvarSignal(condvar_t *); -int condvarBroadcast(condvar_t *); - -#endif /* !_JAVASOFT_CONDVAR_MD_H_ */ diff --git a/src/solaris/hpi/native_threads/include/monitor_md.h b/src/solaris/hpi/native_threads/include/monitor_md.h deleted file mode 100644 index 7d20da695a31d4f2ce7b4159d0f65ce725e458bc..0000000000000000000000000000000000000000 --- a/src/solaris/hpi/native_threads/include/monitor_md.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 1994, 1998, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Monitor interface 10/25/94 - * - * Private data structures and interfaces used in the monitor code. - * This file is used to share declarations and such between the different - * files implementing monitors. It does not contain exported API. - */ - -#ifndef _JAVASOFT_SOLARIS_MONITOR_MD_H_ -#define _JAVASOFT_SOLARIS_MONITOR_MD_H_ - -#include -#include -#include - -/* - * Type definitions. - */ - -typedef struct monitor_waiter monitor_waiter_t; -typedef struct monitor_wait_queue monitor_wait_queue_t; - -/* Element of the MonitorWaitQ - representing thread doing a monitor wait */ -/* - * The only reason we do the queueing is for sysMonitorDumpInfo. - * The counting, though, is used to avoid extraneous calls to - * condvarBroadcast and condvarSignal, for instance. - */ -struct monitor_waiter { - monitor_waiter_t *next; - monitor_waiter_t **prev; - sys_thread_t *waiting_thread; -}; - -struct monitor_wait_queue { - monitor_waiter_t *head; /* linked list of waiting threads */ - short count; /* number of waiters on the list */ -}; - -#define ANY_WAITING(mwq) ((mwq).count > 0) -#define INIT_MONITOR_WAIT_QUEUE(mwq) { (mwq).head = NULL; (mwq).count = 0; } - -/* The system-level monitor data structure */ -struct sys_mon { - mutex_t mutex; /* The monitor's mutex */ - condvar_t cv_monitor; /* Notify those doing monitorWait on - the monitor */ - /* - * Threads waiting on either of the above condvars put themselves - * on one of these lists. - */ - monitor_wait_queue_t mwait_queue; /* Head of MonitorWaitQ */ - - /* Thread currently executing in this monitor */ - sys_thread_t *monitor_owner; - long entry_count; /* Recursion depth */ - int contention_count; -}; - -void initializeContentionCountMutex(); - -typedef enum { - ASYNC_REGISTER, - ASYNC_UNREGISTER -} async_action_t; - -/* - * Macros - */ - -#define SYS_MID_NULL ((sys_mon_t *) 0) - -typedef enum { - SYS_ASYNC_MON_ALARM = 1, - SYS_ASYNC_MON_IO, - SYS_ASYNC_MON_EVENT, - SYS_ASYNC_MON_CHILD, - SYS_ASYNC_MON_MAX -} async_mon_key_t; - -#define SYS_ASYNC_MON_INPUT SYS_ASYNC_MON_IO -#define SYS_ASYNC_MON_OUTPUT SYS_ASYNC_MON_IO - -sys_mon_t *asyncMon(async_mon_key_t); - -#endif /* !_JAVASOFT_SOLARIS_MONITOR_MD_H_ */ diff --git a/src/solaris/hpi/native_threads/include/mutex_md.h b/src/solaris/hpi/native_threads/include/mutex_md.h deleted file mode 100644 index c384d00b2809867a09f5c2c4f4f8b566cd1a7ba8..0000000000000000000000000000000000000000 --- a/src/solaris/hpi/native_threads/include/mutex_md.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 1994, 1998, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Interface to mutex HPI implementation for Solaris - */ - -#ifndef _JAVASOFT_MUTEX_MD_H_ -#define _JAVASOFT_MUTEX_MD_H_ - -#include "porting.h" - -/* - * Generally, we would typedef mutex_t to be whatever the system - * supplies. But Solaris gives us mutex_t directly. - */ - -#ifdef USE_PTHREADS -#define mutexInit(m) pthread_mutex_init(m, 0) -#else -#define mutexInit(m) mutex_init(m, USYNC_THREAD, 0) -#endif -#define mutexDestroy(m) mutex_destroy(m) -#define mutexLock(m) mutex_lock(m) -#define mutexUnlock(m) mutex_unlock(m) -bool_t mutexLocked(mutex_t *); - -#endif /* !_JAVASOFT_MUTEX_MD_H_ */ diff --git a/src/solaris/hpi/native_threads/include/np.h b/src/solaris/hpi/native_threads/include/np.h deleted file mode 100644 index 8fab6e193761c632ded4af684002c4c0b68364de..0000000000000000000000000000000000000000 --- a/src/solaris/hpi/native_threads/include/np.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 1998, 2000, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Non-posix parts of the threads HPI. - */ - -#ifndef _JAVASOFT_NP_H_ -#define _JAVASOFT_NP_H_ - -extern int np_suspend(sys_thread_t *tid); -extern int np_continue(sys_thread_t *tid); - -extern int np_single(void); -extern void np_multi(void); -extern int np_stackinfo(void **addr, long *size); -extern int np_initialize(void); -extern void np_initialize_thread(sys_thread_t *tid); -#ifdef __linux__ -extern int np_initial_suspend(sys_thread_t *tid); -extern void np_free_thread(sys_thread_t *tid); -#endif - -extern void np_profiler_init(sys_thread_t *tid); -extern int np_profiler_suspend(sys_thread_t *tid); -extern int np_profiler_continue(sys_thread_t *tid); -extern bool_t np_profiler_thread_is_running(sys_thread_t *tid); - -#endif /* !_JAVASOFT_NP_H_ */ diff --git a/src/solaris/hpi/native_threads/include/porting.h b/src/solaris/hpi/native_threads/include/porting.h deleted file mode 100644 index fdbbec0071554fce4013f5a5c958ee5159c42db0..0000000000000000000000000000000000000000 --- a/src/solaris/hpi/native_threads/include/porting.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 1998, 2000, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#ifndef _JAVASOFT_PORTING_H_ -#define _JAVASOFT_PORTING_H_ - -#ifndef USE_PTHREADS - -#include -#include -#include - -#else /* USE_PTHREADS */ - -#include - -/* There is a handshake between a newly created thread and its creator - * at thread startup because the creator thread needs to suspend the - * new thread. Currently there are two ways to do this -- with - * semaphores and with mutexes. The semaphore based implementation is - * cleaner and hence is the default. We wish the mutex based one will - * go away, but turns out the implementation of semaphores on - * Linux/ppc etc is flaky, so the mutex based solution lives for now. - */ -#ifndef USE_MUTEX_HANDSHAKE -#include -#endif - -#undef BOUND_THREADS - -#define thread_t pthread_t - -#define mutex_t pthread_mutex_t -#define mutex_lock pthread_mutex_lock -#define mutex_trylock pthread_mutex_trylock -#define mutex_unlock pthread_mutex_unlock -#define mutex_destroy pthread_mutex_destroy - -#define cond_t pthread_cond_t -#define cond_destroy pthread_cond_destroy -#define cond_wait pthread_cond_wait -#define cond_timedwait pthread_cond_timedwait -#define cond_signal pthread_cond_signal -#define cond_broadcast pthread_cond_broadcast - -#define thread_key_t pthread_key_t -#define thr_setspecific pthread_setspecific -#define thr_keycreate pthread_key_create - -#define thr_sigsetmask pthread_sigmask -#define thr_self pthread_self -#define thr_yield sched_yield -#define thr_kill pthread_kill -#define thr_exit pthread_exit -#ifdef __linux__ -void intrHandler(void*); -#endif -#endif /* USE_PTHREADS */ - -#endif /* !_JAVASOFT_PORTING_H_ */ diff --git a/src/solaris/hpi/native_threads/include/threads_md.h b/src/solaris/hpi/native_threads/include/threads_md.h deleted file mode 100644 index a958a40f9cb9bb6d0c9c7ed51d28d3bc1e94469c..0000000000000000000000000000000000000000 --- a/src/solaris/hpi/native_threads/include/threads_md.h +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Implementation of the Java threads HPI on top of Solaris threads - */ - -#ifndef _JAVASOFT_SOLARIS_THREADS_MD_H_ -#define _JAVASOFT_SOLARIS_THREADS_MD_H_ - -#include "porting.h" - -#ifdef sparc -#define N_TRACED_REGS 12 -#elif i386 -#define N_TRACED_REGS 7 -#elif amd64 -#define N_TRACED_REGS 15 -#elif ppc -#define N_TRACED_REGS 1 -#elif m68k -#define N_TRACED_REGS 8 -#elif ia64 -/* [RGV] I don't think this is referenced in the linux code */ -#define N_TRACED_REGS 32 -#else -// TODO: delete this file - threads_md.[ch] is obsolete. struct sys_thread is -// never used. Define a value just to keep compiler happy. -#define N_TRACED_REGS 32 -#endif - -/* Turn on if we want all java threads to be bound tolwps */ -/* #define BOUND_THREADS */ -/* Use /proc soln to stop lwps in place of siglwp soln */ -#define PROCLWP - -/* - * Thread C stack overflow check -#define sysThreadCheckStack(redzone, var) \ - ((var = sysThreadSelf()) && \ - (unsigned int)((char *)&(var) - (char *)(var)->stack_base)\ - < (redzone)) -*/ -/* - * Forward definition of machine dependent monitor struct - */ -struct sys_mon; - -/* - * The following thread states are really hints since there is no - * interface to get at a native thread's true state. The states - * are maintained by updating the states where ever possible - * such as a transition to CONDVAR_WAIT occurs in the definition of - * the routine condvarWait(). - * This state maintenance should disappear once we have a threads interface - * to obtain a thread's state. - */ -typedef enum { - FIRST_THREAD_STATE, - RUNNABLE = FIRST_THREAD_STATE, - SUSPENDED, - CONDVAR_WAIT, - NUM_THREAD_STATES -} thread_state_t; - -#if defined( USE_PTHREADS) && !defined(__linux__) -/* - * Mechanism for starting a new thread suspended. - */ -typedef enum { - NEW_THREAD_MUST_REQUEST_SUSPEND, - NEW_THREAD_REQUESTED_SUSPEND, - NEW_THREAD_SUSPENDED -} new_thr_state_t; - -typedef struct { - pthread_mutex_t m; - pthread_cond_t c; - new_thr_state_t state; -} new_thr_cond_t; -#endif /* USE_PTHREADS */ - -/* - * Machine dependent info in a sys_thread_t - */ -struct sys_thread { - /* - * Fields below this point may change on a per-architecture basis - * depending on how much work is needed to present the sysThread - * model on any given thread implementation. - */ - mutex_t mutex; /* per thread lock to protect thread fields */ - thread_t sys_thread; /* The native thread id */ - struct sys_thread *next; /* Pointer to next thread in the */ - /* queue of all threads. */ - thread_state_t state; - - /* Thread status flags */ - unsigned int primordial_thread:1; - unsigned int system_thread:1; - unsigned int cpending_suspend:1; -#ifdef __linux__ - unsigned int pending_interrupt:1; -#endif - unsigned int interrupted:1; - unsigned int onproc:1; /* set if thread is on an LWP */ - unsigned int :0; - -#ifdef BOUND_THREADS - lwpid_t lwpid; -#endif - -#ifdef __linux__ - void *sp; -#else - unsigned long sp; /* sp at time of last (native) thread switch */ -#endif - void * stack_bottom; /* The real bottom (high address) of stack */ - void * stack_top; /* should be equal to stack_bottom - stack_size */ - long stack_size; /* The stack size for a native thread */ - - long regs[N_TRACED_REGS]; /* stores registers as GC roots. */ - - /* Monitor specific. - - Every monitor keeps track of the number of times it is - entered. When that count goes to 0, the monitor can be - freed up. But each thread has its own entry count on a - particular monitor, because multiple threads can be using a - single monitor (as one does a wait, another enters, etc.). - Each thread can only be waiting in exactly one monitor. - That monitor waited on is saved in mon_wait, and the value - of the monitor's entry_count when the wait was performed is - saved in monitor_entry_count. That is restored into the - monitor when this waiting thread is notified. */ - - long monitor_entry_count; /* For recursive monitor entry */ - struct sys_mon *mon_wait; /* CONDVAR_WAIT'ing */ - - struct sys_mon *mon_enter; /* blocked waiting to enter */ - - void (*start_proc)(void *); - void *start_parm; - int lwp_id; - long last_sum; - - struct sys_thread *prevBlocked; /* Used by nonblocking close semantics */ - struct sys_thread *nextBlocked; -#ifdef USE_PTHREADS - int suspend_count; -#ifdef __linux__ - sem_t sem_suspended; - sem_t sem_ready_to_suspend; - sem_t sem_selfsuspend; - int selfsuspended; -#endif -#ifdef USE_MUTEX_HANDSHAKE - new_thr_cond_t ntcond; -#else - sem_t sem; -#endif /* USE_MUTEX_HANDSHAKE */ -#endif /* USE_PTHREADS */ -}; - -#define SYS_THREAD_NULL ((sys_thread_t *) 0) - -/* - * following macro copied from sys/signal.h since inside #ifdef _KERNEL there. - */ -#ifndef sigmask -#define sigmask(n) ((unsigned int)1 << (((n) - 1) & (32 - 1))) -#endif - -#ifdef __linux__ -extern thread_key_t intrJmpbufkey; -#else -extern thread_key_t sigusr1Jmpbufkey; -extern sigset_t sigusr1Mask; -#endif - -extern sys_mon_t *_sys_queue_lock; - -#define SYS_QUEUE_LOCK(self) sysMonitorEnter(self, _sys_queue_lock) -#define SYS_QUEUE_LOCKED(self) sysMonitorEntered(self, _sys_queue_lock) -#define SYS_QUEUE_UNLOCK(self) sysMonitorExit(self, _sys_queue_lock) -#define SYS_QUEUE_NOTIFYALL(self) sysMonitorNotifyAll(self, _sys_queue_lock) -#define SYS_QUEUE_WAIT(self) sysMonitorWait(self, _sys_queue_lock, \ - SYS_TIMEOUT_INFINITY) - -extern void setFPMode(void); - -extern sys_thread_t *ThreadQueue; - -extern int ActiveThreadCount; /* All threads */ - -#endif /* !_JAVASOFT_SOLARIS_THREADS_MD_H_ */ diff --git a/src/solaris/hpi/native_threads/src/condvar_md.c b/src/solaris/hpi/native_threads/src/condvar_md.c deleted file mode 100644 index 60b3fd75c724f605be65b7bc7fb7973c3a445b78..0000000000000000000000000000000000000000 --- a/src/solaris/hpi/native_threads/src/condvar_md.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Copyright (c) 1994, 2000, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Condition variable HPI implementation for Solaris - */ - -#include -#include -#include -#include -#include - -#include "hpi_impl.h" - -#include "condvar_md.h" -#include "mutex_md.h" -#include "threads_md.h" - -int -condvarInit(condvar_t *condvar) -{ - int err; - -#ifdef USE_PTHREADS - err = pthread_cond_init(&condvar->cond, NULL); -#else - err = cond_init(&condvar->cond, USYNC_THREAD, 0 /* ignored */); -#endif - condvar->counter = 0; - return (err == 0 ? SYS_OK : SYS_ERR); -} - -int -condvarDestroy(condvar_t *condvar) -{ - int err; - -#ifdef __linux__ - err = pthread_cond_destroy((cond_t *) &condvar->cond); -#else - err = cond_destroy((cond_t *) condvar); -#endif - return (err == 0 ? SYS_OK : SYS_ERR); -} - -int -condvarWait(condvar_t *condvar, mutex_t *mutex, thread_state_t wtype) -{ - sigjmp_buf jmpbuf; - int err; - - sys_thread_t *self = sysThreadSelf(); - /* - * There is no threads interface to get a thread's state. So, instead, - * we use this hack so that the debugger agent can get at this thread's - * state. Of course, this is not very reliable, but when a thread goes - * to sleep, it *will* be reported as sleeping. During the transition - * from running to sleep, it may be incorrectly reported, since the - * setting of the state here is not atomic with the voluntary sleep. - * The better fix is to extend the Solaris threads interface and have - * the debugger agent call this interface OR to use libthread_db for - * intra-process state reporting. - * - * Now, condition variables are used either for waiting to enter a - * monitor (MONITOR_WAIT) or to execute a "wait()" method when already - * holding a monitor (CONDVAR_WAIT). So, when condvarWait() is called - * it could be to wait for a monitor or for a condition within a - * monitor. This is indicated by the "wtype" argument to condvarWait(). - * This type is set in the thread state before going to sleep. - */ - self->state = wtype; - -#ifdef __linux__ - /* - * Register our intrHandler as a cleanup handler. If we get - * interrupted (i.e. canceled), we longjmp out of this handler. - */ - pthread_cleanup_push(intrHandler, NULL); - if (setjmp(jmpbuf) == 0) { - /* - * Set the jmp buf and enable cancellation. - */ - thr_setspecific(intrJmpbufkey, &jmpbuf); - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); - - /* - * Note: pthread_cond_wait is _not_ interruptible on Linux - */ -#else - thr_setspecific(sigusr1Jmpbufkey, &jmpbuf); - if (sigsetjmp(jmpbuf, 1) == 0) { - sigset_t osigset; - - thr_sigsetmask(SIG_UNBLOCK, &sigusr1Mask, &osigset); -again: -#endif - err = cond_wait((cond_t *) condvar, (mutex_t *) mutex); - switch(err) { - case 0: - err = SYS_OK; - break; -#ifndef __linux__ - case EINTR: /* Signals other than USR1 were received. */ - goto again; -#endif - default: - err = SYS_ERR; - } -#ifdef __linux__ - /* - * Disable cancellation and clear the jump buf. - */ - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); - thr_setspecific(intrJmpbufkey, NULL); -#else - thr_sigsetmask(SIG_SETMASK, &osigset, NULL); -#endif - } else { - /* - * we've received a SIGUSR1 to interrupt our wait. We just return - * and something above use notices the change. - * clear the jump buf just to be paranoid. - */ -#ifndef __linux__ - thr_setspecific(sigusr1Jmpbufkey, NULL); -#endif - err = SYS_INTRPT; - } -#ifdef __linux__ - pthread_cleanup_pop(0); -#endif - /* - * After having woken up, change the thread state to RUNNABLE, since - * it is now runnable. - */ - self->state = RUNNABLE; - - return err; -} - -/* - * Returns 0 if condition variable became true before timeout expired. - * Returns 1 if timeout expired first. - * Returns <0 if wait fails for any other reason. - */ -int -condvarTimedWait(condvar_t *condvar, mutex_t *mutex, - jlong millis, thread_state_t wtype) -{ -#ifdef __linux__ - jmp_buf jmpbuf; -#else - sigjmp_buf jmpbuf; -#endif - int err; - struct timespec timeout; - sys_thread_t *self; - jlong end_time; - - if (millis < 0) - return SYS_ERR; - - if (millis > (jlong)INT_MAX) { - return condvarWait(condvar, mutex, wtype); - } - - end_time = sysTimeMillis() + millis; - - self = sysThreadSelf(); - self->state = wtype; - -#ifdef __linux__ - /* - * Register our intrHandler as a cleanup handler. If we get - * interrupted (i.e. canceled), we longjmp out of this handler. - */ - pthread_cleanup_push(intrHandler, NULL); - if (setjmp(jmpbuf) == 0) { - /* - * Set the jmp buf and enable cancellation. - */ - thr_setspecific(intrJmpbufkey, &jmpbuf); - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); - - /* - * Calculate an absolute timeout value. - */ - timeout.tv_sec = end_time / 1000; - timeout.tv_nsec = (end_time % 1000) * 1000000; - - again: -#else - thr_setspecific(sigusr1Jmpbufkey, &jmpbuf); - if (sigsetjmp(jmpbuf, 1) == 0) { - sigset_t osigset; - - thr_sigsetmask(SIG_UNBLOCK, &sigusr1Mask, &osigset); - - again: - timeout.tv_sec = end_time / 1000; - timeout.tv_nsec = (end_time % 1000) * 1000000; -#endif - err = cond_timedwait((cond_t *)condvar, (mutex_t *)mutex, &timeout); - switch(err) { - case 0: - err = SYS_OK; - break; - case EINTR: /* Signals other than USR1 were received. */ - if (sysTimeMillis() < end_time) { - goto again; - } - /*FALLTHRU*/ -#ifdef USE_PTHREADS - case ETIMEDOUT: -#else - case ETIME: -#endif - err = SYS_TIMEOUT; - break; - default: - err = SYS_ERR; - } -#ifdef __linux__ - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); - thr_setspecific(intrJmpbufkey, NULL); -#else - thr_sigsetmask(SIG_SETMASK, &osigset, NULL); -#endif - } else { - /* - * we've received a SIGUSR1 to interrupt our wait. We just return - * and something above use notices the change. - * clear the jump buf just to be paranoid. - */ -#ifndef __linux__ - thr_setspecific(sigusr1Jmpbufkey, NULL); -#endif - err = SYS_INTRPT; - } -#ifdef __linux__ - /* Remove intrHandler without calling it. */ - pthread_cleanup_pop(0); - - sysAssert(pthread_mutex_trylock(mutex) == EBUSY); - - /* - * After having woken up, change the thread state to RUNNABLE, since - * it is now runnable. - */ -#endif - self->state = RUNNABLE; - return err; -} - -int -condvarSignal(condvar_t *condvar) -{ - int err; - - err = cond_signal((cond_t *) condvar); - condvar->counter++; - return (err == 0 ? SYS_OK : SYS_ERR); -} - -int -condvarBroadcast(condvar_t *condvar) -{ - int err; - - err = cond_broadcast((cond_t *) condvar); - condvar->counter++; - return (err == 0 ? SYS_OK : SYS_ERR); -} diff --git a/src/solaris/hpi/native_threads/src/interrupt_md.c b/src/solaris/hpi/native_threads/src/interrupt_md.c deleted file mode 100644 index eea1c977aea422137d601f7780892b9a1ed3e578..0000000000000000000000000000000000000000 --- a/src/solaris/hpi/native_threads/src/interrupt_md.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright (c) 1994, 2006, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Solaris 2.X dependant interrupt handling code. - */ - -/* - * Header files. - */ -#include -#include -#include -#include -#include - -#include "hpi_impl.h" - -#include "mutex_md.h" -#include "condvar_md.h" -#include "monitor_md.h" -#include "threads_md.h" -#include "interrupt.h" - -static int pending_signals[N_INTERRUPTS]; - -/* Stubs used from interrupt.c: they are nontrivial on Green */ -void intrLock() {} -void intrUnlock() {} -#ifdef __linux__ -extern int sr_sigsusp; -extern int sr_sigresu; -#endif - -/* We need a special monitor implementation for signals because - * signal handlers are not necessarily called in a Java thread. - */ -struct { - thread_t owner; - unsigned int count; - mutex_t mutex; - condvar_t condvar; -} userSigMon; - -static void sigMonitorInit() -{ - userSigMon.owner = 0; - userSigMon.count = 0; - mutexInit(&userSigMon.mutex); - condvarInit(&userSigMon.condvar); -} - -static void sigMonitorEnter() -{ - thread_t self = thr_self(); - - if (userSigMon.owner == self) { - userSigMon.count++; - } else { - mutex_lock(&userSigMon.mutex); - userSigMon.owner = self; - userSigMon.count = 1; - } -} - -static void sigMonitorExit() -{ - thread_t self = thr_self(); - - sysAssert(userSigMon.owner == self); - sysAssert(userSigMon.count > 0); - if (--userSigMon.count == 0) { - userSigMon.owner = 0; - mutex_unlock(&userSigMon.mutex); - } -} - -static void sigMonitorNotify() -{ - thread_t self = thr_self(); - - sysAssert(userSigMon.owner == self); - sysAssert(userSigMon.count > 0); - condvarSignal(&userSigMon.condvar); -} - -static void sigMonitorWait() -{ - thread_t self = thr_self(); - - unsigned int saved_count = userSigMon.count; - - sysAssert(userSigMon.owner == self); - sysAssert(userSigMon.count > 0); - - userSigMon.count = 0; - userSigMon.owner = 0; - - condvarWait(&userSigMon.condvar, &userSigMon.mutex, CONDVAR_WAIT); - - sysAssert(userSigMon.owner == 0); - sysAssert(userSigMon.count == 0); - - userSigMon.count = saved_count; - userSigMon.owner = self; -} - -static int -my_sigignore(int sig) -{ -#ifndef HAVE_SIGIGNORE - struct sigaction action; - sigset_t set; - - action.sa_handler = SIG_IGN; - action.sa_flags = 0; - sigemptyset(&action.sa_mask); - - if (sigaction(sig, &action, (struct sigaction *)0) < 0) - return -1; - sigemptyset(&set); - if (sigaddset(&set, sig) < 0) - return -1; - return sigprocmask(SIG_UNBLOCK, &set, (sigset_t *)0); -#else - return sigignore(sig); -#endif /* HAVE_SIGIGNORE */ -} - - -/* - * intrInitMD() -- Target-specific initialization. - */ -extern void -intrInitMD() -{ - memset(pending_signals, 0, sizeof(pending_signals)); - (void)my_sigignore(SIGPIPE); - sigMonitorInit(); -} - -/*- - * intrDispatchMD() -- Turn our signal into an intrDispatch(). - */ -void -#ifdef SA_SIGINFO -intrDispatchMD(int sig, siginfo_t *info, void *uc) -#else -intrDispatchMD(int sig) -#endif /* SA_SIGINFO */ -{ - Log1(1, "signalHandlerDispatch(sig=%d)\n", sig); - - sigMonitorEnter(); -#ifdef SA_SIGINFO -#if defined(__linux__) && defined(__sparc__) - uc = (((char *)&sig) + 4 + 0x20); - info = (siginfo_t *)(((char *)uc) + 0x60); -#endif - intrDispatch(sig, info, uc); -#else - intrDispatch(sig, 0, 0); -#endif /* SA_SIGINFO */ - - sigMonitorExit(); -} - -bool_t intrInUse(int sig) -{ - /* Signals used in native threads implementation. */ -#ifdef __linux__ - return sig == SIGPIPE || sig == sr_sigsusp || sig == sr_sigresu; -#else - return sig == SIGPIPE || sig == SIGUSR1; -#endif -} - -void sysSignalNotify(int sig) -{ - sigMonitorEnter(); - pending_signals[sig]++; - sigMonitorNotify(); - sigMonitorExit(); -} - -static int lookupSignal() -{ - int i; - for (i = 0; i < N_INTERRUPTS; i++) { - if (pending_signals[i]) { - pending_signals[i]--; - return i; - } - } - return -1; -} - -int sysSignalWait() -{ - int sig; - sigMonitorEnter(); - while ((sig = lookupSignal()) == -1) { - sigMonitorWait(); - } - sigMonitorExit(); - return sig; -} diff --git a/src/solaris/hpi/native_threads/src/monitor_md.c b/src/solaris/hpi/native_threads/src/monitor_md.c deleted file mode 100644 index 577888b5141cf8d4e2251b57997650ecf581cc7d..0000000000000000000000000000000000000000 --- a/src/solaris/hpi/native_threads/src/monitor_md.c +++ /dev/null @@ -1,365 +0,0 @@ -/* - * Copyright (c) 1994, 1998, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Monitor implementation for Native Solaris threads - * - * Java Monitors are implemented using one solaris mutex and two - * condition variables. Because solaris mutex is not re-entrant we - * cannot simply have a monitor map to a mutex as re-entering a monitor - * would deadlock an application. - * - * Monitor is implemented using: - * mutex_t mutex; - * condvar_t cv_monitor; - * condvar_t cv_waiters; - * - * mutex protects the monitor state. - * cv_monitor is the condtion variable used along with mutex for - * supporting wait and notify on the monitor. - * cv_waiters is used for all the threads waiting to acquire the monitor - * lock. - * - * All of the sysMonitorXXX() functions that are passed a sys_mon_t - * assume that they get something nonnull, and only check when debugging. - */ - -#include "hpi_impl.h" - -#include "threads_md.h" -#include "monitor_md.h" - -#include -#include - -static mutex_t contention_count_mutex; - -void initializeContentionCountMutex() -{ - mutexInit(&contention_count_mutex); -} - -/* - * Operations on monitors - */ -/* - * Return the size of the lib-dependent portion of monitors. This - * is done this way so that monitors can be all of one piece, - * without paying the penalty of an extra level of indirection on - * each sys_mon reference. This is not how it is done for threads - * and it might be a good idea to use a pointer the same way that - * threads do. - */ -size_t -sysMonitorSizeof() -{ - return sizeof(struct sys_mon); -} - -int -sysMonitorInit(sys_mon_t *mid) -{ - int ret; - - sysAssert(mid != SYS_MID_NULL); - ret = mutexInit(&mid->mutex); - ret = (ret == SYS_OK ? condvarInit(&mid->cv_monitor) : ret); - - mid->entry_count = 0; - mid->monitor_owner = SYS_THREAD_NULL; - mid->contention_count = 0; - INIT_MONITOR_WAIT_QUEUE( mid->mwait_queue ); - - return ret; -} - -/* - * Free any system-dependent resources held by monitors. There is - * nothing to be done for native Solaris mutexes or condition variables. - */ -int -sysMonitorDestroy(sys_mon_t *mid) -{ - sysAssert(mid != SYS_MID_NULL); - - return SYS_OK; -} - -static void -enqueue_me(monitor_waiter_t *mp, monitor_wait_queue_t *queue, - sys_thread_t *self) -{ - /* - * Order does not matter here. It is more convenient to - * enqueue ourselves at the head of the list, so we do so. - */ - mp->waiting_thread = self; - mp->next = queue->head; - mp->prev = &(queue->head); - if ( queue->head != NULL ){ - queue->head->prev = &(mp->next); - } - queue->head = mp; - queue->count++; -} - -static void -dequeue_me(monitor_waiter_t *mp, monitor_wait_queue_t *queue) -{ - queue->count--; - *(mp->prev) = mp->next; - if (mp->next != NULL ){ - mp->next->prev = mp->prev; - } - mp->next = NULL; -} - -int -sysMonitorEnter(sys_thread_t *self, sys_mon_t *mid) -{ - int err; - - sysAssert(mid != SYS_MID_NULL); - err = mutex_trylock(&mid->mutex); - if (err == 0) { /* no one owns it */ - mid->monitor_owner = self; - mid->entry_count = 1; - return SYS_OK; - } else if (err == EBUSY) { /* it's already locked */ - if (mid->monitor_owner == self) { - mid->entry_count++; - return SYS_OK; - } else { - self->mon_enter = mid; - /* block on it */ - if (profiler_on) { - VM_CALL(monitorContendedEnter)(self, mid); - mutexLock(&contention_count_mutex); - mid->contention_count++; - mutexUnlock(&contention_count_mutex); - } - mutex_lock(&mid->mutex); - mid->monitor_owner = self; - mid->entry_count = 1; - self->mon_enter = NULL; - if (profiler_on) { - mutexLock(&contention_count_mutex); - mid->contention_count--; - mutexUnlock(&contention_count_mutex); - VM_CALL(monitorContendedEntered)(self, mid); - } - return SYS_OK; - } - } else { - sysAssert(err == 0); - return SYS_ERR; - } -} - -/* - * Return true if we currently own this monitor (and threads have been - * initialized. - */ -bool_t -sysMonitorEntered(sys_thread_t *self, sys_mon_t *mid) -{ - sysAssert(mid != SYS_MID_NULL); - - /* We can only have locked monitors if threads have been initialized */ - return (mid->monitor_owner == self); -} - -int -sysMonitorExit(sys_thread_t *self, sys_mon_t *mid) -{ - sysAssert(mid != SYS_MID_NULL); - - if (mid->monitor_owner == self) { - sysAssert(mid->entry_count > 0); - if (--mid->entry_count == 0) { - mid->monitor_owner = SYS_THREAD_NULL; - if (!mid->contention_count || !profiler_on) { - mutex_unlock(&mid->mutex); - } else { - mutex_unlock(&mid->mutex); - VM_CALL(monitorContendedExit)(self, mid); - } - } - return SYS_OK; - } else { - return SYS_ERR; - } -} - -int -sysMonitorNotify(sys_thread_t *self, sys_mon_t *mid) -{ - sysAssert(mid != SYS_MID_NULL); - if (self == mid->monitor_owner) { - if (ANY_WAITING(mid->mwait_queue)) { - /* If there is someone doing a monitor wait */ - condvarSignal(&(mid->cv_monitor)); - } - return SYS_OK; - } else - return SYS_ERR; -} - -int -sysMonitorNotifyAll(sys_thread_t *self, sys_mon_t *mid) -{ - sysAssert(mid != SYS_MID_NULL); - if (self == mid->monitor_owner) { - if (ANY_WAITING(mid->mwait_queue)) { - /* If there is someone doing a monitor wait */ - condvarBroadcast(&(mid->cv_monitor)); - } - return SYS_OK; - } else - return SYS_ERR; -} - -int -sysMonitorWait(sys_thread_t *self, sys_mon_t *mid, jlong millis) -{ - int ret = SYS_OK; - monitor_waiter_t me; - sysAssert(mid != SYS_MID_NULL); - - if (self != mid->monitor_owner) { - return SYS_ERR; - } - if (sysThreadIsInterrupted(self, TRUE)) { - return SYS_INTRPT; - } - - /* Prepare to wait: drop mutex ownership */ - sysAssert(self->monitor_entry_count == 0); - sysAssert(self->mon_wait == 0); - self->mon_wait = (sys_mon_t *) mid; - self->monitor_entry_count = mid->entry_count; - mid->entry_count = 0; - mid->monitor_owner = SYS_THREAD_NULL; - - /* Add myself to the monitor waitq */ - enqueue_me(&me, &mid->mwait_queue, self); - if (millis == SYS_TIMEOUT_INFINITY) { - ret = condvarWait(&mid->cv_monitor, &mid->mutex, CONDVAR_WAIT); - } else { - ret = condvarTimedWait(&mid->cv_monitor, &mid->mutex, millis, - CONDVAR_WAIT); - } - dequeue_me(&me, &mid->mwait_queue); - - sysAssert(mid->monitor_owner == NULL); - sysAssert(mid->entry_count == 0); - mid->monitor_owner = self; - mid->entry_count = self->monitor_entry_count; - self->monitor_entry_count = 0; - self->mon_wait = 0; - - /* Did we get interrupted in mid-wait? (IS THIS THE RIGHT PLACE?) */ - if (sysThreadIsInterrupted(self, TRUE)) { - return SYS_INTRPT; - } - - return ret; -} - -static int -dumpWaitingQueue(monitor_wait_queue_t *queue, sys_thread_t **waiters, int sz) -{ - int n; - monitor_waiter_t * waiter; - if (queue == NULL || ( waiter = queue->head ) == NULL ) { - return 0; - } - for (n = 0; waiter != 0; waiter = waiter->next, n++, sz--) { - if (sz > 0) { - waiters[n] = waiter->waiting_thread; - } - } - return n; -} - -typedef struct { - sys_mon_t *mid; - sys_thread_t **waiters; - int sz; - int nwaiters; -} wait_info; - -static int -findWaitersHelper(sys_thread_t *t, void *arg) -{ - wait_info * winfo = (wait_info *) arg; - if (t->mon_enter == winfo->mid) { - if (winfo->sz > 0) { - winfo->waiters[winfo->nwaiters] = t; - } - winfo->sz--; - winfo->nwaiters++; - } - return SYS_OK; -} - -int -sysMonitorGetInfo(sys_mon_t *mid, sys_mon_info *info) -{ - wait_info winfo; - - sysAssert(mid != SYS_MID_NULL); - info->owner = mid->monitor_owner; - if (mid->monitor_owner) { - info->entry_count = mid->entry_count; - } - - winfo.mid = mid; - winfo.nwaiters = 0; - winfo.waiters = info->monitor_waiters; - winfo.sz = info->sz_monitor_waiters; - sysThreadEnumerateOver(findWaitersHelper, (void *) &winfo); - info->n_monitor_waiters = winfo.nwaiters; - - info->n_condvar_waiters = dumpWaitingQueue(&mid->mwait_queue, - info->condvar_waiters, - info->sz_condvar_waiters); - - return SYS_OK; -} - - -bool_t -sysMonitorInUse(sys_mon_t * mon) -{ - return mon->monitor_owner != 0 || - mon->mwait_queue.count != 0; -} - -sys_thread_t * -sysMonitorOwner(sys_mon_t *mon) -{ - return mon->monitor_owner; -} diff --git a/src/solaris/hpi/native_threads/src/mutex_md.c b/src/solaris/hpi/native_threads/src/mutex_md.c deleted file mode 100644 index 852dc67b0d2fb79a6dbc18c4987034e7b39da0d3..0000000000000000000000000000000000000000 --- a/src/solaris/hpi/native_threads/src/mutex_md.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 1994, 1998, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Mutex HPI implementation for Solaris - * - * Mutexes are used both by the system-independent monitor implementation and - * to implement critical regions elsewhere within the runtime. - */ - -#include - -#include "hpi_impl.h" - -#include "mutex_md.h" -#include "threads_md.h" - -/* - * Return true of the mutex in question is already locked. note: - * this does not tell if the mutex is already locked by *this* - * thread, only that is is locked by *some* thread. - */ -bool_t -mutexLocked(mutex_t *mutex) -{ - if (mutex_trylock(mutex) == 0) { - mutex_unlock(mutex); - return FALSE; - } - return TRUE; -} diff --git a/src/solaris/hpi/native_threads/src/sys_api_td.c b/src/solaris/hpi/native_threads/src/sys_api_td.c deleted file mode 100644 index 54da289e1d236cf927f373309b661abb2be12cc1..0000000000000000000000000000000000000000 --- a/src/solaris/hpi/native_threads/src/sys_api_td.c +++ /dev/null @@ -1,599 +0,0 @@ -/* - * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Solaris-dependent I/O Note: Routines here are just place holders - - * eventually we need to put in a solution that involves using - * setjmp/longjmp to avoid io races. Look at green_threads/io_md.c for - * more detailed comments on the architechture of the io modules. - */ -#include -#include -#include - -#ifdef HAVE_FILIOH -#include -#else -#include -#endif - -#include -#include -#include -#ifndef USE_SELECT -#include -#endif - -#include "hpi_impl.h" - -#include "threads_md.h" -#include "io_md.h" -#include "largefile.h" -#include "mutex_md.h" - -#if defined(__solaris__) && defined(NO_INTERRUPTIBLE_IO) -#error If there was no policy change, this could be a makefile error. -#endif - -#ifdef NO_INTERRUPTIBLE_IO -#undef CLOSEIO -#else -#define CLOSEIO -#endif /* NO_INTERRUPTIBLE_IO */ - -/* Get typedef for rlim_t */ -#include - -#ifdef CLOSEIO - -/* - * Structure for file control block, used by closable IO. - * We should NOT add more field into the data structure. - * Otherwise, the sysRead() will only work with sysOpen, - * and may NOT work with a fd return by open() - */ -typedef struct -{ - mutex_t lock; /* lock against the entry */ - sys_thread_t* list; /* blocking list on the fd */ -} file_t; - -/* - * Global data structure for interruptable io. - * It must be initialized before any IO access. - */ -static file_t * fd_table = 0; -static int fd_limit = 0; - -/* - * Initialize global data structure for non-blocking - * close semantics for Solaris 2.6 and ealier. - */ -int InitializeIO(rlim_t limit) -{ - int i; - - fd_limit = (int) limit; - - fd_table = (file_t *) sysCalloc(fd_limit, sizeof(file_t)); - if (fd_table == 0) { - return SYS_ERR; - } - - for (i = 0; i < fd_limit; i++) { - mutexInit(&(fd_table[i].lock)); - } - - return SYS_OK; -} - -/* - * Cleanup the data structure allocated as above. - * For JDK 1.2, this function is not called ... - */ -void FinalizeIO() { - int i; - for (i = 0; i < fd_limit; i++) { - mutexDestroy(&fd_table[i].lock); - } - sysFree(fd_table); - fd_table = 0; -} - -/* - * Non-blocking close semantics on Solaris native thread. - */ -int sysClose(int fd) -{ - int ret; - - /* Check if it is valid fd. */ - if (fd >= 0 && fd < fd_limit) { - file_t* file = &fd_table[fd]; - sys_thread_t *thread; - sys_thread_t *next; - - /* Lock the corresponding fd. */ - mutexLock(&file->lock); - - /* Read the blocking list. */ - thread = file->list; - - /* Iterates the list and interrupt every thread in there. */ - while (thread) { - /* This is the classic double-linked list operation. */ - if (thread->nextBlocked != thread) { - next = thread->nextBlocked; - - next->prevBlocked = thread->prevBlocked; - thread->prevBlocked->nextBlocked = next; - } else { - next = 0; - } - - thread->nextBlocked = 0; - thread->prevBlocked = 0; - - /* - * Use current interruptable IO mechanism to - * implement non-blocking closable IO. - */ - sysThreadInterrupt(thread); - - thread = next; - } - - file->list = 0; - - ret = close(fd); - - mutexUnlock(&file->lock); - } else { - /* It is not a valid fd. */ - errno = EBADF; - ret = SYS_ERR; - } - - return ret; -} - -/* - * Called before entering blocking IO. Enqueue the current - * thread to the fd blocking list. Need fd lock. - */ -static void BeginIO(sys_thread_t* self, file_t* file) { - mutexLock(&file->lock); - - if (!file->list) { - file->list = self->nextBlocked = self->prevBlocked = self; - } else { - sys_thread_t* head = file->list; - - self->prevBlocked = head->prevBlocked; - self->nextBlocked = head; - head->prevBlocked->nextBlocked = self; - head->prevBlocked = self; - } - mutexUnlock(&file->lock); -} - -/* - * Called after finishing blocking IO. Dequeue the current - * thread from the blocking list. Note: It may be waken up - * by thread interrupt or fd close operation. - */ -static ssize_t EndIO(sys_thread_t* self, file_t* file, ssize_t ret) { - mutexLock(&file->lock); - - /* - * Dequeue the current thread. It is classic double - * linked list operation. - */ -#ifdef __linux__ - if (!sysThreadIsInterrupted(self, 1) && self->prevBlocked) { -#else - if (self->prevBlocked) { -#endif - if (self->nextBlocked != self) { - self->prevBlocked->nextBlocked = self->nextBlocked; - self->nextBlocked->prevBlocked = self->prevBlocked; - file->list = self->nextBlocked; - } else { - file->list = 0; - } - self->nextBlocked = 0; - self->prevBlocked = 0; - } else { -#ifdef __linux__ - if (self->nextBlocked && self->prevBlocked) { - if (self->nextBlocked != self) { - self->prevBlocked->nextBlocked = self->nextBlocked; - self->nextBlocked->prevBlocked = self->prevBlocked; - file->list = self->nextBlocked; - } else { - file->list = 0; - } - } - self->nextBlocked = 0; - self->prevBlocked = 0; -#endif - /* file got closed during blocking call */ - errno = EBADF; - ret = SYS_ERR; - } - - mutexUnlock(&file->lock); - - return ret; -} - -/* - * The following is a big macro used to implement the closable IO. - * Note: It is also used by interruptable IO. If later we need to - * deprecate interruptable IO, all we need to change the return - * value and errno to EBADF instead of EINTR. The high level - * routine will interpret it as IOException instead of - * InterruptedIOException. No other change is needed. - * The underlying mechanism is using the SIGUSR1 signal to wake up the - * blocking thread. This may cause severe conflicts with any other - * libraries that also use SIGUSR1. - */ -#ifdef __linux__ -#define INTERRUPT_IO(cmd) \ -{\ - ssize_t ret = 0;\ - file_t* file;\ - sys_thread_t* self = sysThreadSelf();\ -\ - if (fd < 0 || fd >= fd_limit) {\ - errno = EBADF;\ - return SYS_ERR;\ - }\ -\ - file = &fd_table[fd];\ - BeginIO(self, file);\ -\ - {\ - jmp_buf jmpbuf;\ -\ - /*\ - * Register our intrHandler as a cleanup handler. If we get\ - * interrupted (i.e. canceled), we longjmp out of this handler.\ - */\ - pthread_cleanup_push(intrHandler, NULL);\ - if (setjmp(jmpbuf) == 0) {\ - thr_setspecific(intrJmpbufkey, &jmpbuf);\ - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);\ - ret = cmd;\ - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);\ - thr_setspecific(intrJmpbufkey, NULL);\ - } else {\ - /* [jk] should/can we call sysThreadIsInterrupted(self, 1) here */ - - self->interrupted = FALSE;\ - errno = EINTR;\ - ret = SYS_INTRPT;\ - }\ - /* Remove intrHandler without calling it. */\ - pthread_cleanup_pop(0);\ - }\ -\ - return EndIO(self, file, ret);\ -} -#else -#define INTERRUPT_IO(cmd) \ -{\ - int ret = 0;\ - file_t* file;\ - sys_thread_t* self = sysThreadSelf();\ -\ - if (fd < 0 || fd >= fd_limit) {\ - errno = EBADF;\ - return SYS_ERR;\ - }\ -\ - file = &fd_table[fd];\ - BeginIO(self, file);\ -\ - {\ - sigjmp_buf jmpbuf;\ - sigset_t omask;\ -\ - thr_setspecific(sigusr1Jmpbufkey, &jmpbuf);\ - if (sigsetjmp(jmpbuf, 1) == 0) {\ - thr_sigsetmask(SIG_UNBLOCK, &sigusr1Mask, &omask);\ - ret = cmd;\ - thr_sigsetmask(SIG_SETMASK, &omask, NULL);\ - } else {\ - sysThreadIsInterrupted(self, TRUE);\ - errno = EINTR;\ - ret = SYS_INTRPT;\ - }\ - }\ -\ - return EndIO(self, file, ret);\ -} -#endif - -#else /* CLOSEIO */ - -#define INTERRUPT_IO(cmd) \ - return cmd; - -int sysClose(int fd) { - return close(fd); -} - -int InitializeIO(rlim_t limit) -{ - return SYS_OK; -} -#endif /* CLOSEIO */ - -/* - * sys API for I/O - */ - -size_t -sysRead(int fd, void *buf, unsigned int nBytes) { - INTERRUPT_IO(read(fd, buf, nBytes)) -} - -size_t -sysWrite(int fd, const void *buf, unsigned int nBytes) { - INTERRUPT_IO(write(fd, buf, nBytes)) -} - -int -sysSocket(int domain, int type, int protocol) { - return socket(domain, type, protocol); -} - -ssize_t -sysRecv(int fd, char *buf, int nBytes, int flags) { - INTERRUPT_IO(recv(fd, buf, nBytes, flags)) -} - -ssize_t -sysSend(int fd, char *buf, int nBytes, int flags) { - INTERRUPT_IO(send(fd, buf, nBytes, flags)) -} -/* -int -sysClose(int fd) { - INTERRUPT_IO(close(fd)) -} -*/ -jlong -sysSeek(int fd, jlong offset, int whence) { - return lseek64_w(fd, offset, whence); -} - -int -sysSetLength(int fd, jlong length) { - return ftruncate64_w(fd, length); -} - -int -sysSync(int fd) { - /* - * XXX: Is fsync() interruptible by the interrupt method? - * Is so, add the TSD, sigsetjmp()/longjmp() code here. - * - * This probably shouldn't be throwing an error and should - * be a macro. - */ - int ret; - if ((ret = fsync(fd)) == -1) { - } - return ret; -} - -int -sysAvailable(int fd, jlong *pbytes) { - jlong cur, end; - int mode; - - if (sysFfileMode(fd, &mode) >= 0) { - if (S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) { - /* - * XXX: is the following call interruptible? If so, this might - * need to go through the INTERRUPT_IO() wrapper as for other - * blocking, interruptible calls in this file. - */ - int n; - if (ioctl(fd, FIONREAD, &n) >= 0) { - *pbytes = n; - return 1; - } - } - } - if ((cur = lseek64_w(fd, 0L, SEEK_CUR)) == -1) { - return 0; - } else if ((end = lseek64_w(fd, 0L, SEEK_END)) == -1) { - return 0; - } else if (lseek64_w(fd, cur, SEEK_SET) == -1) { - return 0; - } - *pbytes = end - cur; - return 1; -} - -/* IO routines that take in a FD object */ - -int -sysTimeout(int fd, long timeout) { -#ifndef USE_SELECT - struct pollfd pfd; - -#ifdef __linux__ - jlong end_time = sysTimeMillis() + (jlong) timeout; - volatile jlong to = (jlong) timeout; -#endif - - pfd.fd = fd; - pfd.events = POLLIN; - -#ifdef __linux__ - INTERRUPT_IO(__extension__ ({ - int __result; - do { - pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); - __result = poll(&pfd, 1, ((int)to)); - pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); - } while (__result == -1 && errno == EINTR && - (to = end_time - sysTimeMillis()) > 0 && - ((pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) == 0)); - if (pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) { - __result = -1; - errno = EBADF; - } - (__result == -1 && errno == EINTR) ? 0 : __result; - })) -#else - INTERRUPT_IO(poll(&pfd, 1, (int)timeout)) -#endif -#else - fd_set tbl; - struct timeval t; - - t.tv_sec = timeout / 1000; - t.tv_usec = (timeout % 1000) * 1000; - - FD_ZERO(&tbl); - FD_SET(fd, &tbl); - -#ifdef __linux__ - INTERRUPT_IO(TEMP_FAILURE_RETRY(select(fd + 1, &tbl, 0, 0, &t))) -#else - INTERRUPT_IO(select(fd + 1, &tbl, 0, 0, &t)) -#endif -#endif -} - - -/* - * sys API for networking - */ - -long -sysSocketAvailable(int fd, jint *pbytes) { - long ret = 1; - /* - * An ILP64 port of this code should pass the address of a local int - * to the ioctl and then convert that to jint with any error handling - * required for overflows, if overflow is possible. - */ - - /* - * XXX: is the following call interruptible? If so, this might - * need to go through the INTERRUPT_IO() wrapper as for other - * blocking, interruptible calls in this file. - */ - if (fd < 0 || ioctl(fd, FIONREAD, pbytes) < 0) { - ret = 0; - } - return ret; -} - -int -sysListen(int fd, int count) { - return listen(fd, count); -} - -int -sysConnect(int fd, struct sockaddr *addr, int size) { - INTERRUPT_IO(connect(fd, addr, size)) -} - -int -sysBind(int fd, struct sockaddr *addr, int size) { - INTERRUPT_IO(bind(fd, addr, size)) -} - -int -sysAccept(int fd, struct sockaddr *him, int *len) { - INTERRUPT_IO(accept(fd, him, (uint *)len)) -} - -int -sysGetSockName(int fd, struct sockaddr *him, int *len) { - return getsockname(fd, him, (uint *)len); -} - -int -sysSocketClose(int fd) { - return sysClose(fd); -} - -int -sysSocketShutdown(int fd, int howto) { - return shutdown(fd, howto); -} - -int -sysGetSockOpt(int fd, int level, int optname, char *optval, int *optlen) { - return getsockopt(fd, level, optname, optval, optlen); -} - -int -sysSetSockOpt(int fd, int level, int optname, const char *optval, int optlen) { - return setsockopt(fd, level, optname, optval, optlen); -} - -int -sysGetHostName(char *hostname, int namelen) { - return gethostname(hostname, namelen); -} - -struct hostent * -sysGetHostByAddr(const char *hostname, int len, int type) { - return gethostbyaddr(hostname, len, type); -} - -struct hostent * -sysGetHostByName(char *hostname) { - return gethostbyname(hostname); -} - -struct protoent * -sysGetProtoByName(char* name) { - return getprotobyname(name); -} - -/* - * Routines to do datagrams - */ -ssize_t -sysSendTo(int fd, char *buf, int len, - int flags, struct sockaddr *to, int tolen) { - INTERRUPT_IO(sendto(fd, buf, len, flags, to, tolen)) -} - -ssize_t -sysRecvFrom(int fd, char *buf, int nBytes, - int flags, struct sockaddr *from, int *fromlen) { - INTERRUPT_IO(recvfrom(fd, buf, nBytes, flags, from, (uint *)fromlen)) -} diff --git a/src/solaris/hpi/native_threads/src/threads_linux.c b/src/solaris/hpi/native_threads/src/threads_linux.c deleted file mode 100644 index dddc2cc8b52116fbefe5b6a67990ca7f8ceb4b2a..0000000000000000000000000000000000000000 --- a/src/solaris/hpi/native_threads/src/threads_linux.c +++ /dev/null @@ -1,411 +0,0 @@ -/* - * Copyright (c) 1999, 2000, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Implementation of notposix.h on Linux. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "hpi_impl.h" -#include "monitor_md.h" -#include "threads_md.h" -#include "np.h" - -#undef LOG_THREADS - -/* Global lock used when calling np_suspend and np_resume */ -static pthread_mutex_t sr_lock; - -/* Semaphore used to acknowledge when the handler has received HANDLER_SIG */ -static sem_t sr_sem; - -/* The tid of the thread being suspended/resumed */ -static sys_thread_t *sr_tid; - -int sr_sigsusp; -int sr_sigresu; - -static void prtsigset(char *s, sigset_t *set) -{ - int sig; - dprintf(2, "%s:", s); - for (sig = 1; sig < _NSIG; sig++) { - if (sigismember(set, sig)) { - dprintf(2, " %d", sig); - } - } - dprintf(2, "\n"); -} - -/* - * Handler function invoked when a thread's execution is suspended - * We have to be careful that only async-safe functions are - * called here. I'm not even sure if calling sysThreadSelf is safe so - * we temporarily stash SP in a global variable instead. - */ -static void -#ifdef SA_SIGINFO -susp_handler(int sig, siginfo_t* info, void* arg) -#else -susp_handler(int sig) -#endif -{ - sys_thread_t *tid = sr_tid; - sigset_t set; - /* Save the current SP */ - tid->sp = &tid; - sem_post(&sr_sem); - sigfillset(&set); - sigdelset(&set,(sr_sigresu)); - /* block until we receive resume signal. */ - sigsuspend(&set); -} - -static void -#ifdef SA_SIGINFO -resu_handler(int sig, siginfo_t* info, void* arg) -#else -resu_handler(int sig) -#endif -{ - return; -} - -/* - * Initialize signal handlers for suspend and resume}. - */ -int -np_initialize() -{ - struct sigaction act; - char *s; - int err; - - /* Signal numbers used to suspend and resume */ -#if __GLIBC__ == 2 && __GLIBC_MINOR__ == 0 -#ifdef SIGUNUSED - sr_sigsusp = SIGUNUSED; -#else - sr_sigsusp = SIGLOST; -#endif -#ifdef SIGPWR - sr_sigresu = SIGPWR; -#else - sr_sigresu = SIGXFSZ; -#endif -#else - /* use real time signals */ - /* currently __SIGRTMIN, +1, +2 are all used by LinuxThreads */ - sr_sigsusp = SIGRTMIN + 3; - sr_sigresu = SIGRTMIN + 4; -#endif - - /* Set up signal handler for suspend and resume */ -#if defined(SA_SIGINFO) && !defined(__sparc__) - act.sa_handler = 0; - act.sa_sigaction = susp_handler; -#else - act.sa_handler = (__sighandler_t) susp_handler; -#endif -#ifdef SA_SIGINFO - act.sa_flags = SA_RESTART | SA_SIGINFO; -#else - act.sa_flags = SA_RESTART; -#endif - sigfillset(&act.sa_mask); - if (sigaction(sr_sigsusp, &act, 0) == -1) { - return -1; - } -#if defined(SA_SIGINFO) && !defined(__sparc__) - act.sa_handler = 0; - act.sa_sigaction = resu_handler; -#else - act.sa_handler = (__sighandler_t) resu_handler; -#endif -#ifdef SA_SIGINFO - act.sa_flags = SA_SIGINFO; -#else - act.sa_flags = 0; -#endif - sigfillset(&act.sa_mask); - if (sigaction(sr_sigresu, &act, 0) == -1) { - return -1; - } - - /* Initialize semaphore used by np_{suspend/resume} */ - if (sem_init(&sr_sem, 0, 0) == -1) { - return SYS_ERR; - } - - /* Initialize mutex used by np_{suspend/resume} */ - err = mutexInit(&sr_lock); - sysAssert(err == 0); - - return SYS_OK; -} - -int -np_initial_suspend(sys_thread_t* tid) -{ - int count; - - tid->selfsuspended = (tid == sysThreadSelf()); - sysAssert(tid->selfsuspended); - - count = tid->suspend_count++; - sysAssert(count == 0); - -#ifdef LOG_THREADS - dprintf(2, - "[Initial self-suspend [tid = %ld, sys_thread = %ld]\n", - pthread_self(), tid->sys_thread); -#endif - - /* Order should not matter but doing the post first should be faster */ - sem_post(&tid->sem_suspended); - do { - sem_wait(&tid->sem_selfsuspend); - } while (tid->selfsuspended); /* paranoid */ - return 0; -} - - -int -np_suspend(sys_thread_t *tid) -{ - int count, ret = 0; - - int err = mutexLock(&sr_lock); - sysAssert(err == 0); - - tid->selfsuspended = (tid == sysThreadSelf()); - - count = tid->suspend_count++; -#ifdef LOG_THREADS - dprintf(2, "[Suspending fromtid = %ld, tid = %ld, pid = %d, count = %d]\n", - pthread_self(), tid->sys_thread, tid->lwp_id, count); -#endif - if (count == 0) { - if (tid->selfsuspended) { -#ifdef LOG_THREADS - dprintf(2, - "[Self-suspending [tid = %ld, sys_thread = %ld]\n", - pthread_self(), tid->sys_thread); -#endif - mutexUnlock(&sr_lock); - do { - sem_wait(&tid->sem_selfsuspend); - } while (tid->selfsuspended); - /* [jk] What is the correct return value here? - There was no error, but when we return the thread - has already been resumed. */ - return SYS_OK; - - } else { - sr_tid = tid; - ret = pthread_kill(tid->sys_thread, sr_sigsusp); - if (ret == 0) { - sem_wait(&sr_sem); - } -#ifdef LOG_THREADS - dprintf(2, - "[Suspended fromtid = %ld, pthread_kill(%ld, %d) = %d]\n", - pthread_self(), tid->sys_thread, sr_sigsusp, ret); -#endif - } - } - - err = mutexUnlock(&sr_lock); - sysAssert(err == 0); - - return ret == 0 ? SYS_OK : SYS_ERR; -} - -int -np_continue(sys_thread_t *tid) -{ - int count, ret = 0; - - int err = mutexLock(&sr_lock); - sysAssert(err == 0); - - count = --tid->suspend_count; -#ifdef LOG_THREADS - dprintf(2, "[Resuming fromtid = %ld, tid = %ld, pid = %d, count = %d]\n", - pthread_self(), tid->sys_thread, tid->lwp_id, count); -#endif - if (count == 0) { - if (tid->selfsuspended) { - tid->selfsuspended = 0; - sem_post(&tid->sem_selfsuspend); - } else { - sr_tid = tid; - ret = pthread_kill(tid->sys_thread, sr_sigresu); - } -#ifdef LOG_THREADS - dprintf(2, "[Resumed fromtid = %ld, pthread_kill(%ld, %d) = %d]\n", - pthread_self(), tid->sys_thread, sr_sigresu, ret); -#endif - } else if (count < 0) { - /* Ignore attempts to resume a thread that has not been suspended */ - tid->suspend_count = 0; - } - - err = mutexUnlock(&sr_lock); - sysAssert(err == 0); - - return ret == 0 ? SYS_OK : SYS_ERR; -} - -/* - * Get the stack base and size. - */ -int -np_stackinfo(void **addr, long *size) -{ - /* For now assume stack is 2 meg, from internals.h. */ -#define STACK_SIZE (2 * 1024 * 1024) - void *p; - char *sp = (char *)&p; /* rougly %esp */ - - *addr = (void *)(((unsigned long)sp | (STACK_SIZE-1))+1) - 1; - *size = STACK_SIZE; - - return SYS_OK; -} - -typedef unsigned long ulong_t; -#define VALID_SP(sp, bottom, top) \ - (((ulong_t)(sp)) < ((ulong_t)(bottom)) && ((ulong_t)(sp)) > ((ulong_t)(top))) - -/* - * Go into single threaded mode for GC. - */ -int -np_single() -{ - sys_thread_t *tid; - pthread_t me = pthread_self(); - int i; - -#ifdef LOG_THREADS - dprintf(2, "[Entering np_single: thread count = %d]\n", ActiveThreadCount); -#endif - /* Stop all other threads. */ - tid = ThreadQueue; - for (i = 0; i < ActiveThreadCount && tid != 0; i++) { - if ((tid->sys_thread != me) && (tid->state != SUSPENDED)) { - np_suspend(tid); - sysAssert(VALID_SP(tid->sp, tid->stack_bottom, tid->stack_top)); - tid->onproc = FALSE; /* REMIND: Might not need this */ - } - tid = tid->next; - } -#ifdef LOG_THREADS - dprintf(2, "[Leaving np_single]\n"); -#endif - return SYS_OK; -} - -/* - * Per thread initialization. - */ -void -np_initialize_thread(sys_thread_t *tid) -{ - sigset_t set; - - /* Block SIGQUIT so that it can be handled by the SIGQUIT handler thread */ - sigemptyset(&set); - sigaddset(&set, SIGQUIT); - pthread_sigmask(SIG_BLOCK, &set, 0); - /* Set process id */ - tid->lwp_id = getpid(); - tid->suspend_count = 0; - - /* Semaphore used for self-suspension */ - sem_init(&tid->sem_selfsuspend, 0, 0); - tid->selfsuspended = 0; - -#ifdef LOG_THREADS - dprintf(2, "[Init thread, tid = %ld, pid = %d, base = %p, size = %lu]\n", - pthread_self(), tid->lwp_id, tid->stack_bottom, tid->stack_size); -#endif -} - -void -np_free_thread(sys_thread_t *tid) -{ - sem_destroy(&tid->sem_selfsuspend); -} - -/* - * Recover from single threaded mode after GC. - */ -void -np_multi() -{ - int i; - sys_thread_t *tid; - pthread_t me = pthread_self(); - - tid = ThreadQueue; - for (i = 0; i < ActiveThreadCount && tid != 0; i++) { - if ((tid->sys_thread != me) && (tid->state != SUSPENDED)) { - np_continue(tid); - } - tid = tid->next; - } -} - -void -np_profiler_init(sys_thread_t *tid) -{ -} - -int -np_profiler_suspend(sys_thread_t *tid) -{ - return np_suspend(tid); -} - -int -np_profiler_continue(sys_thread_t *tid) -{ - return np_continue(tid); -} - -bool_t -np_profiler_thread_is_running(sys_thread_t *tid) -{ - return TRUE; -} diff --git a/src/solaris/hpi/native_threads/src/threads_md.c b/src/solaris/hpi/native_threads/src/threads_md.c deleted file mode 100644 index f3aab1aad1434c920fe65ecfbe6d26754190123c..0000000000000000000000000000000000000000 --- a/src/solaris/hpi/native_threads/src/threads_md.c +++ /dev/null @@ -1,1133 +0,0 @@ -/* - * Copyright (c) 1994, 2002, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Implementation of Java threads HPI on top of native Solaris threads - * - * [Sheng 1/18/97] Do not include any JVM-specific header file (such - * as interpreter.h) here! This file implements the thread-related - * APIs sys_api.h. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "hpi_impl.h" - -#include "threads_md.h" -#include "monitor_md.h" - -#include "np.h" - -extern int InitializeIO(rlim_t limit); - -#if defined(__solaris__) && !defined(SA_SIGINFO) -#error That can NOT possibly be right. -#endif - -#ifdef SA_SIGINFO -static void sigusr1Handler(int sig, siginfo_t *info, void *uc); -#else -static void sigusr1Handler(int sig); -#endif /* SA_SIGINFO */ - -static void removeFromActiveQ(sys_thread_t *p); -static void clear_onproc_flags(void); - -sys_thread_t *ThreadQueue; -int ActiveThreadCount = 0; /* All threads */ -sys_mon_t *_sys_queue_lock; - -/* This is explained in linker_md.c. */ -#ifdef __GLIBC__ -#define NEED_DL_LOCK -#endif /* __GLIBC__ */ - -#ifdef NEED_DL_LOCK -extern sys_mon_t _dl_lock; -#endif /* NEED_DL_LOCK */ - -/* - * threads_initialized simplifies the check that has to be done in - * sysThreadCheckStack(). Otherwise, before sysThreadInit() is called - * on the primordial thread, we need to handle there being no current - * thread at all, and there being one with a 0 stack_base. - */ -static int threads_initialized = 0; - -/* The tid_key is a global key to *native* thread-specific data. That is, - * each native thread has a back pointer to the Java TID associated with it. - */ -static thread_key_t tid_key = (thread_key_t) -1; - -/* - * The sigusr1Jmpbufkey is used to get at the jmp buffer to longjmp to in a - * SIGUSR1 handler - used to implement stop(). The jmp buffer - * should have been allocated off the thread's stack. - */ -#ifdef __linux__ -thread_key_t intrJmpbufkey; -static sigset_t squm = {{sigmask(SIGUSR1), 0, 0, 0}}; -#else -thread_key_t sigusr1Jmpbufkey; -sigset_t sigusr1Mask = {{sigmask(SIGUSR1), 0, 0, 0}}; -#endif - -/* - * Thread C stack overflow check - * - * sysThreadCheckStack() being a function call is unfortunate, as it - * takes stack space to do, but that is weakly accounted for by the - * previous stack redzone. In general, where we can't predict stack - * use by C, thread stack overflow checking doesn't really work. - */ - -#define STACK_REDZONE 4096 - -#ifdef __linux__ -int jdk_waitpid(pid_t pid, int* status, int options); -int fork1(void); -int jdk_sem_init(sem_t*, int, unsigned int); -int jdk_sem_post(sem_t*); -int jdk_sem_wait(sem_t*); -int jdk_pthread_sigmask(int, const sigset_t*, sigset_t*); -pid_t waitpid(pid_t, int*, int); - -int jdk_waitpid(pid_t pid, int* status, int options) { - return waitpid(pid, status, options); -} - -int fork1() { - return fork(); -} - -int -jdk_sem_init(sem_t *sem, int pshared, unsigned int value) { - return sem_init(sem, pshared, value); -} - -int -jdk_sem_post(sem_t *sem) { - return sem_post(sem); -} - -int -jdk_sem_wait(sem_t *sem) { - return sem_wait(sem); -} - -int -jdk_pthread_sigmask(int how , const sigset_t* newmask, sigset_t* oldmask) { - return pthread_sigmask(how , newmask, oldmask); -} - -#endif - -/* REMIND: port _CurrentThread changes to make process - of getting the tid more efficient */ - -int -sysThreadCheckStack() -{ - sys_thread_t *tid = sysThreadSelf(); - - /* Stacks grow toward lower addresses on Solaris... */ - if (!threads_initialized || - (char *)(tid)->stack_bottom - (char *)&(tid) + STACK_REDZONE < - tid->stack_size) { - return 1; - } else { - return 0; - } -} - -#ifndef __linux__ -static sigset_t squm = {{sigmask(SIGUSR1), 0, 0, 0}}; -#endif - - -/* - * Allocate and initialize the sys_thread_t structure for an arbitary - * native thread. - */ -int -sysThreadAlloc(sys_thread_t **tidP) -{ - int err; - sys_thread_t *tid = allocThreadBlock(); - if (tid == NULL) { - return SYS_NOMEM; - } -#ifdef __linux__ - memset((char *)tid, 0, sizeof(sys_thread_t)); -#endif - - if (profiler_on) { - np_profiler_init(tid); - } - - if (np_stackinfo(&tid->stack_bottom, &tid->stack_size) == SYS_ERR) { - return SYS_ERR; - } -#ifdef __linux__ - tid->stack_top = tid->stack_bottom - tid->stack_size; -#else - tid->stack_top = (void *)((char *)(tid->stack_bottom) - tid->stack_size); -#endif - - tid->primordial_thread = 0; -#ifdef __linux__ - tid->interrupted = tid->pending_interrupt = FALSE; -#else - tid->interrupted = FALSE; -#endif - tid->onproc = FALSE; - tid->sys_thread = thr_self(); -#ifdef __linux__ - /* - * Disable cancellation. The default cancel type is - * PTHREAD_CANCEL_DEFERRED, so if we set the cancel state to - * PTHREAD_CANCEL_ENABLE again, we'll get deferred cancellation. - */ - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); -#endif - np_initialize_thread(tid); - - /* - * For the Invocation API: - * We update the thread-specific storage before locking the - * queue because sysMonitorEnter will access sysThreadSelf. - */ - err = thr_setspecific(tid_key, tid); - /* sys_thread_t * back pointer from native */ -#ifdef __linux__ - thr_setspecific(intrJmpbufkey, NULL); /* paranoid */ -#endif - assert (err == 0); - - if (threads_initialized) - SYS_QUEUE_LOCK(sysThreadSelf()); - ActiveThreadCount++; /* Count the thread */ - tid->next = ThreadQueue; /* Chain all threads */ - ThreadQueue = tid; - if (threads_initialized) - SYS_QUEUE_UNLOCK(sysThreadSelf()); - else - threads_initialized = TRUE; - - /* - * Ensure that SIGUSR1 is masked for interruptable IO - * Signal mask inheritance ensures all child threads are masked too. - */ -#ifndef __linux__ - thr_sigsetmask(SIG_BLOCK, &squm, NULL); -#endif - - setFPMode(); - - *tidP = tid; - return SYS_OK; -} - -/* - * threadBootstrapMD() bootstraps the UNIX process running from main() - * into a first primordial thread. This thread is distinguishable because - * it uniquely has the primordial_thread flag on in its private data. - * However, so that we have to special-case it as little as possible, we - * set it up to look as closely as possible to a thread that we created. - * One difference is that its stack is *not* known to us. - */ -int -threadBootstrapMD(sys_thread_t **tidP, sys_mon_t **lockP, int nb) -{ - /* We are running out of file descriptors in fonts. As a temporary - * fix, bump up the number of open file descriptors to OPEN_MAX. - */ - struct rlimit nbr_files; - - getrlimit(RLIMIT_NOFILE, &nbr_files); - nbr_files.rlim_cur = nbr_files.rlim_max; - setrlimit(RLIMIT_NOFILE, &nbr_files); - - /* - * Use the above setting for initialize (closable) IO package. - */ - if (InitializeIO(nbr_files.rlim_cur) != SYS_OK) { - return SYS_ERR; - } - - /* Create a thread-private key for a pointer back to the sys_thread_t *. - * Note that we don't need to worry about the destructor, as that's taken - * care of elsewhere. - */ - thr_keycreate(&tid_key, NULL); - -#ifdef __linux__ - thr_keycreate(&intrJmpbufkey, NULL); -#else - thr_keycreate(&sigusr1Jmpbufkey, NULL); -#endif - -#ifndef NO_INTERRUPTIBLE_IO - { - /* initialize SIGUSR1 handler for interruptable IO */ - struct sigaction sigAct; - -#ifdef SA_SIGINFO - sigAct.sa_handler = NULL; - sigAct.sa_sigaction = sigusr1Handler; -#else - sigAct.sa_handler = sigusr1Handler; -#endif /* SA_SIGINFO */ - memset((char *)&(sigAct.sa_mask), 0, sizeof (sigset_t)); - /* we do not want the restart flag for SIGUSR1 */ - sigAct.sa_flags = 0; - sigaction(SIGUSR1, &sigAct, (struct sigaction *)0); - } -#endif /* NO_INTERRUPTIBLE_IO */ - - nReservedBytes = (nb + 7) & (~7); - if (sysThreadAlloc(tidP) < 0) { - return SYS_NOMEM; - } - - /* profiler_on may have not been setup yet. */ - np_profiler_init(*tidP); - -#ifdef NEED_DL_LOCK - VM_CALL(monitorRegister)(&_dl_lock, "Dynamic loading lock"); -#endif /* NEED_DL_LOCK */ - - /* Initialize the queue lock monitor */ - _sys_queue_lock = (sys_mon_t *)sysMalloc(sysMonitorSizeof()); - if (_sys_queue_lock == NULL) { - return SYS_ERR; - } - VM_CALL(monitorRegister)(_sys_queue_lock, "Thread queue lock"); - *lockP = _sys_queue_lock; - - (*tidP)->primordial_thread = 1; - - if (np_initialize() == SYS_ERR) { - return SYS_ERR; - } - - return SYS_OK; -} - -/* - * Access to the thread stack pointer of an arbitrary thread (for GC). - * This information should be legitimately available in Solaris 2.5. - */ -void * -sysThreadStackPointer(sys_thread_t * tid) -{ - char *thread_info; - - if (tid == sysThreadSelf()) { - /* - * doing this assigment gets around a warning about returning - * the address of a local variable - */ - void *aStackAddress = &thread_info; - return aStackAddress; - } else { - return (void *) tid->sp; - } -} - -/* - * Get the end of stack (if you step beyond (above or below depending - * on your architecture) you can die. We refer to the logical top of - * stack. - * - * NOTE! There are restrictions about when you can call this method. If - * you did a sysThreadAlloc, then you can call this method as soon as - * sysThreadAlloc returns. If you called sysThreadCreate(start_function), - * then you must call sysThreadStackTop only inside start_function and not - * as soon as sysThreadCreate returns. - */ -void * -sysThreadStackTop(sys_thread_t *tid) -{ - return tid->stack_top; -} - -long * -sysThreadRegs(sys_thread_t * tid, int *nregs) -{ - *nregs = N_TRACED_REGS; - return tid->regs; -} - -static void * -_start(void *tid_) -{ - sys_thread_t *tid = (sys_thread_t *)tid_; - - np_initialize_thread(tid); - -#ifdef __linux__ - /* - * Disable cancellation. The default cancel type is - * PTHREAD_CANCEL_DEFERRED, so if we set the cancel state to - * PTHREAD_CANCEL_ENABLE again, we'll get deferred cancellation. - */ - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); - - tid->sp = 0; - thr_setspecific(tid_key, tid); - thr_setspecific(intrJmpbufkey, NULL); /* paranoid */ - np_stackinfo(&tid->stack_bottom, &tid->stack_size); - tid->stack_top = (void *)((char *)(tid->stack_bottom) - tid->stack_size); - - /* Wait for resume signal */ - np_initial_suspend(tid); -#else -#ifdef USE_PTHREADS -#ifndef USE_MUTEX_HANDSHAKE - /* Wait for semaphore to be posted once thread has been suspended */ - sem_wait(&tid->sem); - sem_destroy(&tid->sem); -#else - /* I'm a new thread, and I must co-operate so I can be suspended. */ - pthread_mutex_lock(&tid->ntcond.m); - tid->ntcond.state = NEW_THREAD_REQUESTED_SUSPEND; - pthread_cond_signal(&tid->ntcond.c); - while (tid->ntcond.state != NEW_THREAD_SUSPENDED) - pthread_cond_wait(&tid->ntcond.c, &tid->ntcond.m); - pthread_mutex_unlock(&tid->ntcond.m); -#endif /* USE_MUTEX_HANDSHAKE */ -#endif /* USE_PTHREADS */ -#endif /* !linux */ - if (profiler_on) { - np_profiler_init(tid); - } - -#ifndef __linux__ - tid->sp = 0; - thr_setspecific(tid_key, tid); -#endif - - tid->state = RUNNABLE; - -#ifndef __linux__ - np_stackinfo(&tid->stack_bottom, &tid->stack_size); - tid->stack_top = (void *)((char *)(tid->stack_bottom) - tid->stack_size); -#endif - - setFPMode(); - tid->start_proc(tid->start_parm); -#ifdef __linux__ - /* Paranoid: We don't want to be canceled now, it would have - unpredictable consequences */ - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); -#endif - - sysThreadFree(); - thr_exit(0); - /* NOT REACHED */ - return 0; -} - -int -sysThreadCreate(sys_thread_t **tidP, long ss, void (*start)(void *), void *arg) -{ - size_t stack_size = ss; - int err; - sys_thread_t *tid = allocThreadBlock(); -#ifdef USE_PTHREADS - pthread_attr_t attr; -#endif - - if (tid == NULL) { - return SYS_NOMEM; - } - *tidP = tid; - -#ifdef __linux__ - memset((char *)tid, 0, sizeof(sys_thread_t)); -#endif - /* Install the backpointer to the Thread object */ - -#ifdef __linux__ - tid->interrupted = tid->pending_interrupt = FALSE; -#else - tid->interrupted = FALSE; -#endif - tid->onproc = FALSE; - -#ifndef __linux__ - SYS_QUEUE_LOCK(sysThreadSelf()); - ActiveThreadCount++; /* Global thread count */ - tid->next = ThreadQueue; /* Chain all threads */ - ThreadQueue = tid; - SYS_QUEUE_UNLOCK(sysThreadSelf()); -#endif - - tid->start_proc = start; - tid->start_parm = arg; -#ifdef __linux__ - tid->state = SUSPENDED; -#endif - -#ifdef __linux__ - tid->primordial_thread = 0; - - /* Semaphore used to block thread until np_suspend() is called */ - err = sem_init(&tid->sem_suspended, 0, 0); - sysAssert(err == 0); - /* Thread attributes */ - pthread_attr_init(&attr); -#ifdef _POSIX_THREAD_ATTR_STACKSIZE - pthread_attr_setstacksize(&attr, stack_size); -#endif - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - if (profiler_on) { - pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); - } - /* Create the thread. The thread will block waiting to be suspended */ - err = pthread_create(&tid->sys_thread, &attr, _start, (void *)tid); - sysAssert(err == 0); - if (err == 0) { - err = sem_wait(&tid->sem_suspended); - if (err == 0) { - sem_destroy(&tid->sem_suspended); - } - } - sysAssert(err == 0); - - SYS_QUEUE_LOCK(sysThreadSelf()); - ActiveThreadCount++; /* Global thread count */ - tid->next = ThreadQueue; /* Chain all threads */ - ThreadQueue = tid; - SYS_QUEUE_UNLOCK(sysThreadSelf()); -#else -#ifdef USE_PTHREADS - -#ifndef USE_MUTEX_HANDSHAKE - /* Semaphore used to block thread until np_suspend() is called */ - err = sem_init(&tid->sem, 0, 0); - sysAssert(err == 0); - /* Thread attributes */ -#else - /* Setup condition required to suspend the newly created thread. */ - pthread_mutex_init(&tid->ntcond.m, NULL); - pthread_cond_init(&tid->ntcond.c, NULL); - tid->ntcond.state = NEW_THREAD_MUST_REQUEST_SUSPEND; - pthread_mutex_lock(&tid->ntcond.m); -#endif /* USE_MUTEX_HANDSHAKE */ - - /* Create the new thread. */ - pthread_attr_init(&attr); -#ifdef _POSIX_THREAD_ATTR_STACKSIZE - pthread_attr_setstacksize(&attr, stack_size); -#endif - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - if (profiler_on) - pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); - err = pthread_create(&tid->sys_thread, &attr, _start, (void *)tid); - -#ifndef USE_MUTEX_HANDSHAKE - if (err == 0) { - /* Suspend the thread */ - err = np_suspend(tid); - if (err == SYS_OK) { - /* Unblock the thread now that it has been suspended */ - err = sem_post(&tid->sem); - sysAssert(err == 0); - } - } -#else - /* Wait for the newly created thread to block. */ - while (tid->ntcond.state != NEW_THREAD_REQUESTED_SUSPEND) - pthread_cond_wait(&tid->ntcond.c, &tid->ntcond.m); - - /* So it blocked. Now suspend it and _then_ get it out of the block. */ - np_suspend(tid->sys_thread); - tid->ntcond.state = NEW_THREAD_SUSPENDED; - pthread_cond_signal(&tid->ntcond.c); - pthread_mutex_unlock(&tid->ntcond.m); -#endif /* USE_MUTEX_HANDSHAKE */ - -#else - /* Create the thread */ - err = thr_create(NULL, stack_size, _start, (void *)tid, - THR_SUSPENDED|THR_DETACHED| - (profiler_on ? THR_BOUND : 0), - &tid->sys_thread); -#endif /* USE_PTHREADS */ -#endif /* !linux */ - - tid->state = SUSPENDED; - sysAssert(err != EINVAL); /* Invalid argument: shouldn't happen */ - if (err == EAGAIN) { - err = SYS_NORESOURCE; /* Will be treated as though SYS_NOMEM */ - } else if (err == ENOMEM) { - err = SYS_NOMEM; - } else { - err = SYS_OK; - } - - return err; -} - -/* - * Free a system thread block. - * Remove from the thread queue. - */ -int -sysThreadFree() -{ - sys_thread_t *tid = sysThreadSelf(); - /* - * remove ourselves from the thread queue. This must be done after - * the notify above since monitor operations aren't really safe if - * your thread isn't on the thread queue. (This isn't true of - * the sysMonitor* functions, only monitor*) - */ - SYS_QUEUE_LOCK(tid); - removeFromActiveQ(tid); - SYS_QUEUE_UNLOCK(tid); - - /* For invocation API: later sysThreadSelf() calls will return 0 */ - thr_setspecific(tid_key, 0); - -#ifdef __linux__ - np_free_thread(tid); -#endif - - freeThreadBlock(tid); - return SYS_OK; -} - -/* - * Current thread yield control - * - * Green threads originally supported forcing another thread to yield... - */ -void -sysThreadYield() -{ -#ifndef __linux__ - thr_yield(); -#endif -} - -#ifdef USE_PTHREADS -/* - * For POSIX threads, we don't want to use real-time policies SCHED_FIFO or - * SCHED_RR. That leaves SCHED_OTHER which is implementation defined. We - * assume Solaris-pthreads like behavior for SCHED_OTHER, and if it doesn't - * work on your platform, then maybe you want to do turn off thread - * priorities by setting -DMOOT_PRIORITIES. - */ -#ifndef MOOT_PRIORITIES -#define USE_SCHED_OTHER -#endif /* MOOT_PRIORITIES */ -#endif /* USE_PTHREADS */ - -/* - * Get the scheduling priority of a specified thread - */ -int -sysThreadGetPriority(sys_thread_t * tid, int *pri) -{ -#ifdef USE_PTHREADS -#ifdef USE_SCHED_OTHER - struct sched_param param; - int policy = SCHED_OTHER; - param.sched_priority = *pri; - return pthread_getschedparam(tid->sys_thread, &policy, ¶m); -#else - return 0; -#endif /* USE_SCHED_OTHER */ -#else - return thr_getprio(tid->sys_thread, pri); -#endif /* USE_PTHREADS */ -} - - -/* - * Set the scheduling priority of a specified thread - */ -int -sysThreadSetPriority(sys_thread_t * tid, int pri) -{ - int err; -#ifdef USE_PTHREADS -#ifdef USE_SCHED_OTHER - struct sched_param param; - param.sched_priority = pri; - err = pthread_setschedparam(tid->sys_thread, SCHED_OTHER, ¶m); -#else - err = 0; -#endif /* USE_SCHED_OTHER */ -#else - err = thr_setprio(tid->sys_thread, pri); -#endif /* USE_PTHREADS */ - sysAssert(err != ESRCH); /* No such thread: shouldn't happen */ - sysAssert(err != EINVAL); /* Invalid arguments: shouldn't happen */ - return SYS_OK; -} - -/* - * Suspend execution of the specified thread - */ -int -sysThreadSuspend(sys_thread_t * tid) -{ - int err1 = 0; - int err2 = 0; - sys_thread_t *self = sysThreadSelf(); - - if (tid == self) { - self->state = SUSPENDED; - } else { -#ifndef __linux__ - mutexLock(&tid->mutex); -#endif - switch(tid->state) { - case RUNNABLE: - tid->state = SUSPENDED; - break; - case CONDVAR_WAIT: - tid->state = SUSPENDED; - tid->cpending_suspend = 1; - break; - case SUSPENDED: - default: - err1 = -1; /* Thread in inconsistent state */ - break; - } -#ifndef __linux__ - mutexUnlock(&tid->mutex); -#endif - } - if (err1 == 0) { - err2 = np_suspend(tid); - } - - return ((err1 == 0 && err2 == 0) ? SYS_OK : SYS_ERR); -} - -/* - * Resume execution of the specified thread - */ -int -sysThreadResume(sys_thread_t * tid) -{ - int err1 = 0; - int err2 = 0; - -#ifndef __linux__ - mutexLock(&tid->mutex); -#endif - if (tid->cpending_suspend) { - tid->cpending_suspend = 0; - tid->state = CONDVAR_WAIT; - } else { - switch(tid->state) { - case SUSPENDED: - tid->state = RUNNABLE; - break; - case RUNNABLE: - case CONDVAR_WAIT: - default: - err1 = -1; /* Thread in inconsistent state */ - break; - } - } -#ifndef __linux__ - mutexUnlock(&tid->mutex); -#endif - if (err1 == 0) { - err2 = np_continue(tid); - } - - return ((err1 == 0 && err2 == 0) ? SYS_OK : SYS_ERR); -} - -/* - * Return the sys_thread_t * of the calling thread - */ -sys_thread_t * -sysThreadSelf() -{ -#ifdef USE_PTHREADS - return pthread_getspecific(tid_key); -#else - sys_thread_t * tid=NULL; - int err = thr_getspecific(tid_key, (void *) &tid); - - if (err == 0) { - return tid; - } - - sysAssert(tid_key == -1 || err != 0); - - return NULL; -#endif -} - -/* - * Enumerate over all threads, calling a function for each one. A - * paranoid helper function would be prepared to deal with threads - * that have not been created by Java. - */ - -int -sysThreadEnumerateOver(int (*func)(sys_thread_t *, void *), void *arg) -{ - sys_thread_t *tid; - int err = SYS_OK; - int i; - - sysAssert(SYS_QUEUE_LOCKED(sysThreadSelf())); - - tid = ThreadQueue; - for (i = 0; i < ActiveThreadCount && tid != 0; i++) { - if ((err = (*func)(tid, arg)) != SYS_OK) { - break; - } - tid = tid->next; - } - - return err; -} - -void * -sysThreadNativeID(sys_thread_t *tid) -{ - return (void *) tid->sys_thread; -} - -/* - * Remove this thread from the list of Active threads. - */ -static void -removeFromActiveQ(sys_thread_t * t) -{ - sys_thread_t *prev; - sys_thread_t *tid; - - sysAssert(SYS_QUEUE_LOCKED(sysThreadSelf())); - - ActiveThreadCount--; - - prev = 0; - tid = ThreadQueue; - while (tid) { - if (tid == t) { - if (prev) { - prev->next = tid->next; - } else { - ThreadQueue = tid->next; - } - tid->next = 0; - break; - } - prev = tid; - tid = tid->next; - } -} - -/* - * The mechanics of actually signalling an exception (in the future, - * and Alarm or Interrupt) depend upon what thread implementation you - * are using. - */ -void -sysThreadPostException(sys_thread_t *tid, void *exc) -{ - /* Thread.stop is deprecated */ - /* No longer wake up the thread if it is sleeping */ - /* thr_kill(tid->sys_thread, SIGUSR1); */ -} - -/* - * Support for (Java-level) interrupts. - */ -void -sysThreadInterrupt(sys_thread_t *tid) -{ -#ifdef __linux__ - tid->pending_interrupt = TRUE; - pthread_cancel(tid->sys_thread); -#else - mutexLock(&tid->mutex); - tid->interrupted = TRUE; - mutexUnlock(&tid->mutex); - thr_kill(tid->sys_thread, SIGUSR1); -#endif -} - -/* This doesn't need to aquire any locks */ -int -sysThreadIsInterrupted(sys_thread_t *tid, int ClearInterrupted) -{ - bool_t interrupted; - -#ifndef __linux__ - mutexLock(&tid->mutex); -#endif -#ifdef __linux__ - interrupted = tid->pending_interrupt || tid->interrupted; - - if (ClearInterrupted == 1 && tid->pending_interrupt) { - sys_thread_t* self = sysThreadSelf(); - - if (self == tid && pthread_getspecific(intrJmpbufkey) == NULL) { - jmp_buf jmpbuf; - - /* - * Register our intrHandler as a cleanup handler. If we get - * interrupted (i.e. canceled), we longjmp out of this handler. - */ - pthread_cleanup_push(intrHandler, NULL); - if (setjmp(jmpbuf) == 0) { - thr_setspecific(intrJmpbufkey, &jmpbuf); - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); - while (1) { pthread_testcancel(); } - } - /* Remove intrHandler without calling it. */ - pthread_cleanup_pop(0); - } - } - - if (ClearInterrupted == 1 && interrupted) { - /* we have do to this last, otherwise we really would cancel the - thread */ - tid->interrupted = FALSE; - } -#else - interrupted = tid->interrupted; - if (ClearInterrupted == 1) { - tid->interrupted = FALSE; - mutexUnlock(&tid->mutex); - if (interrupted) { - sigset_t osigset; - /* - * we were interrupted so we may have a signal pending that - * we need to clear. We can just temporarily unmask SIGUSR1 - * and the sigusr1Handler to catch and notice that the - * interrupted flag is not set. - */ - - thr_setspecific(sigusr1Jmpbufkey, NULL); /* paranoid */ - thr_sigsetmask(SIG_UNBLOCK, &sigusr1Mask, &osigset); - thr_sigsetmask(SIG_SETMASK, &osigset, NULL); - } - } else { /* Otherwise leave it alone */ - mutexUnlock(&tid->mutex); - } -#endif - return interrupted; -} - - - -/* - * Stop all threads other than the current one. The stopped threads - * may be restarted with sysThreadMulti(); the operation of this - * routine is atomic; it either stops all java threads or it stops - * none of them. Upon success (all threads stopped) this routine - * returns SYS_OK, otherwise SYS_ERR. - * - * In general, sysThreadSingle() should take care of anything below - * the HPI that needs to be done to safely run single-threaded. - */ -int -sysThreadSingle() -{ - return np_single(); -} - -/* - * Allow multi threaded execution to resume after a - * sysThreadSingle() call. - * - * Note: When this routine is called the scheduler should already - * have been locked by sysThreadSingle(). - */ -void -sysThreadMulti() -{ - np_multi(); -} - -#ifdef __linux__ -/* - * We abuse thread cancellation to interrupt the threads, i.e when an - * exception is posted against the thread, pthread_cancel(3) is sent to the - * thread and the canceled thread executes the following cleanup handler - */ -void -intrHandler(void* arg) -{ - jmp_buf* jmpbufp = pthread_getspecific(intrJmpbufkey); - if (jmpbufp != NULL) { - volatile sys_thread_t* self = sysThreadSelf(); - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); - pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); - self->interrupted = TRUE; - self->pending_interrupt = FALSE; - thr_setspecific(intrJmpbufkey, NULL); - longjmp(*jmpbufp, 1); - } else { -#ifdef PARANOID_DEBUG - sysAssert(0); -#endif - } -} - -#else -/* - * SIGUSR1 is used to interrupt the threads, i.e when an exception - * is posted against the thread, SIGUSR1 is sent to the thread and the - * thread gets the signal, executes the following handler - */ - -static void -#ifdef SA_SIGINFO -sigusr1Handler(int sig, siginfo_t *info, void *uc) -#else -sigusr1Handler(int sig) -#endif -{ - sys_thread_t *tid = sysThreadSelf(); - - if (tid->interrupted) { - sigjmp_buf *jmpbufp; -#ifdef USE_PTHREADS - jmpbufp = pthread_getspecific(sigusr1Jmpbufkey); -#else - thr_getspecific(sigusr1Jmpbufkey, (void **)&jmpbufp); -#endif - if (jmpbufp != NULL) - siglongjmp(*jmpbufp, 1); - } -} -#endif - -HPI_SysInfo * -sysGetSysInfo() -{ - static HPI_SysInfo info = {0, 0}; - - if (info.name == NULL) { - /* - * we want the number of processors configured not the number online - * since processors may be turned on and off dynamically. - */ - int cpus = (int) sysconf(_SC_NPROCESSORS_CONF); - - info.isMP = (cpus < 0) ? 1 : (cpus > 1); - info.name = "native threads"; - } - return &info; -} - - -jlong -sysThreadCPUTime() -{ -#ifdef HAVE_GETHRVTIME - return gethrvtime(); -#else - return 0; -#endif -} - -int -sysThreadGetStatus(sys_thread_t *tid, sys_mon_t **monitorPtr) -{ - int status; - switch (tid->state) { - case RUNNABLE: - if (tid->mon_enter) { - status = SYS_THREAD_MONITOR_WAIT; - } else { - status = SYS_THREAD_RUNNABLE; - } - break; - case SUSPENDED: - if (tid->mon_enter) - status = SYS_THREAD_SUSPENDED | SYS_THREAD_MONITOR_WAIT; - else if (tid->cpending_suspend) - status = SYS_THREAD_SUSPENDED | SYS_THREAD_CONDVAR_WAIT; - else - status = SYS_THREAD_SUSPENDED; - break; - case CONDVAR_WAIT: - status = SYS_THREAD_CONDVAR_WAIT; - break; - default: - return SYS_ERR; - } - if (monitorPtr) { - if (status & SYS_THREAD_MONITOR_WAIT) { - *monitorPtr = tid->mon_enter; - } else if (status & SYS_THREAD_CONDVAR_WAIT) { - *monitorPtr = tid->mon_wait; - } else { - *monitorPtr = NULL; - } - } - return status; -} - -int sysAdjustTimeSlice(int new) -{ - return SYS_ERR; -} - -void sysThreadProfSuspend(sys_thread_t *tid) -{ - np_profiler_suspend(tid); -} - -void sysThreadProfResume(sys_thread_t *tid) -{ - np_profiler_continue(tid); -} - -bool_t sysThreadIsRunning(sys_thread_t *tid) -{ - return np_profiler_thread_is_running(tid); -} - -void * -sysThreadInterruptEvent() -{ - return NULL; -} diff --git a/src/solaris/hpi/native_threads/src/threads_solaris.c b/src/solaris/hpi/native_threads/src/threads_solaris.c deleted file mode 100644 index 33606d3b2bdf319f6249bb674c7a05b04bd56f7e..0000000000000000000000000000000000000000 --- a/src/solaris/hpi/native_threads/src/threads_solaris.c +++ /dev/null @@ -1,666 +0,0 @@ -/* - * Copyright (c) 1998, 2004, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Implementation of HPI that can not be expressed with POSIX threads. - * Note that even if you are building with USE_PTHREADS, we have to - * explicitly undef it here because pthread.h and thread.h can not be - * included in the same file, and this file needs only thread.h. - */ -#undef USE_PTHREADS - -#include "hpi_impl.h" -#include "monitor_md.h" -#include "threads_md.h" -#include "np.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -extern int syscall(int, ...); - - -/* - * Forward declarations. - */ -static int procfd; -static void stop_lwps(); -static void clear_onproc_flags(); -static void restart_lwps(); -static void MakeProcName(register char *procname, register pid_t pid); -static void GC_msec_sleep(int n); - - -/* - * Make sure that we link against a verion of libthread that has at least - * the bug fixes and the interface for getting the stack from threads that - * aren't on LWPs. Otherwise we should exit with some informative message. - */ -extern ulong_t __gettsp(thread_t); - -static const char * gettspMessage = -"You must install a Solaris patch to run the native threads version of the\n" -"Java runtime. The green threads version will work without this patch.\n" -"Please check the native threads release notes for more information.\n" -"\n" -"If you are embedding the VM in a native application, please make sure that\n" -"the native application is linked with libthread.so (-lthread).\n" -"\n" -"Exiting.\n"; - -static void -checkForCorrectLibthread() -{ - if (&__gettsp == 0) { - fprintf(stderr, gettspMessage); - exit(1); - } -} -#ifdef __GNUC__ -static void checkForCorrectLibthread() __attribute__((constructor)); -#else -#pragma init(checkForCorrectLibthread) -#endif - -#pragma weak __gettsp - - -/* - * Suspend said thread. Used to implement java.lang.Thread.suspend(), - * which is deprecated. - */ -int -np_suspend(sys_thread_t *tid) -{ - return thr_suspend(tid->sys_thread); -} - - -/* - * Resume a suspended thread. Used to implement java.lang.Thread.resume(), - * which is deprecated. - */ -int -np_continue(sys_thread_t *tid) -{ - return thr_continue(tid->sys_thread); -} - -/* - * If there is any initialization is required by the non-POSIX parts. - */ -void np_initialize_thread(sys_thread_t *tid) -{ - return; -} - - -/* - * Get the stack start address, and max stack size for the current thread. - */ -int -np_stackinfo(void **addr, long *size) -{ - stack_t stkseg; - - if (thr_stksegment(&stkseg) == 0) { - *addr = (void *)(stkseg.ss_sp); - if (thr_main()) { - struct rlimit r; - getrlimit(RLIMIT_STACK, &r); - *size = (long)r.rlim_cur; - } else { - *size = (long)(stkseg.ss_size); - } - return SYS_OK; - } else { - return SYS_ERR; /* thr_stksegment failed. */ - } -} - -/* - * On Solaris when doing CPU profiling, the threads are bound. - */ -void -np_profiler_init(sys_thread_t *tid) -{ - tid->lwp_id = _lwp_self(); -} - -int -np_profiler_suspend(sys_thread_t *tid) -{ - return _lwp_suspend(tid->lwp_id); -} - -int -np_profiler_continue(sys_thread_t *tid) -{ - return _lwp_continue(tid->lwp_id); -} - -bool_t -np_profiler_thread_is_running(sys_thread_t *tid) -{ - unsigned long sum = 0; - int i; - prstatus_t lwpstatus; - int lwpfd; - int res; - - lwpfd = syscall(SYS_ioctl, procfd, PIOCOPENLWP, &(tid->lwp_id)); - sysAssert(lwpfd >= 0); - - retry: - res = syscall(SYS_ioctl, lwpfd, PIOCSTATUS, &lwpstatus); - sysAssert(res >= 0); - - if (!(lwpstatus.pr_flags & PR_STOPPED)) { - GC_msec_sleep(1); - goto retry; - } - - close(lwpfd); - -#if defined(sparc) - sum += lwpstatus.pr_reg[R_SP]; - sum += lwpstatus.pr_reg[R_PC]; - - sum += lwpstatus.pr_reg[R_G1]; - sum += lwpstatus.pr_reg[R_G2]; - sum += lwpstatus.pr_reg[R_G3]; - sum += lwpstatus.pr_reg[R_G4]; - - sum += lwpstatus.pr_reg[R_O0]; - sum += lwpstatus.pr_reg[R_O1]; - sum += lwpstatus.pr_reg[R_O2]; - sum += lwpstatus.pr_reg[R_O3]; - sum += lwpstatus.pr_reg[R_O4]; - sum += lwpstatus.pr_reg[R_O5]; - - sum += lwpstatus.pr_reg[R_I0]; - sum += lwpstatus.pr_reg[R_I1]; - sum += lwpstatus.pr_reg[R_I2]; - sum += lwpstatus.pr_reg[R_I3]; - sum += lwpstatus.pr_reg[R_I4]; - sum += lwpstatus.pr_reg[R_I5]; - sum += lwpstatus.pr_reg[R_I6]; - sum += lwpstatus.pr_reg[R_I7]; - - sum += lwpstatus.pr_reg[R_L0]; - sum += lwpstatus.pr_reg[R_L1]; - sum += lwpstatus.pr_reg[R_L2]; - sum += lwpstatus.pr_reg[R_L3]; - sum += lwpstatus.pr_reg[R_L4]; - sum += lwpstatus.pr_reg[R_L5]; - sum += lwpstatus.pr_reg[R_L6]; - sum += lwpstatus.pr_reg[R_L7]; -#elif defined(amd64) - sum += lwpstatus.pr_reg[REG_RIP]; - sum += lwpstatus.pr_reg[REG_RSP]; - - sum += lwpstatus.pr_reg[REG_RAX]; - sum += lwpstatus.pr_reg[REG_RCX]; - sum += lwpstatus.pr_reg[REG_RDX]; - sum += lwpstatus.pr_reg[REG_RBX]; - sum += lwpstatus.pr_reg[REG_RBP]; - sum += lwpstatus.pr_reg[REG_RSI]; - sum += lwpstatus.pr_reg[REG_RDI]; - - sum += lwpstatus.pr_reg[REG_R8]; - sum += lwpstatus.pr_reg[REG_R9]; - sum += lwpstatus.pr_reg[REG_R10]; - sum += lwpstatus.pr_reg[REG_R11]; - sum += lwpstatus.pr_reg[REG_R12]; - sum += lwpstatus.pr_reg[REG_R13]; - sum += lwpstatus.pr_reg[REG_R14]; - sum += lwpstatus.pr_reg[REG_R15]; -#elif defined(i386) - sum += lwpstatus.pr_reg[EIP]; - sum += lwpstatus.pr_reg[UESP]; - - sum += lwpstatus.pr_reg[EAX]; - sum += lwpstatus.pr_reg[ECX]; - sum += lwpstatus.pr_reg[EDX]; - sum += lwpstatus.pr_reg[EBX]; - sum += lwpstatus.pr_reg[EBP]; - sum += lwpstatus.pr_reg[ESI]; - sum += lwpstatus.pr_reg[EDI]; -#endif - - if (tid->last_sum == sum) { - return FALSE; - } - tid->last_sum = sum; - - return TRUE; -} - - -/* - * If building for Solaris native threads, open up the /proc file - * descriptor to be used when doing GC. The open is done at JVM start-up so - * as to reserve this fd, to prevent GC stall due to exhausted fds. This fd - * will never be closed, and will alwyas be present. - */ -int -np_initialize() -{ - char procname[32]; - MakeProcName(procname, getpid()); - if ((procfd = open(procname, O_RDONLY, 0)) < 0) { - VM_CALL(jio_fprintf)(stderr, "Cannot open %s for GC", procname); - return SYS_ERR; - } - return SYS_OK; -} - -static void -MakeProcName(register char *procname, register pid_t pid) -{ - register char * s; - - (void) strcpy(procname, "/proc/00000"); - s = procname + strlen(procname); - while (pid) { - *--s = pid%10 + '0'; - pid /= 10; - } -} - -/* - * Suspend all other threads, and record their contexts (register - * set or stack pointer) into the sys_thread structure, so that a - * garbage collect can be run. - */ -int -np_single(void) -{ - int ret; - - sysAssert(SYS_QUEUE_LOCKED(sysThreadSelf())); - - stop_lwps(); - ret = SYS_OK; - return ret; -} - -/* - * Continue threads suspended earlier. But clear their context - * recorded in sys_thread structure first. - */ -void -np_multi(void) -{ - sysAssert(SYS_QUEUE_LOCKED(sysThreadSelf())); - clear_onproc_flags(); - restart_lwps(); -} - -/* /proc solution to stop and restrt lwps */ -/* make sure gc is run as a bound thread */ -/* make sure signals are turned off for gc thread */ -/* what about new lwps getting created in the meantime? */ - -#define MAX_LWPS 1024 - -static prstatus_t Mystatus; -static id_t lwpid_list_buf[MAX_LWPS]; -static id_t oldlwpid_list_buf[MAX_LWPS]; -static sys_thread_t *onproct_list_buf[MAX_LWPS]; -static id_t *lwpid_list = lwpid_list_buf; -static id_t *oldlwpid_list = oldlwpid_list_buf; -static sys_thread_t **onproct_list = onproct_list_buf; -static int lwpid_list_len; -static int oldlwpid_list_len; -static int onproct_ix = 0; -static int gcprio; -static sigset_t gcmask; - -static void -clear_onproc_flags() -{ - int i; - - for (i = 0; i < onproct_ix; i++) { - ((sys_thread_t *)(onproct_list[i]))->onproc = FALSE; - } - onproct_ix = 0; -} - - -/* Sleep for n milliseconds, n < 1000 */ -static void -GC_msec_sleep(int n) -{ - struct timespec ts; - - ts.tv_sec = 0; - ts.tv_nsec = 1000000*n; - if (syscall(SYS_nanosleep, &ts, 0) < 0) { - VM_CALL(jio_fprintf)(stderr, "%d\n", errno); - } -} - -/* - * Assumes stacks grow down from high to low memory. True on sparc and Intel. - */ -#define VALID_SP(sp, bottom, top) \ - (((uintptr_t)(sp)) < ((uintptr_t)(bottom)) && ((uintptr_t)(sp)) > ((uintptr_t)(top))) - -static void -record_lwp_regs(prstatus_t lwpstatus) -{ - sys_thread_t *tid; - int i; -#if defined(sparc) - register uintptr_t sp = lwpstatus.pr_reg[R_SP]; -#elif defined(amd64) - register uintptr_t sp = lwpstatus.pr_reg[REG_RSP]; -#elif defined(i386) - register uintptr_t sp = lwpstatus.pr_reg[UESP]; -#endif - - tid = ThreadQueue; - for (i = 0; i < ActiveThreadCount && tid != 0; i++) { - if (VALID_SP(sp, tid->stack_bottom, tid->stack_top)) { - long *regs = tid->regs; - tid->sp = sp; - /* - * The code below relies on N_TRACED_REGS being set - * correctly for each platform. If you change the - * number of registers being watched, you should update - * the define for N_TRACED_REGS - */ -#if defined(sparc) - regs[0] = lwpstatus.pr_reg[R_G1]; - regs[1] = lwpstatus.pr_reg[R_G2]; - regs[2] = lwpstatus.pr_reg[R_G3]; - regs[3] = lwpstatus.pr_reg[R_G4]; - - regs[4] = lwpstatus.pr_reg[R_O0]; - regs[5] = lwpstatus.pr_reg[R_O1]; - regs[6] = lwpstatus.pr_reg[R_O2]; - regs[7] = lwpstatus.pr_reg[R_O3]; - regs[8] = lwpstatus.pr_reg[R_O4]; - regs[9] = lwpstatus.pr_reg[R_O5]; - regs[10] = lwpstatus.pr_reg[R_O6]; - regs[11] = lwpstatus.pr_reg[R_O7]; -#elif defined(amd64) - regs[0] = lwpstatus.pr_reg[REG_RAX]; - regs[1] = lwpstatus.pr_reg[REG_RCX]; - regs[2] = lwpstatus.pr_reg[REG_RDX]; - regs[3] = lwpstatus.pr_reg[REG_RBX]; - regs[4] = lwpstatus.pr_reg[REG_RBP]; - regs[5] = lwpstatus.pr_reg[REG_RSI]; - regs[6] = lwpstatus.pr_reg[REG_RDI]; - regs[7] = lwpstatus.pr_reg[REG_R8]; - regs[8] = lwpstatus.pr_reg[REG_R9]; - regs[9] = lwpstatus.pr_reg[REG_R10]; - regs[10]= lwpstatus.pr_reg[REG_R11]; - regs[11]= lwpstatus.pr_reg[REG_R12]; - regs[12]= lwpstatus.pr_reg[REG_R13]; - regs[13]= lwpstatus.pr_reg[REG_R14]; - regs[14]= lwpstatus.pr_reg[REG_R15]; -#elif defined(i386) - regs[0] = lwpstatus.pr_reg[EAX]; - regs[1] = lwpstatus.pr_reg[ECX]; - regs[2] = lwpstatus.pr_reg[EDX]; - regs[3] = lwpstatus.pr_reg[EBX]; - regs[4] = lwpstatus.pr_reg[EBP]; - regs[5] = lwpstatus.pr_reg[ESI]; - regs[6] = lwpstatus.pr_reg[EDI]; -#endif - - if (tid->onproc != TRUE) { - tid->onproc = TRUE; - onproct_list[onproct_ix++] = tid; - } - break; - } - tid = tid->next; - } -} - -static void -record_thread_regs() -{ - sys_thread_t *tid; - int i; - - tid = ThreadQueue; - for (i = 0; i < ActiveThreadCount && tid != 0; i++) { - if (tid->onproc != TRUE) { - int i; - - if (tid->sys_thread != 0) { - /* if thread has already been initialized */ - tid->sp = __gettsp(tid->sys_thread); - } else { - /* - * thread is still in the process of being initalized. - * So GC should not care about this thread. Just - * set its sp to 0, and this will force GC to ignore it. - */ - tid->sp = 0; - } - - /* - * Clear out the registers since they are no longer live - * and we don't want to garbage collector to think they are. - */ - - for (i = 0; i < N_TRACED_REGS; i++) - tid->regs[i] = 0; - } - tid = tid->next; - } -} - -static void -wait_stopped_lwps(void) -{ - int i, lwpfd; - prstatus_t lwpstatus; - - for (i = 0; i < (int) Mystatus.pr_nlwp; i++) { - /* if its not me */ - if (lwpid_list[i] != _lwp_self()) { - - /* open the lwp and check the status */ - if ((lwpfd = syscall(SYS_ioctl, procfd, PIOCOPENLWP, - &lwpid_list[i])) < 0) { -#ifdef MY_DEBUG - VM_CALL(jio_fprintf)(stderr, "lwpid %d was not found in process\n", - lwpid_list[i]); -#endif - continue; - } - memset(&lwpstatus, 0, sizeof(lwpstatus)); - while (1) { - if (syscall(SYS_ioctl,lwpfd, PIOCSTATUS, &lwpstatus)<0) { - sysAssert(0); -#ifdef MY_DEBUG - VM_CALL(jio_fprintf)(stderr, "PIOCSTATUS failed for lwp %d", - lwpid_list[i]); -#endif - break; - } - if (lwpstatus.pr_flags & PR_STOPPED) { - record_lwp_regs(lwpstatus); - break; - } - GC_msec_sleep(1); - } - - close (lwpfd); - } /* end of if-me */ - } /* end of for */ -} - -static void -suspend_lwps() -{ - int i; - /* pioopen all the lwps and stop them - except the one I am running on */ - for (i = 0; i < (int) Mystatus.pr_nlwp; i++) { - - /* open and stop the lwp if its not me */ - if (lwpid_list[i] != _lwp_self()) { - - /* PIOCSTOP doesn't work without a writable */ - /* descriptor. And that makes the process */ - /* undebuggable. */ - if (_lwp_suspend(lwpid_list[i]) < 0) { - /* Could happen if the lwp exited */ - lwpid_list[i] = _lwp_self(); - continue; - } - } - } -} - -static void -print_lwps() -{ -#ifdef MY_DEBUG - /* print all the lwps in the process */ - VM_CALL(jio_fprintf)(stdout, "lwpids "); - for (i = 0; i < (int) Mystatus.pr_nlwp; i++) { - if (i == 0) { - VM_CALL(jio_fprintf)(stdout, "%d", lwpid_list[0]); - } else if (i != Mystatus.pr_nlwp - 1) { - VM_CALL(jio_fprintf)(stdout, ", %d", lwpid_list[i]); - } else { - VM_CALL(jio_fprintf)(stdout, " and %d", lwpid_list[i]); - } - } -#endif -} - -/* routine to iteratively stop all lwps */ -static void -stop_lwps() -{ - int i; - sigset_t set; - boolean_t changed; - - /* mask all signals */ - (void) sigfillset(&set); - syscall(SYS_sigprocmask, SIG_SETMASK, &set, &gcmask); - - /* run at highest prio so I cannot be preempted */ - thr_getprio(thr_self(), &gcprio); - thr_setprio(thr_self(), 2147483647); /* #define INT_MAX 2147483647 */ - - oldlwpid_list_len = 0; - - while(1) { - changed = B_FALSE; - - /* Get the # of lwps in the process */ - memset(&Mystatus, 0, sizeof(Mystatus)); - syscall(SYS_ioctl, procfd, PIOCSTATUS, &Mystatus); - -#ifdef MY_DEBUG - VM_CALL(jio_fprintf)(stdout, "Number of lwps in the process is %d\n", - Mystatus.pr_nlwp); - VM_CALL(jio_fprintf)(stdout, "My lwp id is %d\n", _lwp_self()); -#endif - lwpid_list_len = Mystatus.pr_nlwp; - if (syscall(SYS_ioctl, procfd, PIOCLWPIDS, lwpid_list) == -1) { -#ifdef MY_DEBUG - VM_CALL(jio_fprintf)(stderr, "Can't read proc's lwpid list"); -#endif - return; - } - - print_lwps(); - - /* suspend all the lwps */ - suspend_lwps(); - - /* make sure all the lwps have actually stopped */ - wait_stopped_lwps(); - - /* make sure the list has not changed while you were not looking - else start all over again */ - if (lwpid_list_len != oldlwpid_list_len) changed = B_TRUE; - else { - for (i=0; i -#include -#include -#include - -#include "hpi_impl.h" - -#include "interrupt.h" - -/* handler_entry_t is used to keep track of the registered handlers. */ -typedef struct handler_entry { - intr_handler_t handler; - void *handlerArg; -} handler_entry_t; - -static handler_entry_t handlerList[N_INTERRUPTS]; - -/* Initialize the interrupt system */ -void -intrInit() -{ - memset(handlerList, 0, sizeof(handlerList)); - /* - * Target-dependent initialization. - */ - intrInitMD(); -} - -/* Add/Remove a handler for a particular interrupt */ - -signal_handler_t -intrRegister(int interrupt, intr_handler_t handler, void *handlerArg) -{ - struct sigaction sigAct, sigActOld; - - intrLock(); - - if (handler == (intr_handler_t)SYS_SIG_IGN || - handler == (intr_handler_t)SYS_SIG_DFL) { - /* If we get IGN or DFL, register that as the process signal handler, - * and clear the handlerList entry. - */ - sigAct.sa_handler = (void (*)(int))handler; - sigAct.sa_flags = 0; - sigaction(interrupt, &sigAct, &sigActOld); - handlerList[interrupt].handler = NULL; - } else { - /* Otherwise, we register intrDispatchMD as the common signal handler, - * and set the real handler in handlerList[interrupt].handler. - */ -#ifdef SA_SIGINFO - sigAct.sa_handler = 0; - sigAct.sa_sigaction = intrDispatchMD; - sigAct.sa_flags = SA_SIGINFO | SA_RESTART; -#else - sigAct.sa_handler = intrDispatchMD; - sigAct.sa_flags = SA_RESTART; -#endif - sigfillset(&sigAct.sa_mask); - sigaction(interrupt, &sigAct, &sigActOld); - handlerList[interrupt].handler = handler; - handlerList[interrupt].handlerArg = handlerArg; - } - - intrUnlock(); - - /* If SA_SIGINFO is set, sa_sigaction is valid, otherwise sa_handler is. */ -#ifdef SA_SIGINFO - return (sigActOld.sa_flags & SA_SIGINFO) ? - (signal_handler_t)sigActOld.sa_sigaction : - (signal_handler_t)sigActOld.sa_handler; -#else - return (signal_handler_t)sigActOld.sa_handler; -#endif -} - -/* - * intrDispatch -- Dispatch an interrupt. - * - * This routine is called from the low-level handlers - * at interrupt time. - */ -void -intrDispatch(int interrupt, void *siginfo, void *context) -{ - /* - * Assumptions: - * - Each interrupt only has one priority level associated with - * it. - * - Each handler will do enough work so that when it returns - * the source of the interrupt is masked. - */ - handler_entry_t *entry = &handlerList[interrupt]; - intr_handler_t handler = entry->handler; - - if (handler) { - (*handler)(interrupt, siginfo, context, entry->handlerArg); - return; - } - - /* No handler for this interrupt, log the error */ - Log1(0, "spurious interrupt %d\n", interrupt); - return; -} - -static void userSignalHandler(int sig, void *info, void *uc, void *arg) -{ - signal_handler_t handler = (signal_handler_t)arg; - /* for now we don't change the disposition of the signal in this case */ - /* sysSignal(sig, SYS_SIG_DFL); */ - handler(sig, info, uc); -} - -signal_handler_t sysSignal(int sig, signal_handler_t newHandler) -{ - handler_entry_t *entry = &handlerList[sig]; - void *oldHandlerArg = entry->handlerArg; - signal_handler_t oldHandler; - - if (intrInUse(sig)) { - return SYS_SIG_ERR; - } - -#ifdef __linux__ - oldHandler = intrRegister(sig, (intr_handler_t)userSignalHandler, (void *)newHandler); -#else - oldHandler = intrRegister(sig, userSignalHandler, (void *)newHandler); -#endif - /* If the old handler is intrDispatchMD, we get the real handler from - * entry->handlerArg. - */ - if (oldHandler == (signal_handler_t)intrDispatchMD) { - oldHandler = (signal_handler_t)oldHandlerArg; - } - - return oldHandler; -} - -void sysRaise(int sig) -{ - raise(sig); -} diff --git a/src/solaris/hpi/src/linker_md.c b/src/solaris/hpi/src/linker_md.c deleted file mode 100644 index 5f4e09692ea1ad8fd912b6100162d4a6d053afb5..0000000000000000000000000000000000000000 --- a/src/solaris/hpi/src/linker_md.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (c) 1994, 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Machine Dependent implementation of the dynamic linking support - * for java. This routine is Solaris specific. - */ - -#include "hpi_impl.h" - -#include -#include -#include -#include -#include - -#include "path_md.h" -#include "monitor_md.h" - -#ifndef NATIVE -#include "iomgr.h" -#include "threads_md.h" -#endif - -/* - * This lock protects the dl wrappers, assuring that two threads aren't - * in libdl at the same time. - */ -sys_mon_t _dl_lock; - -/* - * Solaris green threads needs to lock around libdl.so. - */ -#if defined(__solaris__) && !defined(NATIVE) - #define NEED_DL_LOCK -#endif - -/* - * create a string for the JNI native function name by adding the - * appropriate decorations. - */ -int -sysBuildFunName(char *name, int nameLen, int args_size, int encodingIndex) -{ - /* On Solaris, there is only one encoding method. */ - if (encodingIndex == 0) - return 1; - return 0; -} - -/* - * create a string for the dynamic lib open call by adding the - * appropriate pre and extensions to a filename and the path - */ -void -sysBuildLibName(char *holder, int holderlen, char *pname, char *fname) -{ - const size_t pnamelen = pname ? strlen(pname) : 0; - - /* Quietly truncate on buffer overflow. Should be an error. */ - if (pnamelen + strlen(fname) + 10 > (size_t) holderlen) { - *holder = '\0'; - return; - } - - if (pnamelen == 0) { - sprintf(holder, "lib%s.so", fname); - } else { - sprintf(holder, "%s/lib%s.so", pname, fname); - } -} - - -#ifdef __linux__ - static int thr_main(void) - { - return -1; - } -#else - #ifndef NATIVE - extern int thr_main(void); - #endif -#endif - -void * -sysLoadLibrary(const char *name, char *err_buf, int err_buflen) -{ - void * result; - -#ifdef NEED_DL_LOCK - sysMonitorEnter(sysThreadSelf(), &_dl_lock); - result = dlopen(name, RTLD_NOW); - sysMonitorExit(sysThreadSelf(), &_dl_lock); -#else - result = dlopen(name, RTLD_LAZY); -#endif - /* - * This is a bit of bulletproofing to catch the commonly occurring - * problem of people loading a library which depends on libthread into - * the VM. thr_main() should always return -1 which means that libthread - * isn't loaded. - */ -#ifndef NATIVE - if (thr_main() != -1) { - VM_CALL(panic)("libthread loaded into green threads"); - } -#endif - if (result == NULL) { - strncpy(err_buf, dlerror(), err_buflen-2); - err_buf[err_buflen-1] = '\0'; - } - return result; -} - -void -sysUnloadLibrary(void *handle) -{ -#ifdef NEED_DL_LOCK - sysMonitorEnter(sysThreadSelf(), &_dl_lock); - dlclose(handle); - sysMonitorExit(sysThreadSelf(), &_dl_lock); -#else - dlclose(handle); -#endif -} - -void * -sysFindLibraryEntry(void *handle, const char *name) -{ - void *sym; -#ifdef NEED_DL_LOCK - sysMonitorEnter(sysThreadSelf(), &_dl_lock); - sym = dlsym(handle, name); - sysMonitorExit(sysThreadSelf(), &_dl_lock); -#else - sym = dlsym(handle, name); -#endif - return sym; -} diff --git a/src/solaris/hpi/src/memory_md.c b/src/solaris/hpi/src/memory_md.c deleted file mode 100644 index 7650f254f6b5425092949a1868058ee2e806a7af..0000000000000000000000000000000000000000 --- a/src/solaris/hpi/src/memory_md.c +++ /dev/null @@ -1,439 +0,0 @@ -/* - * Copyright (c) 1995, 2000, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Implementation of primitive memory allocation. - * - * The only thing machine dependent about this allocator is how it - * initially finds all of the possible memory, and how it implements - * mapChunk() and unmapChunk(). - * - * This is all pretty simple stuff. It is not likely to be banged on - * frequently enough to be a performance issue, unless the underlying - * primitives are. Implementing things: - * - * HPI function Solaris "malloc" Win32 - * -------------------------------------------------------------------- - * sysMapMem() mmap() malloc() VirtualAlloc(...MEM_RESERVE...) - * sysUnMapMem() munmap() free() VirtualFree(...MEM_RESERVE...) - * sysCommitMem() no-op no-op VirtualAlloc(...MEM_COMMIT...) - * sysDecommitMem() no-op no-op VirtualFree(...MEM_COMMIT...) - * - * Memory mapping is the default, but compiling with -DUSE_MALLOC gives - * a system based on malloc(). - */ - -#include -#include -#include -#include /* For perror() */ -#include -#include - -#include "hpi_impl.h" - -#ifndef USE_MALLOC - -#include -#include -#ifdef __linux__ -#ifndef MAP_ANONYMOUS -static int devZeroFD; -#endif -#else -static int devZeroFD; -#endif - -#endif /* !USE_MALLOC */ - -#ifdef __linux__ -#ifndef MAP_FAILED -#define MAP_FAILED ((caddr_t)-1) -#endif -static size_t memGrainSize; /* A page for Linux */ -#else -static unsigned int memGrainSize; /* A page for Solaris */ -#endif - -/* - * Mem size rounding is done at this level. The calling code asks - * these routines for literally what it thinks it wants. The size is - * rounded up to the first multiple of memGrainSize that contains - * requestedSize bytes. - */ - -static long -roundUpToGrain(long value) -{ - return (value + memGrainSize - 1) & ~(memGrainSize - 1); -} - -static long -roundDownToGrain(long value) -{ - return value & ~(memGrainSize - 1); -} - -void -InitializeMem(void) -{ - static int init = 0; - - if (init) { - return; /* Subsequent calls are no-ops */ - } - - /* - * Set system-specific variables used by mem allocator - */ - if (memGrainSize == 0) { - memGrainSize = (int) sysconf(_SC_PAGESIZE); - } - -#ifdef __linux__ -#if !defined(USE_MALLOC) && !defined(MAP_ANONYMOUS) - devZeroFD = open("/dev/zero", O_RDWR); - if (devZeroFD == -1) { - perror("devzero"); - exit(1); - } -#endif /* !USE_MALLOC MAP_ANONYMOUS*/ -#else -#ifndef USE_MALLOC - devZeroFD = open("/dev/zero", O_RDWR); - if (devZeroFD == -1) { - perror("devzero"); - exit(1); - } -#endif /* !USE_MALLOC */ -#endif - - init = 1; /* We're initialized now */ -} - - -#ifndef USE_MALLOC - -#define PROT_ALL (PROT_READ|PROT_WRITE|PROT_EXEC) - -#ifndef MAP_NORESERVE -#define MAP_NORESERVE 0 -#endif - -/* - * Map a chunk of memory. Return the address of the base if successful, - * 0 otherwise. We do not care where the mapped memory is, and can't - * even express a preference in the current HPI. If any platforms - * require us to manage addresses of mapped chunks explicitly, that - * must be done below the HPI. - */ -static char * -mapChunk(long length) -{ - char *ret; - -#if defined(__linux__) && defined(MAP_ANONYMOUS) - ret = (char *) mmap(0, length, PROT_ALL, - MAP_NORESERVE | MAP_PRIVATE | MAP_ANONYMOUS, - -1, (off_t) 0); -#else - ret = (char *) mmap(0, length, PROT_ALL, MAP_NORESERVE|MAP_PRIVATE, - devZeroFD, (off_t) 0); -#endif - return (ret == MAP_FAILED ? 0 : ret); -} - -/* - * Map a chunk of memory at a specific address and reserve swap space - * for it. This is currently only used to remap space previously mapped - * MAP_NORESERVE, reserving swap and getting native error handling. We - * assume that all alignment and rounding has been done by the caller. - * Return 1 if successful and 0 otherwise. - */ -static char * -mapChunkReserve(char *addr, long length) -{ - char *ret; -#if defined(__linux__) && defined(MAP_ANONYMOUS) - ret = (char *) mmap(addr, length, PROT_ALL, - MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, - -1, (off_t) 0); -#else - ret = (char *) mmap(addr, length, PROT_ALL, MAP_FIXED|MAP_PRIVATE, - devZeroFD, (off_t) 0); -#endif - return (ret == MAP_FAILED ? 0 : ret); -} - -/* - * Map a chunk of memory at a specific address and reserve swap space - * for it. This is currently only used to remap space previously mapped - * MAP_RESERVE, unreserving swap and getting native error handling. We - * assume that all alignment and rounding has been done by the caller. - * Return 1 if successful and 0 otherwise. - */ -static char * -mapChunkNoreserve(char *addr, long length) -{ - char *ret; - -#if defined(__linux__) && defined(MAP_ANONYMOUS) - ret = (char *) mmap(addr, length, PROT_ALL, - MAP_FIXED | MAP_PRIVATE | - MAP_NORESERVE | MAP_ANONYMOUS, - -1, (off_t) 0); -#else - ret = (char *) mmap(addr, length, PROT_ALL, - MAP_FIXED|MAP_PRIVATE|MAP_NORESERVE, - devZeroFD, (off_t) 0); -#endif - return (ret == MAP_FAILED ? 0 : ret); -} - -/* - * Unmap a chunk of memory. Return 1 if successful, 0 otherwise. We - * currently don't do any alignment or rounding, assuming that we only - * will unmap chunks that have previously been returned by mapChunk(). - */ -static int -unmapChunk(void *addr, long length) -{ - return (munmap(addr, length) == 0); -} - -#endif /* !USE_MALLOC */ - - -/* HPI Functions: */ - -/* - * Map a range of virtual memory. Note that the size asked for here - * is literally what the upper level has asked for. We need to do - * any rounding, etc. here. If mapping fails return 0, otherwise - * return the address of the base of the mapped memory. - */ -void * -sysMapMem(size_t requestedSize, size_t *mappedSize) -{ - void *mappedAddr; - - *mappedSize = roundUpToGrain(requestedSize); -#ifdef USE_MALLOC - mappedAddr = (void *) sysMalloc(*mappedSize); /* Returns 0 on failure */ -#ifdef __linux__ - if (mappedAddr) { - memset(mappedAddr, 0, *mappedSize); - mappedAddr = (void *) roundUpToGrain(mappedAddr); - } -#endif -#else - mappedAddr = mapChunk(*mappedSize); /* Returns 0 on failure */ -#endif /* USE_MALLOC */ - if (mappedAddr) { - Log3(2, "sysMapMem: 0x%x bytes at 0x%x (request: 0x%x bytes)\n", - *mappedSize, mappedAddr, requestedSize); - } else { - Log1(2, "sysMapMem failed: (request: 0x%x bytes)\n", requestedSize); - } - return mappedAddr; -} - -/* - * Unmap a range of virtual memory. Note that the size asked for here - * is literally what the upper level has asked for. We need to do any - * rounding, etc. here. If unmapping fails return 0, otherwise return - * the address of the base of the unmapped memory. - */ -void * -sysUnmapMem(void *requestedAddr, size_t requestedSize, size_t *unmappedSize) -{ - void *unmappedAddr; - int ret; - - *unmappedSize = roundUpToGrain(requestedSize); -#ifdef USE_MALLOC - sysFree(requestedAddr); - ret = 1; -#else - ret = unmapChunk(requestedAddr, *unmappedSize); -#endif /* USE_MALLOC */ - if (ret) { - unmappedAddr = requestedAddr; - Log4(2, - "sysUnmapMem: 0x%x bytes at 0x%x (request: 0x%x bytes at 0x%x)\n", - *unmappedSize, unmappedAddr, requestedSize, requestedAddr); - } else { - unmappedAddr = 0; - Log2(2, "sysUnmapMem failed: (request: 0x%x bytes at 0x%x)\n", - requestedSize, requestedAddr); - } - return unmappedAddr; -} - -/* - * Commit/decommit backing store to a range of virtual memory. This range - * needs not be identical to a mapped range, but must be a subset of one. - * On Solaris, we remap the range to reserve swap for the space on - * commit. We don't strictly need to do this, as Solaris will demand - * page pages that we've mapped when we want to access them. But by - * reserving swap we get reasonable error handling for free where we'd - * otherwise end up getting a SIGBUS on a random write when we run out - * of swap. It also emphasizes the general need for shared code to - * postpone committing to mapped memory for as long as is feasible. - * When Java really needs space (the thread stacks excepted), it will - * soon write over it (heap, markbits), so we don't really get much from - * demand paging. - * - * We do not validate that commitment requests cover already-mapped - * memory, although in principle we could. The size asked for here - * is what the upper level has asked for. We need to do any platform- - * dependent rounding here. - * - * When you commit, you commit to the entire page (or whatever quantum - * your O/S requires) containing the pointer, and return the beginning of - * that page. When you decommit, you decommit starting at the next page - * *up* from that containing the pointer, except that decommitting from - * a pointer to the beginning of the page operates on that page. - */ - -/* - * Return the address of the base of the newly committed memory, or 0 - * if committing failed. - */ -void * -sysCommitMem(void *requestedAddr, size_t requestedSize, size_t *committedSize) -{ - void *committedAddr; - char *ret; - - *committedSize = roundUpToGrain(requestedSize); - committedAddr = (void *) roundDownToGrain((long) requestedAddr); -#ifdef USE_MALLOC -#ifdef __linux__ - ret = committedAddr; -#else - ret = requestedAddr; -#endif -#else - ret = mapChunkReserve(committedAddr, *committedSize); -#endif - if (ret) { - committedAddr = ret; - Log4(2, - "sysCommitMem: 0x%x bytes at 0x%x (request: 0x%x bytes at 0x%x)\n", - *committedSize, committedAddr, requestedSize, requestedAddr); - } else { - committedAddr = 0; - Log2(2, "sysCommitMem failed: (request: 0x%x bytes at 0x%x)\n", - requestedSize, requestedAddr); - } - - return committedAddr; -} - -/* - * Return the address of the base of the newly decommitted memory, or 0 - * if decommitting failed. - */ -void * -sysDecommitMem(void *requestedAddr, size_t requestedSize, - size_t *decommittedSize) -{ - void *decommittedAddr; - char *ret; - - *decommittedSize = roundDownToGrain(requestedSize); - decommittedAddr = (void *) roundUpToGrain((long) requestedAddr); -#ifdef USE_MALLOC - ret = 0; -#else - ret = mapChunkNoreserve(decommittedAddr, *decommittedSize); -#endif - Log4(2, - "sysDecommitMem: 0x%x bytes at 0x%x (request: 0x%x bytes at 0x%x)\n", - *decommittedSize, decommittedAddr, requestedSize, requestedAddr); - - return ret; -} - -/* - * Allocate memory on an alignment boundary. Returns aligned - * pointer to new memory. Use sysFreeBlock to free the block. - * - * sysAllocBlock() is similar to memalign(), except that it also - * returns a pointer to the beginning of the block returned by the - * OS, which must be used to deallocate the block. (On some OSes, - * these two won't be the same.) sysAllocBlock() is also more - * limited than memalign in that it can only be used to allocate - * on particular alignments (PAGE_ALIGNMENT) and should be assumed - * to round the sizes of allocated blocks up to multiples of the - * alignment value (PAGE_ALIGNMENT*n bytes). - */ -void * -sysAllocBlock(size_t size, void** allocHead) -{ - void* alignedPtr = memalign(PAGE_ALIGNMENT, size); - *allocHead = alignedPtr; - return alignedPtr; -} - -/* - * Wrapper to free block allocated by sysMemAlign. - */ -void -sysFreeBlock(void *allocHead) -{ - free(allocHead); -} - -void * sysMalloc(size_t s) -{ - if (s == 0) - return malloc(1); - return malloc(s); -} - -void * sysRealloc(void *p, size_t s) -{ - return realloc(p, s); -} - -void sysFree(void *p) -{ - if (p != NULL) - free(p); -} - -void * sysCalloc(size_t s1, size_t s2) -{ - if (s1 == 0 || s2 == 0) - return calloc(1, 1); - return calloc(s1, s2); -} - -char * sysStrdup(const char * string) -{ - return strdup(string); -} diff --git a/src/solaris/hpi/src/system_md.c b/src/solaris/hpi/src/system_md.c deleted file mode 100644 index e4823021053e5776bfcccf8f6396a95234c4556c..0000000000000000000000000000000000000000 --- a/src/solaris/hpi/src/system_md.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include "hpi_impl.h" - -#include -#include -#include -#include /* timeval */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "jni_md.h" -#include "mutex_md.h" - -#include "hpi_init.h" - -#include "interrupt.h" -#include "threads_md.h" -#include "monitor_md.h" -#include "largefile.h" - - -#define O_DELETE 0x10000 - -int sysThreadBootstrap(sys_thread_t **tidP, sys_mon_t **lockP, int nb) -{ - threadBootstrapMD(tidP, lockP, nb); - - intrInit(); - -#ifndef NATIVE - /* Initialize the special case for sbrk on Solaris (see synch.c) */ - InitializeSbrk(); - /* Initialize the async io */ - InitializeAsyncIO(); - InitializeMem(); - /* Initialize Clock and Idle threads */ - InitializeHelperThreads(); -#else /* if NATIVE */ - initializeContentionCountMutex(); - InitializeMem(); -#endif /* NATIVE */ - - return SYS_OK; -} - -int sysShutdown() -{ - return SYS_OK; -} - -long -sysGetMilliTicks() -{ - struct timeval tv; - - (void) gettimeofday(&tv, (void *) 0); - return((tv.tv_sec * 1000) + (tv.tv_usec / 1000)); -} - -jlong -sysTimeMillis() -{ - struct timeval t; - gettimeofday(&t, 0); - return ((jlong)t.tv_sec) * 1000 + (jlong)(t.tv_usec/1000); -} - -int -sysGetLastErrorString(char *buf, int len) -{ - if (errno == 0) { - return 0; - } else { - const char *s = strerror(errno); - int n = strlen(s); - if (n >= len) n = len - 1; - strncpy(buf, s, n); - buf[n] = '\0'; - return n; - } -} - -/* - * File system - * - * These are all the sys API which implement the straight POSIX - * API. Those that do not are defined by thread-specific files - * (i.e. io_md.c) - */ - -/* - * Open a file. Unlink the file immediately after open returns - * if the specified oflag has the O_DELETE flag set. - */ -int sysOpen(const char *path, int oflag, int mode) -{ - int fd; - int delete = (oflag & O_DELETE); - oflag = oflag & ~O_DELETE; - fd = open64_w(path, oflag, mode); - if (delete != 0) { - unlink(path); - } - return fd; -} - -char *sysNativePath(char *path) -{ - return path; -} - -int -sysFileSizeFD(int fd, jlong *size) -{ - struct stat64 buf64; - int ret = fstat64(fd, &buf64); - *size = buf64.st_size; - return ret; -} - -int -sysFfileMode(int fd, int *mode) -{ - struct stat64 buf64; - int ret = fstat64(fd, &buf64); - (*mode) = buf64.st_mode; - return ret; -} - -int -sysFileType(const char *path) -{ - int ret; - struct stat buf; - - if ((ret = stat(path, &buf)) == 0) { - mode_t mode = buf.st_mode & S_IFMT; - if (mode == S_IFREG) return SYS_FILETYPE_REGULAR; - if (mode == S_IFDIR) return SYS_FILETYPE_DIRECTORY; - return SYS_FILETYPE_OTHER; - } - return ret; -} - -/* - * Wrapper functions for low-level I/O routines - use the 64 bit - * version if available, else revert to the 32 bit versions. - */ - -off64_t -lseek64_w(int fd, off64_t offset, int whence) -{ - return lseek64(fd, offset, whence); -} - -int -ftruncate64_w(int fd, off64_t length) -{ - return ftruncate64(fd, length); -} - -int -open64_w(const char *path, int oflag, int mode) -{ - int fd = open64(path, oflag, mode); - if (fd == -1) return -1; - - /* If the open succeeded, the file might still be a directory */ - { - int st_mode; - if (sysFfileMode(fd, &st_mode) != -1) { - if ((st_mode & S_IFMT) == S_IFDIR) { - errno = EISDIR; - close(fd); - return -1; - } - } else { - close(fd); - return -1; - } - } - - /* - * 32-bit Solaris systems suffer from: - * - * - an historical default soft limit of 256 per-process file - * descriptors that is too low for many Java programs. - * - * - a design flaw where file descriptors created using stdio - * fopen must be less than 256, _even_ when the first limit above - * has been raised. This can cause calls to fopen (but not calls to - * open, for example) to fail mysteriously, perhaps in 3rd party - * native code (although the JDK itself uses fopen). One can hardly - * criticize them for using this most standard of all functions. - * - * We attempt to make everything work anyways by: - * - * - raising the soft limit on per-process file descriptors beyond - * 256 (done by hotspot) - * - * - As of Solaris 10u4, we can request that Solaris raise the 256 - * stdio fopen limit by calling function enable_extended_FILE_stdio, - * (also done by hotspot). We check for its availability. - * - * - If we are stuck on an old (pre 10u4) Solaris system, we can - * workaround the bug by remapping non-stdio file descriptors below - * 256 to ones beyond 256, which is done below. - * - * See: - * 1085341: 32-bit stdio routines should support file descriptors >255 - * 6533291: Work around 32-bit Solaris stdio limit of 256 open files - * 6431278: Netbeans crash on 32 bit Solaris: need to call - * enable_extended_FILE_stdio() in VM initialisation - * Giri Mandalika's blog - * http://technopark02.blogspot.com/2005_05_01_archive.html - */ -#if defined(__solaris__) && defined(_ILP32) - { - static int needToWorkAroundBug1085341 = -1; - if (needToWorkAroundBug1085341) { - if (needToWorkAroundBug1085341 == -1) - needToWorkAroundBug1085341 = - (dlsym(RTLD_DEFAULT, "enable_extended_FILE_stdio") == NULL); - if (needToWorkAroundBug1085341 && fd < 256) { - int newfd = fcntl(fd, F_DUPFD, 256); - if (newfd != -1) { - close(fd); - fd = newfd; - } - } - } - } -#endif /* 32-bit Solaris */ - - /* - * All file descriptors that are opened in the JVM and not - * specifically destined for a subprocess should have the - * close-on-exec flag set. If we don't set it, then careless 3rd - * party native code might fork and exec without closing all - * appropriate file descriptors (e.g. as we do in closeDescriptors in - * UNIXProcess.c), and this in turn might: - * - * - cause end-of-file to fail to be detected on some file - * descriptors, resulting in mysterious hangs, or - * - * - might cause an fopen in the subprocess to fail on a system - * suffering from bug 1085341. - * - * (Yes, the default setting of the close-on-exec flag is a Unix - * design flaw) - * - * See: - * 1085341: 32-bit stdio routines should support file descriptors >255 - * 4843136: (process) pipe file descriptor from Runtime.exec not being closed - * 6339493: (process) Runtime.exec does not close all file descriptors on Solaris 9 - */ -#ifdef FD_CLOEXEC - { - int flags = fcntl(fd, F_GETFD); - if (flags != -1) - fcntl(fd, F_SETFD, flags | FD_CLOEXEC); - } -#endif - return fd; -} - -void setFPMode(void) -{ -#if defined(__amd64) - asm(" pushq $0x1F80"); - /* ldmxcsr (%rsp) */ - asm(" .byte 0x0f,0xae,0x14,0x24"); - asm(" popq %rax"); -#elif defined(i386) - asm(" pushl $575"); - asm(" fldcw (%esp)"); - asm(" popl %eax"); -#endif -#if defined(__linux__) && defined(__mc68000__) - asm(" fmovel #0x80,%fpcr"); -#endif -} diff --git a/src/solaris/native/sun/java2d/x11/X11SurfaceData.c b/src/solaris/native/sun/java2d/x11/X11SurfaceData.c index 7b1d717008f6d9351e25965a2d3fcdb2792ea027..1a715ca1369ada17b7e4c36b264a9707252a97d5 100644 --- a/src/solaris/native/sun/java2d/x11/X11SurfaceData.c +++ b/src/solaris/native/sun/java2d/x11/X11SurfaceData.c @@ -595,15 +595,16 @@ XImage* X11SD_CreateSharedImage(X11SDOps *xsdo, } XImage* X11SD_GetSharedImage(X11SDOps *xsdo, jint width, jint height, - jboolean readBits) + jint maxWidth, jint maxHeight, jboolean readBits) { XImage * retImage = NULL; if (cachedXImage != NULL && - X11SD_CachedXImageFits(width, height, xsdo->depth, readBits)) { - /* sync so previous data gets flushed */ - XSync(awt_display, False); - retImage = cachedXImage; - cachedXImage = (XImage *)NULL; + X11SD_CachedXImageFits(width, height, maxWidth, maxHeight, + xsdo->depth, readBits)) { + /* sync so previous data gets flushed */ + XSync(awt_display, False); + retImage = cachedXImage; + cachedXImage = (XImage *)NULL; } else if (width * height * xsdo->depth > 0x10000) { retImage = X11SD_CreateSharedImage(xsdo, width, height); } @@ -728,8 +729,8 @@ void X11SD_UnPuntPixmap(X11SDOps *xsdo) * it must be close enough to avoid excessive reading from the screen; * otherwise it should just be at least the size requested. */ -jboolean X11SD_CachedXImageFits(jint width, jint height, jint depth, - jboolean readBits) +jboolean X11SD_CachedXImageFits(jint width, jint height, jint maxWidth, + jint maxHeight, jint depth, jboolean readBits) { /* we assume here that the cached image exists */ jint imgWidth = cachedXImage->width; @@ -747,10 +748,14 @@ jboolean X11SD_CachedXImageFits(jint width, jint height, jint depth, return JNI_TRUE; } - if ((imgWidth < width + 64) && (imgHeight < height + 64)) { + if ((imgWidth < width + 64) && (imgHeight < height + 64) + && imgWidth <= maxWidth && imgHeight <= maxHeight) + { /* Cached image's width/height shouldn't be more than 64 pixels * larger than requested, because the region in XShmGetImage * can't be specified and we don't want to read too much. + * Furthermore it has to be smaller than maxWidth/Height + * so drawables are not read out of bounds. */ return JNI_TRUE; } @@ -1295,7 +1300,7 @@ static XImage * X11SD_GetImage(JNIEnv *env, X11SDOps *xsdo, SurfaceDataBounds *bounds, jint lockFlags) { - int x, y, w, h; + int x, y, w, h, maxWidth, maxHeight; int scan; XImage * img = NULL; Drawable drawable; @@ -1311,10 +1316,31 @@ static XImage * X11SD_GetImage(JNIEnv *env, X11SDOps *xsdo, #ifdef MITSHM if (useMitShmExt == CAN_USE_MITSHM) { - if (xsdo->isPixmap && readBits) { - X11SD_PuntPixmap(xsdo, w, h); + if (xsdo->isPixmap) { + if (readBits) { + X11SD_PuntPixmap(xsdo, w, h); + } + maxWidth = xsdo->pmWidth; + maxHeight = xsdo->pmHeight; + } else { + XWindowAttributes winAttr; + if (XGetWindowAttributes(awt_display, + (Window) xsdo->drawable, &winAttr) != 0) { + maxWidth = winAttr.width; + maxHeight = winAttr.height; + } else { + /* XGWA failed which isn't a good thing. Defaulting to using + * x,y means that after the subtraction of these we will use + * w=0, h=0 which is a reasonable default on such a failure. + */ + maxWidth = x; + maxHeight = y; + } } - img = X11SD_GetSharedImage(xsdo, w, h, readBits); + maxWidth -= x; + maxHeight -= y; + + img = X11SD_GetSharedImage(xsdo, w, h, maxWidth, maxHeight, readBits); } #endif /* MITSHM */ drawable = xsdo->drawable; diff --git a/src/solaris/native/sun/java2d/x11/X11SurfaceData.h b/src/solaris/native/sun/java2d/x11/X11SurfaceData.h index 818688e31e71a914e4fb88f943e4c8772d620ec0..104d7b1021adb8a1239ff784d6ed87ccf883a430 100644 --- a/src/solaris/native/sun/java2d/x11/X11SurfaceData.h +++ b/src/solaris/native/sun/java2d/x11/X11SurfaceData.h @@ -125,15 +125,21 @@ struct _X11SDOps { #define X11SD_LOCK_BY_SHMEM 4 /* surface locked by ShMemExt */ #ifdef MITSHM -XImage * X11SD_GetSharedImage (X11SDOps *xsdo, jint width, jint height, jboolean readBits); +XImage * X11SD_GetSharedImage (X11SDOps *xsdo, + jint width, jint height, + jint maxWidth, jint maxHeight, + jboolean readBits); XImage * X11SD_CreateSharedImage (X11SDOps *xsdo, jint width, jint height); Drawable X11SD_CreateSharedPixmap (X11SDOps *xsdo); void X11SD_DropSharedSegment (XShmSegmentInfo *shminfo); void X11SD_PuntPixmap (X11SDOps *xsdo, jint width, jint height); void X11SD_UnPuntPixmap (X11SDOps *xsdo); -jboolean X11SD_CachedXImageFits (jint width, jint height, jint depth, jboolean readBits); +jboolean X11SD_CachedXImageFits (jint width, jint height, + jint maxWidth, jint maxHeight, + jint depth, jboolean readBits); XImage * X11SD_GetCachedXImage (jint width, jint height, jboolean readBits); #endif /* MITSHM */ +jint X11SD_InitWindow(JNIEnv *env, X11SDOps *xsdo); void X11SD_DisposeOrCacheXImage (XImage * image); void X11SD_DisposeXImage(XImage * image); void X11SD_DirectRenderNotify(JNIEnv *env, X11SDOps *xsdo); diff --git a/src/solaris/native/sun/nio/ch/FileChannelImpl.c b/src/solaris/native/sun/nio/ch/FileChannelImpl.c index c570fe1bc3ed08584b15d0ce3986308ce4c544d1..539013f0bd73986a6dcca5183f581a6aa941a5c8 100644 --- a/src/solaris/native/sun/nio/ch/FileChannelImpl.c +++ b/src/solaris/native/sun/nio/ch/FileChannelImpl.c @@ -35,48 +35,17 @@ #include "nio_util.h" #include -static jfieldID chan_fd; /* jobject 'fd' in sun.io.FileChannelImpl */ - -#ifdef __solaris__ -typedef struct sendfilevec64 { - int sfv_fd; /* input fd */ - uint_t sfv_flag; /* Flags. see below */ - off64_t sfv_off; /* offset to start reading from */ - size_t sfv_len; /* amount of data */ -} sendfilevec_t; - -/* Function pointer for sendfilev on Solaris 8+ */ -typedef ssize_t sendfile_func(int fildes, const struct sendfilevec64 *vec, - int sfvcnt, size_t *xferred); - -sendfile_func* my_sendfile_func = NULL; -#endif - -#ifdef __linux__ +#if defined(__linux__) || defined(__solaris__) #include - -/* Function pointer for sendfile64 on Linux 2.6 (and newer 2.4 kernels) */ -typedef ssize_t sendfile64_func(int out_fd, int in_fd, off64_t *offset, size_t count); - -sendfile64_func* my_sendfile64_func = NULL; #endif +static jfieldID chan_fd; /* jobject 'fd' in sun.io.FileChannelImpl */ + JNIEXPORT jlong JNICALL Java_sun_nio_ch_FileChannelImpl_initIDs(JNIEnv *env, jclass clazz) { jlong pageSize = sysconf(_SC_PAGESIZE); chan_fd = (*env)->GetFieldID(env, clazz, "fd", "Ljava/io/FileDescriptor;"); - -#ifdef __solaris__ - if (dlopen("/usr/lib/libsendfile.so.1", RTLD_GLOBAL | RTLD_LAZY) != NULL) { - my_sendfile_func = (sendfile_func*) dlsym(RTLD_DEFAULT, "sendfilev64"); - } -#endif - -#ifdef __linux__ - my_sendfile64_func = (sendfile64_func*) dlsym(RTLD_DEFAULT, "sendfile64"); -#endif - return pageSize; } @@ -178,22 +147,9 @@ Java_sun_nio_ch_FileChannelImpl_transferTo0(JNIEnv *env, jobject this, jlong position, jlong count, jint dstFD) { -#ifdef __linux__ - jlong max = (jlong)java_lang_Integer_MAX_VALUE; - jlong n; - - if (my_sendfile64_func == NULL) { - off_t offset; - if (position > max) - return IOS_UNSUPPORTED_CASE; - if (count > max) - count = max; - offset = (off_t)position; - n = sendfile(dstFD, srcFD, &offset, (size_t)count); - } else { - off64_t offset = (off64_t)position; - n = (*my_sendfile64_func)(dstFD, srcFD, &offset, (size_t)count); - } +#if defined(__linux__) + off64_t offset = (off64_t)position; + jlong n = sendfile64(dstFD, srcFD, &offset, (size_t)count); if (n < 0) { if (errno == EAGAIN) return IOS_UNAVAILABLE; @@ -206,41 +162,37 @@ Java_sun_nio_ch_FileChannelImpl_transferTo0(JNIEnv *env, jobject this, return IOS_THROWN; } return n; -#endif - -#ifdef __solaris__ - if (my_sendfile_func == NULL) { - return IOS_UNSUPPORTED; - } else { - sendfilevec_t sfv; - size_t numBytes = 0; - jlong result; - - sfv.sfv_fd = srcFD; - sfv.sfv_flag = 0; - sfv.sfv_off = (off64_t)position; - sfv.sfv_len = count; - - result = (*my_sendfile_func)(dstFD, &sfv, 1, &numBytes); - - /* Solaris sendfilev() will return -1 even if some bytes have been - * transferred, so we check numBytes first. - */ - if (numBytes > 0) - return numBytes; - if (result < 0) { - if (errno == EAGAIN) - return IOS_UNAVAILABLE; - if (errno == EOPNOTSUPP) - return IOS_UNSUPPORTED_CASE; - if ((errno == EINVAL) && ((ssize_t)count >= 0)) - return IOS_UNSUPPORTED_CASE; - if (errno == EINTR) - return IOS_INTERRUPTED; - JNU_ThrowIOExceptionWithLastError(env, "Transfer failed"); - return IOS_THROWN; - } - return result; +#elif defined (__solaris__) + sendfilevec64_t sfv; + size_t numBytes = 0; + jlong result; + + sfv.sfv_fd = srcFD; + sfv.sfv_flag = 0; + sfv.sfv_off = (off64_t)position; + sfv.sfv_len = count; + + result = sendfilev64(dstFD, &sfv, 1, &numBytes); + + /* Solaris sendfilev() will return -1 even if some bytes have been + * transferred, so we check numBytes first. + */ + if (numBytes > 0) + return numBytes; + if (result < 0) { + if (errno == EAGAIN) + return IOS_UNAVAILABLE; + if (errno == EOPNOTSUPP) + return IOS_UNSUPPORTED_CASE; + if ((errno == EINVAL) && ((ssize_t)count >= 0)) + return IOS_UNSUPPORTED_CASE; + if (errno == EINTR) + return IOS_INTERRUPTED; + JNU_ThrowIOExceptionWithLastError(env, "Transfer failed"); + return IOS_THROWN; } + return result; +#else + return IOS_UNSUPPORTED_CASE; #endif } diff --git a/src/windows/classes/sun/awt/windows/WPathGraphics.java b/src/windows/classes/sun/awt/windows/WPathGraphics.java index d2700a1c91d721ac558753bacc67bb8151d50f9d..180341f20f3db616bcaba3633af4644eb6c79769 100644 --- a/src/windows/classes/sun/awt/windows/WPathGraphics.java +++ b/src/windows/classes/sun/awt/windows/WPathGraphics.java @@ -51,9 +51,12 @@ import java.awt.image.ColorModel; import java.awt.image.DataBuffer; import java.awt.image.IndexColorModel; import java.awt.image.WritableRaster; +import java.awt.image.ComponentSampleModel; +import java.awt.image.MultiPixelPackedSampleModel; +import java.awt.image.SampleModel; + import sun.awt.image.ByteComponentRaster; import sun.awt.image.BytePackedRaster; - import java.awt.print.PageFormat; import java.awt.print.Printable; import java.awt.print.PrinterException; @@ -1272,6 +1275,25 @@ class WPathGraphics extends PathGraphics { return false; } + int bitsPerPixel = 24; + SampleModel sm = deepImage.getSampleModel(); + if (sm instanceof ComponentSampleModel) { + ComponentSampleModel csm = (ComponentSampleModel)sm; + bitsPerPixel = csm.getPixelStride() * 8; + } else if (sm instanceof MultiPixelPackedSampleModel) { + MultiPixelPackedSampleModel mppsm = + (MultiPixelPackedSampleModel)sm; + bitsPerPixel = mppsm.getPixelBitStride(); + } else { + if (icm != null) { + int diw = deepImage.getWidth(); + int dih = deepImage.getHeight(); + if (diw > 0 && dih > 0) { + bitsPerPixel = data.length*8/diw/dih; + } + } + } + /* Because the caller's image has been rotated * and sheared into our BufferedImage and because * we will be handing that BufferedImage directly to @@ -1289,7 +1311,7 @@ class WPathGraphics extends PathGraphics { (float)Math.rint(scaledBounds.height+0.5), 0f, 0f, deepImage.getWidth(), deepImage.getHeight(), - icm); + bitsPerPixel, icm); setClip(holdClip); } diff --git a/src/windows/classes/sun/awt/windows/WPrinterJob.java b/src/windows/classes/sun/awt/windows/WPrinterJob.java index b73a1b51517f64c13a7d573461b88b494640cd66..cf629bb0ae80c4b2be9323ea0fb5b4f0d57078c8 100644 --- a/src/windows/classes/sun/awt/windows/WPrinterJob.java +++ b/src/windows/classes/sun/awt/windows/WPrinterJob.java @@ -1212,13 +1212,14 @@ public class WPrinterJob extends RasterPrinterJob implements DisposerTarget { float destWidth, float destHeight, float srcX, float srcY, float srcWidth, float srcHeight, + int sampleBitsPerPixel, IndexColorModel icm) { int bitCount = 24; byte[] bmiColors = null; if (icm != null) { - bitCount = icm.getPixelSize(); - bmiColors = new byte[(1< #include #include #include #include #include -#include #include #include @@ -147,7 +149,7 @@ md_seek(int filedes, jlong pos) void md_close(int filedes) { - (void)close(filedes); + (void)closesocket(filedes); } int diff --git a/src/windows/hpi/export/byteorder_md.h b/src/windows/hpi/export/byteorder_md.h deleted file mode 100644 index 3ff9e162362a0d4ae77440f9a0b705b7de0fc918..0000000000000000000000000000000000000000 --- a/src/windows/hpi/export/byteorder_md.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 1994, 1998, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/*- - * Win32 dependent machine byte ordering (actually intel ordering) - */ - -#ifndef _JAVASOFT_WIN32_BYTEORDER_MD_H_ -#define _JAVASOFT_WIN32_BYTEORDER_MD_H_ - -#ifdef x86 -#define ntohl(x) ((x << 24) | \ - ((x & 0x0000ff00) << 8) | \ - ((x & 0x00ff0000) >> 8) | \ - (((unsigned long)(x & 0xff000000)) >> 24)) -#define ntohs(x) (((x & 0xff) << 8) | ((x >> 8) & (0xff))) -#define htonl(x) ntohl(x) -#define htons(x) ntohs(x) -#else /* x86 */ -#define ntohl(x) (x) -#define ntohs(x) (x) -#define htonl(x) (x) -#define htons(x) (x) -#endif /* x86 */ - -#endif /* !_JAVASOFT_WIN32_BYTEORDER_MD_H_ */ diff --git a/src/windows/hpi/export/io_md.h b/src/windows/hpi/export/io_md.h deleted file mode 100644 index 620533e26f4e9be6ddc671824122e12d296ee932..0000000000000000000000000000000000000000 --- a/src/windows/hpi/export/io_md.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 1994, 1998, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Win32 system dependent low level io definitions - */ - -#ifndef _JAVASOFT_WIN32_IO_MD_H_ -#define _JAVASOFT_WIN32_IO_MD_H_ - -#include -#include /* For read(), lseek() etc. */ -#include /* For mkdir() */ -#include -#include -#include -#include -#include - -#include "jvm_md.h" - -#define R_OK 4 -#define W_OK 2 -#define X_OK 1 -#define F_OK 0 - -#define MAXPATHLEN _MAX_PATH - -#define S_ISFIFO(mode) (((mode) & _S_IFIFO) == _S_IFIFO) -#define S_ISCHR(mode) (((mode) & _S_IFCHR) == _S_IFCHR) -#define S_ISDIR(mode) (((mode) & _S_IFDIR) == _S_IFDIR) -#define S_ISREG(mode) (((mode) & _S_IFREG) == _S_IFREG) - -#define LINE_SEPARATOR "\r\n" - -#endif /* !_JAVASOFT_WIN32_IO_MD_H_ */ diff --git a/src/windows/hpi/export/path_md.h b/src/windows/hpi/export/path_md.h deleted file mode 100644 index fc801d80a9ca12b7925b0dcd61e837e6b86f9635..0000000000000000000000000000000000000000 --- a/src/windows/hpi/export/path_md.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 1994, 1998, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/*- - * Win32 dependent search path definitions and API - */ - -#ifndef _JAVASOFT_WIN32_PATH_MD_H_ -#define _JAVASOFT_WIN32_PATH_MD_H_ - -#define PATH_SEPARATOR ";" -#define PATH_CURDIR "." - -#define DIR_SEPARATOR '/' -#define LOCAL_DIR_SEPARATOR '\\' - -#endif /* !_JAVASOFT_WIN32_PATH_MD_H_ */ diff --git a/src/windows/hpi/export/timeval_md.h b/src/windows/hpi/export/timeval_md.h deleted file mode 100644 index 98392b1d9f03df84f4c2d91d251a5dd4207d8ee2..0000000000000000000000000000000000000000 --- a/src/windows/hpi/export/timeval_md.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 1994, 1998, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#ifndef _JAVASOFT_WIN32_TIMEVAL_H_ -#define _JAVASOFT_WIN32_TIMEVAL_H_ - -typedef struct { - long tv_sec; - long tv_usec; -} timeval_t; - -/* - * Operations on timevals. - * - * NB: timercmp does not work for >=, <= or ==. - */ -#define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec) -#define timercmp(tvp, uvp, cmp) \ - ((tvp)->tv_sec cmp (uvp)->tv_sec || \ - (tvp)->tv_sec == (uvp)->tv_sec && (tvp)->tv_usec cmp (uvp)->tv_usec) -#define timereq(tvp, uvp) \ - ((tvp)->tv_sec == (uvp)->tv_sec && (tvp)->tv_usec == (uvp)->tv_usec) -#define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0 - -void timeradd(timeval_t*, timeval_t*); -void timersub(timeval_t*, timeval_t*); - -#endif /* !_JAVASOFT_WIN32_TIMEVAL_H_ */ diff --git a/src/windows/hpi/include/monitor_md.h b/src/windows/hpi/include/monitor_md.h deleted file mode 100644 index dc74c4c3b0ce044cb24b958ccae5988ae21c1d33..0000000000000000000000000000000000000000 --- a/src/windows/hpi/include/monitor_md.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 1994, 1998, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Win32 implementation of Java monitors - */ - -#ifndef _JAVASOFT_WIN32_MONITOR_MD_H_ -#define _JAVASOFT_WIN32_MONITOR_MD_H_ - -#include - -#include "threads_md.h" -#include "mutex_md.h" - -#define SYS_MID_NULL ((sys_mon_t *) 0) - -typedef struct sys_mon { - long atomic_count; /* Variable for atomic compare swap */ - HANDLE semaphore; /* Semaphore used for the contention */ - sys_thread_t *monitor_owner; /* Current owner of this monitor */ - long entry_count; /* Recursion depth */ - sys_thread_t *monitor_waiter; /* Monitor waiting queue head */ - long waiter_count; /* For debugging purpose */ -} sys_mon_t; - -#endif /* !_JAVASOFT_WIN32_MONITOR_MD_H_ */ diff --git a/src/windows/hpi/include/mutex_md.h b/src/windows/hpi/include/mutex_md.h deleted file mode 100644 index f927bd0a08fb5e12c6f5683277a43ff1ab1f00b1..0000000000000000000000000000000000000000 --- a/src/windows/hpi/include/mutex_md.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 1994, 1998, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Win32 implementation of mutexes. Here we use critical sections as - * our mutexes. We could have used mutexes, but mutexes are heavier - * weight than critical sections. Mutexes and critical sections are - * semantically identical, the only difference being that mutexes - * can operate between processes (i.e. address spaces). - * - * It's worth noting that the Win32 functions supporting critical - * sections do not provide any error information whatsoever (i.e. - * all critical section routines return (void)). - */ - -#ifndef _JAVASOFT_WIN32_MUTEX_MD_H_ -#define _JAVASOFT_WIN32_MUTEX_MD_H_ - -#include - -typedef CRITICAL_SECTION mutex_t; - -#define mutexInit(m) InitializeCriticalSection(m) -#define mutexDestroy(m) DeleteCriticalSection(m) -#define mutexLock(m) EnterCriticalSection(m) -#define mutexUnlock(m) LeaveCriticalSection(m) - -#endif /* !_JAVASOFT_WIN32_MUTEX_MD_H_ */ diff --git a/src/windows/hpi/include/threads_md.h b/src/windows/hpi/include/threads_md.h deleted file mode 100644 index 166a880c58f5e10e3e54f760d9f928229b3e3299..0000000000000000000000000000000000000000 --- a/src/windows/hpi/include/threads_md.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 1994, 1999, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Win32 implementation of Java threads - */ - -#ifndef _JAVASOFT_WIN32_THREADS_MD_H_ -#define _JAVASOFT_WIN32_THREADS_MD_H_ - -#include - -#define N_TRACED_REGS 7 - -#define SYS_THREAD_NULL ((sys_thread_t *) 0) - -/* - * Machine dependent info in a sys_thread_t: Keep these values in - * sync with the string array used by sysThreadDumpInfo() in threads_md.c! - */ -typedef enum { - FIRST_THREAD_STATE, - RUNNABLE = FIRST_THREAD_STATE, - SUSPENDED, - MONITOR_WAIT, - CONDVAR_WAIT, - MONITOR_SUSPENDED, - NUM_THREAD_STATES -} thread_state_t; - -struct sys_mon; - -/* - * Machine dependent thread data structure - */ -typedef struct sys_thread { - HANDLE handle; /* Win32 thread handle */ - unsigned long id; /* Win32 thread id */ - long regs[N_TRACED_REGS]; /* Registers */ - thread_state_t state; /* Current thread state */ - bool_t system_thread; /* TRUE if this is a system thread */ - bool_t interrupted; /* Shadow thread interruption */ - short suspend_flags; - HANDLE interrupt_event; /* Event signaled on thread interrupt */ - struct sys_mon *wait_monitor; /* Monitor the thread is waiting for */ - struct sys_thread *next_waiter; /* Next thread in the waiting queue */ - struct sys_mon *enter_monitor; /* Monitor thread is waiting to enter */ - void (*start_proc)(void *); /* Thread start routine address */ - void *start_parm; /* Thread start routine parameter */ - struct sys_thread *next; /* Next thread in active thread queue */ - void *stack_ptr; /* Pointer into the stack segment */ - unsigned int last_sum; - PNT_TIB nt_tib; /* Pointer to NT thread-local block */ -} sys_thread_t; - -#define MONITOR_WAIT_SUSPENDED 0x0001 -#define CONDVAR_WAIT_SUSPENDED 0x0002 - -extern bool_t ThreadsInitialized; - -extern sys_mon_t *_sys_queue_lock; - -#define SYS_QUEUE_LOCK(self) sysMonitorEnter(self, _sys_queue_lock) -#define SYS_QUEUE_LOCKED(self) sysMonitorEntered(self, _sys_queue_lock) -#define SYS_QUEUE_UNLOCK(self) sysMonitorExit(self, _sys_queue_lock) -#define SYS_QUEUE_NOTIFYALL(self) sysMonitorNotifyAll(self, _sys_queue_lock) -#define SYS_QUEUE_WAIT(self) sysMonitorWait(self, _sys_queue_lock, \ - SYS_TIMEOUT_INFINITY) - -#endif /* !_JAVASOFT_WIN32_THREADS_MD_H_ */ diff --git a/src/windows/hpi/src/linker_md.c b/src/windows/hpi/src/linker_md.c deleted file mode 100644 index f14109a1f66e284317f5c0aee0ddcba30cd79c16..0000000000000000000000000000000000000000 --- a/src/windows/hpi/src/linker_md.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) 1994, 2005, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Maintains a list of currently loaded DLLs (Dynamic Link Libraries) - * and their associated handles. Library names are case-insensitive. - */ - -#include -#include -#include - -#include "hpi_impl.h" - -#include "path_md.h" - -/* - * create a string for the JNI native function name by adding the - * appropriate decorations. - * - * On Win32, "__stdcall" functions are exported differently, depending - * on the compiler. In MSVC 4.0, they are decorated with a "_" in the - * beginning, and @nnn in the end, where nnn is the number of bytes in - * the arguments (in decimal). Borland C++ exports undecorated names. - * - * sysBuildFunName handles different encodings depending on the value - * of encodingIndex. It returns 0 when handed an out-of-range - * encodingIndex. - */ -int -sysBuildFunName(char *name, int nameMax, int args_size, int encodingIndex) -{ - if (encodingIndex == 0) { - /* For Microsoft MSVC 4.0 */ - char suffix[6]; /* This is enough since Java never has more than - 256 words of arguments. */ - int nameLen; - int i; - - sprintf(suffix, "@%d", args_size * 4); - - nameLen = strlen(name); - if (nameLen >= nameMax - 7) - return 1; - for(i = nameLen; i > 0; i--) - name[i] = name[i-1]; - name[0] = '_'; - - sprintf(name + nameLen + 1, "%s", suffix); - return 1; - } else if (encodingIndex == 1) - /* For Borland, etc. */ - return 1; - else - return 0; -} - -/* - * Build a machine dependent library name out of a path and file name. - */ -void -sysBuildLibName(char *holder, int holderlen, char *pname, char *fname) -{ - const int pnamelen = pname ? strlen(pname) : 0; - const char c = (pnamelen > 0) ? pname[pnamelen-1] : 0; - - /* Quietly truncates on buffer overflow. Should be an error. */ - if (pnamelen + strlen(fname) + 10 > holderlen) { - *holder = '\0'; - return; - } - - if (pnamelen == 0) { - sprintf(holder, "%s.dll", fname); - } else if (c == ':' || c == '\\') { - sprintf(holder, "%s%s.dll", pname, fname); - } else { - sprintf(holder, "%s\\%s.dll", pname, fname); - } -} - -void * -sysLoadLibrary(const char * name, char *err_buf, int err_buflen) -{ - void *result = LoadLibrary(name); - if (result == NULL) { - /* Error message is pretty lame, try to make a better guess. */ - long errcode = GetLastError(); - if (errcode == ERROR_MOD_NOT_FOUND) { - strncpy(err_buf, "Can't find dependent libraries", err_buflen-2); - err_buf[err_buflen-1] = '\0'; - } else { - sysGetLastErrorString(err_buf, err_buflen); - } - } - return result; -} - -void sysUnloadLibrary(void *handle) -{ - FreeLibrary(handle); -} - -void * sysFindLibraryEntry(void *handle, const char *name) -{ - return GetProcAddress(handle, name); -} diff --git a/src/windows/hpi/src/memory_md.c b/src/windows/hpi/src/memory_md.c deleted file mode 100644 index 982a93f27074165ab103914605ec28f95796aac1..0000000000000000000000000000000000000000 --- a/src/windows/hpi/src/memory_md.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Copyright (c) 1995, 2002, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Implementation of primitive memory allocation. - * - * The only thing machine dependent about this allocator is how it - * initially finds all of the possible memory, and how it implements - * mapChunk() and unmapChunk(). - * - * This is all pretty simple stuff. It is not likely to be banged on - * frequently enough to be a performance issue, unless the underlying - * primitives are. Implementing things: - * - * HPI function Solaris "malloc" Win32 - * -------------------------------------------------------------------- - * sysMapMem() mmap() malloc() VirtualAlloc(...MEM_RESERVE...) - * sysUnMapMem() munmap() free() VirtualFree(...MEM_RESERVE...) - * sysCommitMem() no-op no-op VirtualAlloc(...MEM_COMMIT...) - * sysDecommitMem() no-op no-op VirtualFree(...MEM_COMMIT...) - * - * Memory mapping is the default, but compiling with -DUSE_MALLOC gives - * a system based on malloc(). - */ - -#include -#include - -#include "hpi_impl.h" - -static size_t -roundUp(size_t n, size_t m) -{ - return (n + m - 1) & ~(m - 1); -} - -static size_t -roundDown(size_t n, size_t m) -{ - return n & ~(m - 1); -} - -#define RESERVE_SIZE 65536 /* Memory is reserved in 64KB chunks */ - -static size_t pageSize; /* Machine page size */ - -void -InitializeMem() -{ - SYSTEM_INFO si; - - GetSystemInfo(&si); - pageSize = si.dwPageSize; -} - -/* HPI Functions: */ - -/* - * Map a range of virtual memory. Note that the size asked for here - * is literally what the upper level has asked for. We need to do - * any rounding, etc. here. If mapping fails return 0, otherwise - * return the address of the base of the mapped memory. - */ -void * -sysMapMem(size_t requestedSize, size_t *mappedSize) -{ - void *mappedAddr; - -#ifdef USE_MALLOC - *mappedSize = roundUp(requestedSize, pageSize); - mappedAddr = (void *)malloc(*mappedSize); -#else - *mappedSize = roundUp(requestedSize, RESERVE_SIZE); - mappedAddr = VirtualAlloc(NULL, *mappedSize, MEM_RESERVE, PAGE_READWRITE); -#endif - if (mappedAddr != NULL) { - Log3(2, "sysMapMem: 0x%x bytes at 0x%x (request: 0x%x bytes)\n", - *mappedSize, mappedAddr, requestedSize); - } else { - Log1(2, "sysMapMem failed: (request: 0x%x bytes)\n", requestedSize); - } - return mappedAddr; -} - -/* - * Unmap a range of virtual memory. Note that the size asked for here - * is literally what the upper level has asked for. We need to do any - * rounding, etc. here. If unmapping fails return 0, otherwise return - * the address of the base of the unmapped memory. - */ -void * -sysUnmapMem(void *requestedAddr, size_t requestedSize, size_t *unmappedSize) -{ - void *unmappedAddr; - int ret; - -#ifdef USE_MALLOC - *unmappedSize = roundUp(requestedSize, pageSize); - free(requestedAddr); - ret = TRUE; -#else - *unmappedSize = roundUp(requestedSize, RESERVE_SIZE); - ret = VirtualFree(requestedAddr, 0, MEM_RELEASE); -#endif - if (ret) { - unmappedAddr = requestedAddr; - Log4(2, - "sysUnmapMem: 0x%x bytes at 0x%x (request: 0x%x bytes at 0x%x)\n", - *unmappedSize, unmappedAddr, requestedSize, requestedAddr); - } else { - unmappedAddr = NULL; - Log2(2, "sysUnmapMem failed: (request: 0x%x bytes at 0x%x)\n", - requestedSize, requestedAddr); - } - return unmappedAddr; -} - -/* - * Commit/decommit backing store to a range of virtual memory. This range - * needs not be identical to a mapped range, but must be a subset of one. - * On Solaris, we remap the range to reserve swap for the space on - * commit. We don't strictly need to do this, as Solaris will demand - * page pages that we've mapped when we want to access them. But by - * reserving swap we get reasonable error handling for free where we'd - * otherwise end up getting a SIGBUS on a random write when we run out - * of swap. It also emphasizes the general need for shared code to - * postpone committing to mapped memory for as long as is feasible. - * When Java really needs space (the thread stacks excepted), it will - * soon write over it (heap, markbits), so we don't really get much from - * demand paging. - * - * We do not validate that commitment requests cover already-mapped - * memory, although in principle we could. The size asked for here - * is what the upper level has asked for. We need to do any platform- - * dependent rounding here. - * - * When you commit, you commit to the entire page (or whatever quantum - * your O/S requires) containing the pointer, and return the beginning of - * that page. When you decommit, you decommit starting at the next page - * *up* from that containing the pointer, except that decommitting from - * a pointer to the beginning of the page operates on that page. - */ - -/* - * Return the address of the base of the newly committed memory, or 0 - * if committing failed. - */ -void * -sysCommitMem(void *requestedAddr, size_t requestedSize, size_t *committedSize) -{ - void *committedAddr; - - *committedSize = roundUp(requestedSize, pageSize); - committedAddr = VirtualAlloc(requestedAddr, *committedSize, MEM_COMMIT, - PAGE_READWRITE); - if (committedAddr != NULL) { - Log4(2, - "sysCommitMem: 0x%x bytes at 0x%x (request: 0x%x bytes at 0x%x)\n", - *committedSize, committedAddr, requestedSize, requestedAddr); - } else { - Log2(2, "sysCommitMem failed: (request: 0x%x bytes at 0x%x)\n", - requestedSize, requestedAddr); - } - return committedAddr; -} - -/* - * Return the address of the base of the newly decommitted memory, or 0 - * if decommitting failed. - */ -void * -sysDecommitMem(void *requestedAddr, size_t requestedSize, - size_t *decommittedSize) -{ - void *decommittedAddr; - - /* - * We round the size down to a multiple of the page size and - * round the address up. This ensures that we never decommit - * more that we intend to. - */ - *decommittedSize = roundDown(requestedSize, pageSize); - decommittedAddr = (void *)roundUp((size_t)requestedAddr, pageSize); - - /* - * If the rounded size is equal to zero we simply fail. Passing - * 0 to VirtualFree seems to cause the entire region to be released, - * which is definitely not what we want, since that probably means - * that decommittedAddr is at the end of the current mapping which - * may be the beginning of the next mapping. - */ - if (*decommittedSize != 0 && - VirtualFree(decommittedAddr, *decommittedSize, MEM_DECOMMIT)) { - Log4(2, - "sysDecommitMem: 0x%x bytes at 0x%x (request: 0x%x bytes at 0x%x)\n", - *decommittedSize, decommittedAddr, requestedSize, requestedAddr); - } else { - Log4(2, - "sysDecommitMem: failed 0x%x bytes at 0x%x (request: 0x%x bytes at 0x%x)\n", - *decommittedSize, decommittedAddr, requestedSize, requestedAddr); - decommittedAddr = NULL; - } - return decommittedAddr; -} - -#define PAGED_HEAPS - -#ifdef PAGED_HEAPS - -/* - * Allocate memory on an alignment boundary. Returns aligned - * pointer to new memory. Use sysFreeBlock to free the block. - * - * sysAllocBlock() is similar to memalign(), except that it also - * returns a pointer to the beginning of the block returned by the - * OS, which must be used to deallocate the block. (On some OSes, - * these two won't be the same.) sysAllocBlock() is also more - * limited than memalign in that it can only be used to allocate - * on particular alignments (PAGE_ALIGNMENT) and should be assumed - * to round the sizes of allocated blocks up to multiples of the - * alignment value (PAGE_ALIGNMENT*n bytes). - * - * Note that the use of VirtualAlloc on Win32 is closely tied in to - * the decision for paged heap pages on Win32 to be 64K (that is, - * PAGE_ALIGNMENT is 64K), a reasonable choice in any case. - */ -void * -sysAllocBlock(size_t size, void** allocHead) -{ - void* alignedPtr = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE); - *allocHead = alignedPtr; - return alignedPtr; -} - -/* - * Wrapper to free block allocated by sysMemAlign. - */ -void -sysFreeBlock(void *allocHead) -{ - VirtualFree(allocHead, 0, MEM_RELEASE); -} - -#endif /* PAGED_HEAPS */ - -void * sysMalloc(size_t s) -{ - if (s == 0) - return malloc(1); - return malloc(s); -} - -void * sysRealloc(void *p, size_t s) -{ - return realloc(p, s); -} - -void sysFree(void *p) -{ - if (p != NULL) - free(p); -} - -void * sysCalloc(size_t s1, size_t s2) -{ - if (s1 == 0 || s2 == 0) - return calloc(1, 1); - return calloc(s1, s2); -} - -char * sysStrdup(const char * string) -{ - return strdup(string); -} diff --git a/src/windows/hpi/src/monitor_md.c b/src/windows/hpi/src/monitor_md.c deleted file mode 100644 index 9765f0a51ac21343eea0d56685b93623447a159b..0000000000000000000000000000000000000000 --- a/src/windows/hpi/src/monitor_md.c +++ /dev/null @@ -1,517 +0,0 @@ -/* - * Copyright (c) 1994, 2002, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Win32 implementation of Java monitors - */ - -#include - -#include "hpi_impl.h" - -#include "threads_md.h" -#include "monitor_md.h" - -/* - * Use this information to improve performance for single CPU machine. - */ -static int systemIsMP; - -static mutex_t semaphore_init_mutex; -static mutex_t *semaphore_init_mutex_p = NULL; -/* - * Create and initialize monitor. This can be called before threads have - * been initialized. - */ -int -sysMonitorInit(sys_mon_t *mid) -{ - sysAssert(mid != SYS_MID_NULL); - - if (semaphore_init_mutex_p == NULL) { - systemIsMP = sysGetSysInfo()->isMP; - mutexInit(&semaphore_init_mutex); - semaphore_init_mutex_p = &semaphore_init_mutex; - } - - mid->atomic_count = -1; /* -1 for no thread, 0 means 1 thread */ - mid->semaphore = NULL; /* No semaphore until needed */ - mid->monitor_owner = SYS_THREAD_NULL; - mid->entry_count = 0; /* Recursion count */ - mid->monitor_waiter = 0; /* First waiting thread */ - mid->waiter_count = 0; /* Count of waiting and wake-up thread */ - - return SYS_OK; -} - -/* - * Free any system-dependent resources held by monitors. On Win32 this - * means releasing the critical section (mutex) and condition variable - * that are part of each monitor. - */ -int -sysMonitorDestroy(sys_mon_t *mid) -{ - sysAssert(mid != SYS_MID_NULL); - - CloseHandle(mid->semaphore); - - return SYS_OK; -} - -static void initializeSemaphore(HANDLE *pSema) -{ - mutexLock(semaphore_init_mutex_p); - if (*pSema == NULL) { - *pSema = CreateSemaphore(0,0,1,0); - } - mutexUnlock(semaphore_init_mutex_p); -} - -/* - * Take ownership of monitor. This can be called before threads have - * been initialized, in which case we do nothing since locked monitors - * are not yet needed. - - * The actual code is split into two functions, the assembler routine - * handles the fast path, while the C routine handle the slow path, - * including the lazy initialization of monitor semaphore. - * - * REMIND: It is EXTREMELY RISKY to change any of the code without - * thorough understanding of the system, compiler and call convention. - */ - -static int __fastcall sysMonitorEnter2(sys_thread_t *self, sys_mon_t *mid) -{ - if (mid->semaphore == NULL) { - initializeSemaphore(&(mid->semaphore)); - if (mid->semaphore == NULL) { - return SYS_NORESOURCE; - } - } - - self->enter_monitor = mid; - if (profiler_on) { - VM_CALL(monitorContendedEnter)(self, mid); - } - WaitForSingleObject(mid->semaphore, INFINITE); - self->enter_monitor = NULL; - - mid->monitor_owner = self; - mid->entry_count = 1; - - if (profiler_on) { - VM_CALL(monitorContendedEntered)(self, mid); - } - return SYS_OK; -} - -/* - * The following assembler routine is highly compiler specific. - * Because of the complexity, there is no debug error check. - */ - -#ifndef _WIN64 -int __cdecl -sysMonitorEnter(sys_thread_t *self, sys_mon_t *mid) -{ - __asm - { - mov edx, dword ptr [esp+8]; // load mid - mov ecx, dword ptr [esp+4]; // load self - mov eax, dword ptr [edx+8]; // load mid->monitor_owner - - cmp eax, ecx; // if ( self == mid->monitor_owner ) - je RECURSION; // goto RECURSION; - - mov eax, dword ptr [systemIsMP]; - test eax, eax; - jne MPM; - - inc dword ptr [edx]; /* atomic increment mid->atomic_count */ - jne ACQUIRE_SEMAPHORE; /* if there is an owner already */ - - mov dword ptr [edx+8], ecx; /* mid->monitor_owner = self */ - mov dword ptr [edx+12], 1; /* mid->entry_count = 1 */ - xor eax, eax; /* return SYS_OK */ - ret; - -MPM: - lock inc dword ptr [edx]; /* atomic increment mid->atomic_count */ - jne ACQUIRE_SEMAPHORE; /* if there is an owner already */ - - mov dword ptr [edx+8], ecx; /* mid->monitor_owner = self */ - mov dword ptr [edx+12], 1; /* mid->entry_count = 1 */ - xor eax, eax; /* return SYS_OK */ - ret; - -RECURSION: - inc dword ptr [edx+12]; /* Increment mid->entry_count */ - xor eax, eax; /* return SYS_OK */ - ret; - -ACQUIRE_SEMAPHORE: - /* The self is passed by ECX, mid is passed by EDX */ - jmp sysMonitorEnter2; - } -} -#else -int __cdecl -sysMonitorEnter(sys_thread_t *self, sys_mon_t *mid) -{ -return (SYS_NORESOURCE); -} -#endif - -/* - * Return TRUE if this thread currently owns the monitor. This can be - * called before threads have been initialized, in which case we always - * return TRUE. - */ -bool_t -sysMonitorEntered(sys_thread_t *self, sys_mon_t *mid) -{ - sysAssert(mid != SYS_MID_NULL); - sysAssert(self != 0); - sysAssert(ThreadsInitialized); - - return (mid->monitor_owner == self); -} - -/* - * Release ownership of monitor. This can be called before threads have - * been initialized, in which case we do nothing as locked monitors are - * not yet needed. - * - * The actual code is split into two functions, the assembler routine - * handles the fast path, while the C routine handle the slow path. - * - * REMIND: It is EXTREMELY RISKY to change any of the code without - * thorough understanding of the system, compiler and call convention. - */ - -static int __fastcall -sysMonitorExit2(sys_thread_t *self, sys_mon_t *mid) -{ - sysAssert(mid->entry_count == 0); - sysAssert(mid->atomic_count >= 0); - sysAssert(mid->monitor_owner == 0); - - if (mid->semaphore == NULL) { - initializeSemaphore(&(mid->semaphore)); - if (mid->semaphore == NULL) { - return SYS_NORESOURCE; - } - } - - ReleaseSemaphore(mid->semaphore, 1, 0); - - if (profiler_on) { - VM_CALL(monitorContendedExit)(self, mid); - } - - return SYS_OK; -} - -#ifndef _WIN64 -__declspec(naked) int __cdecl -sysMonitorExit(sys_thread_t *self, sys_mon_t *mid) -{ - __asm - { - mov edx, dword ptr [esp+8]; /* load mid */ - mov ecx, dword ptr [esp+4]; /* load self */ - mov eax, dword ptr [edx+8]; /* load mid->monitor_owner */ - - cmp eax, ecx; /* if ( self != mid->monitor_owner ) */ - jne ERR_RET; /* goto ERROR_RET */ - - dec dword ptr [edx+12]; /* dec mid->entry_count */ - jne OK_RET; /* entry_count != 0 */ - - mov dword ptr [edx+8], 0; /* mid->monitor_owner = 0 */ - - mov eax, dword ptr [systemIsMP]; - test eax, eax; - jne MPM; - - dec dword ptr [edx]; /* atomic decrement mid->atomic_count */ - jge RELEASE_SEMAPHORE; /* if ( atomic_variable < 0 ) */ - xor eax, eax; /* return SYS_OK */ - ret; - -MPM: - lock dec dword ptr [edx]; /* atomic decrement mid->atomic_count */ - jge RELEASE_SEMAPHORE; /* if ( atomic_variable < 0 ) */ -OK_RET: - xor eax, eax; - ret; - -ERR_RET: - mov eax, 0FFFFFFFFH; - ret; - -RELEASE_SEMAPHORE: - jmp sysMonitorExit2; /* forwading call */ - } -} -#else -int __cdecl -sysMonitorExit(sys_thread_t *self, sys_mon_t *mid) -{ -return (-1); -} -#endif - -/* - * Notify single thread waiting on condition variable. - */ -int -sysMonitorNotify(sys_thread_t *self, sys_mon_t *mid) -{ - sysAssert(mid != SYS_MID_NULL); - - if (mid->monitor_owner != self) { - return SYS_ERR; - } - - if (mid->monitor_waiter != SYS_THREAD_NULL) - { - sys_thread_t *thread = mid->monitor_waiter; - mid->monitor_waiter = thread->next_waiter; - - thread->next_waiter = SYS_THREAD_NULL; - thread->wait_monitor = SYS_MID_NULL; - - SetEvent(thread->interrupt_event); - } - - return SYS_OK; -} - -/* - * Notify all threads waiting on condition variable. - */ -int -sysMonitorNotifyAll(sys_thread_t *self, sys_mon_t *mid) -{ - sysAssert(mid != SYS_MID_NULL); - - if (mid->monitor_owner != self) { - return SYS_ERR; - } - - while (mid->monitor_waiter != SYS_THREAD_NULL) - { - sys_thread_t *thread = mid->monitor_waiter; - mid->monitor_waiter = thread->next_waiter; - - thread->next_waiter = SYS_THREAD_NULL; - thread->wait_monitor = SYS_MID_NULL; - - SetEvent(thread->interrupt_event); - } - - return SYS_OK; -} - -/* - * Atomically drop mutex and wait for notification. - */ -int -sysMonitorWait(sys_thread_t *self, sys_mon_t *mid, jlong millis) -{ - long entry_count; - DWORD timeout; - - sysAssert(mid != SYS_MID_NULL); - - if (mid->monitor_owner != self) { - return SYS_ERR; - } - - if ( sysThreadIsInterrupted(self, 1) ) { - return SYS_INTRPT; - } - - entry_count = mid->entry_count; - mid->entry_count = 1; - - self->wait_monitor = mid; - self->next_waiter = 0; - - if (mid->monitor_waiter == 0) { - mid->monitor_waiter = self; - } else { - sys_thread_t *thread = mid->monitor_waiter; - while (thread->next_waiter != 0) { - thread = thread->next_waiter; - } - thread->next_waiter = self; - } - - if ( millis == SYS_TIMEOUT_INFINITY || - millis > (jlong)((unsigned int)0xffffffff) ) { - timeout = INFINITE; - } else { - timeout = (long) millis; - } - - mid->waiter_count++; - - sysMonitorExit(self, mid); - - self->state = CONDVAR_WAIT; - - WaitForSingleObject(self->interrupt_event, timeout); - - self->state = RUNNABLE; - - sysMonitorEnter(self, mid); - - mid->waiter_count--; - - mid->entry_count = entry_count; - /* Reset event anyway, prevent racing the timeout */ - ResetEvent(self->interrupt_event); - - if (self->wait_monitor != SYS_MID_NULL) { - sys_thread_t *head; - - sysAssert( self->wait_monitor == mid ); - sysAssert( mid->monitor_waiter != SYS_THREAD_NULL ); - - head = mid->monitor_waiter; - - if (head == self) { - mid->monitor_waiter = self->next_waiter; - } else { - while (head != SYS_THREAD_NULL) { - if (head->next_waiter == self) { - head->next_waiter = self->next_waiter; - break; - } else { - head = head->next_waiter; - } - } - } - - self->next_waiter = SYS_THREAD_NULL; - self->wait_monitor = SYS_MID_NULL; - } - - if ( sysThreadIsInterrupted(self, 1) ) { - return SYS_INTRPT; - } - - return SYS_OK; -} - -static int -dumpWaitingQueue(sys_thread_t *tid, sys_thread_t **waiters, int sz) -{ - int n; - for (n = 0; tid != 0; tid = tid->next_waiter, n++, sz--) { - if (sz > 0) { - waiters[n] = tid; - } - } - return n; -} - -typedef struct { - sys_mon_t *mid; - sys_thread_t **waiters; - int sz; - int nwaiters; -} wait_info; - -static int -findWaitersHelper(sys_thread_t *t, void *arg) -{ - wait_info * winfo = (wait_info *) arg; - if (t->enter_monitor == winfo->mid) { - if (winfo->sz > 0) { - winfo->waiters[winfo->nwaiters] = t; - } - winfo->sz--; - winfo->nwaiters++; - } - return SYS_OK; -} - -int -sysMonitorGetInfo(sys_mon_t *mid, sys_mon_info *info) -{ - wait_info winfo; - - sysAssert(mid != SYS_MID_NULL); - info->owner = mid->monitor_owner; - if (mid->monitor_owner) { - info->entry_count = mid->entry_count; - } - - winfo.mid = mid; - winfo.nwaiters = 0; - winfo.waiters = info->monitor_waiters; - winfo.sz = info->sz_monitor_waiters; - sysThreadEnumerateOver(findWaitersHelper, (void *) &winfo); - info->n_monitor_waiters = winfo.nwaiters; - - info->n_condvar_waiters = dumpWaitingQueue(mid->monitor_waiter, - info->condvar_waiters, - info->sz_condvar_waiters); - - return SYS_OK; -} - -/* - * Return size of system-dependent monitor structure. - */ -size_t -sysMonitorSizeof(void) -{ - return sizeof(struct sys_mon); -} - - -/* - * Return true if there are any threads inside this monitor. - */ -bool_t -sysMonitorInUse(sys_mon_t *mid) -{ - return (mid->atomic_count != -1 - || mid->waiter_count != 0 - || mid->monitor_owner != SYS_THREAD_NULL - || mid->monitor_waiter != SYS_THREAD_NULL); -} - - -sys_thread_t * -sysMonitorOwner(sys_mon_t *mon) -{ - return mon->monitor_owner; -} diff --git a/src/windows/hpi/src/path_md.c b/src/windows/hpi/src/path_md.c deleted file mode 100644 index 2f86ceabeb4b4567f8e687117b6ce9a45da9481b..0000000000000000000000000000000000000000 --- a/src/windows/hpi/src/path_md.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Machine dependent path name and file name manipulation code - */ - -#include -#include -#include -#include -#include - -#include -#include - -#include "hpi_impl.h" - -#undef DEBUG_PATH /* Define this to debug path code */ - -#define isfilesep(c) ((c) == '/' || (c) == '\\') -#define islb(c) (IsDBCSLeadByte((BYTE)(c))) - - -/* Convert a pathname to native format. On win32, this involves forcing all - separators to be '\\' rather than '/' (both are legal inputs, but Win95 - sometimes rejects '/') and removing redundant separators. The input path is - assumed to have been converted into the character encoding used by the local - system. Because this might be a double-byte encoding, care is taken to - treat double-byte lead characters correctly. - - This procedure modifies the given path in place, as the result is never - longer than the original. There is no error return; this operation always - succeeds. */ - -char * -sysNativePath(char *path) -{ - char *src = path, *dst = path, *end = path; - char *colon = NULL; /* If a drive specifier is found, this will - point to the colon following the drive - letter */ - - /* Assumption: '/', '\\', ':', and drive letters are never lead bytes */ - sysAssert(!islb('/') && !islb('\\') && !islb(':')); - - /* Check for leading separators */ - while (isfilesep(*src)) src++; - if (isalpha(*src) && !islb(*src) && src[1] == ':') { - /* Remove leading separators if followed by drive specifier. This - hack is necessary to support file URLs containing drive - specifiers (e.g., "file://c:/path"). As a side effect, - "/c:/path" can be used as an alternative to "c:/path". */ - *dst++ = *src++; - colon = dst; - *dst++ = ':'; src++; - } else { - src = path; - if (isfilesep(src[0]) && isfilesep(src[1])) { - /* UNC pathname: Retain first separator; leave src pointed at - second separator so that further separators will be collapsed - into the second separator. The result will be a pathname - beginning with "\\\\" followed (most likely) by a host name. */ - src = dst = path + 1; - path[0] = '\\'; /* Force first separator to '\\' */ - } - } - - end = dst; - - /* Remove redundant separators from remainder of path, forcing all - separators to be '\\' rather than '/'. Also, single byte space - characters are removed from the end of the path because those - are not legal ending characters on this operating system. - */ - while (*src != '\0') { - if (isfilesep(*src)) { - *dst++ = '\\'; src++; - while (isfilesep(*src)) src++; - if (*src == '\0') { /* Check for trailing separator */ - end = dst; - if (colon == dst - 2) break; /* "z:\\" */ - if (dst == path + 1) break; /* "\\" */ - if (dst == path + 2 && isfilesep(path[0])) { - /* "\\\\" is not collapsed to "\\" because "\\\\" marks the - beginning of a UNC pathname. Even though it is not, by - itself, a valid UNC pathname, we leave it as is in order - to be consistent with the path canonicalizer as well - as the win32 APIs, which treat this case as an invalid - UNC pathname rather than as an alias for the root - directory of the current drive. */ - break; - } - end = --dst; /* Path does not denote a root directory, so - remove trailing separator */ - break; - } - end = dst; - } else { - if (islb(*src)) { /* Copy a double-byte character */ - *dst++ = *src++; - if (*src) { - *dst++ = *src++; - } - end = dst; - } else { /* Copy a single-byte character */ - char c = *src++; - *dst++ = c; - /* Space is not a legal ending character */ - if (c != ' ') - end = dst; - } - } - } - - *end = '\0'; - - /* For "z:", add "." to work around a bug in the C runtime library */ - if (colon == dst - 1) { - path[2] = '.'; - path[3] = '\0'; - } - -#ifdef DEBUG_PATH - jio_fprintf(stderr, "sysNativePath: %s\n", path); -#endif DEBUG_PATH - return path; -} diff --git a/src/windows/hpi/src/socket_md.c b/src/windows/hpi/src/socket_md.c deleted file mode 100644 index 1641650dd4fc6f9ad96f19628e4fe7c9711dab87..0000000000000000000000000000000000000000 --- a/src/windows/hpi/src/socket_md.c +++ /dev/null @@ -1,537 +0,0 @@ -/* - * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include -#include - -#include "hpi_impl.h" - -#include "mutex_md.h" - -struct sockaddr; - -#define FN_RECV 0 -#define FN_SEND 1 -#define FN_LISTEN 2 -#define FN_BIND 3 -#define FN_ACCEPT 4 -#define FN_RECVFROM 5 -#define FN_SENDTO 6 -#define FN_SELECT 7 -#define FN_CONNECT 8 -#define FN_CLOSESOCKET 9 -#define FN_SHUTDOWN 10 -#define FN_GETHOSTNAME 11 -#define FN_GETHOSTBYADDR 12 -#define FN_GETHOSTBYNAME 13 -#define FN_HTONS 14 -#define FN_HTONL 15 -#define FN_NTOHS 16 -#define FN_NTOHL 17 -#define FN_GETSOCKOPT 18 -#define FN_SETSOCKOPT 19 -#define FN_GETPROTOBYNAME 20 -#define FN_GETSOCKNAME 21 -#define FN_SOCKET 22 -#define FN_WSASENDDISCONNECT 23 -#define FN_SOCKETAVAILABLE 24 - -static int (PASCAL FAR *sockfnptrs[])() = - {NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, - }; - -static bool_t sockfnptrs_initialized = FALSE; -static mutex_t sockFnTableMutex; - -/* is Winsock2 loaded? better to be explicit than to rely on sockfnptrs */ -static bool_t winsock2Available = FALSE; - -/* Winsock2 options at the IPPROTO_IP level - We need the following translation in order to deal with the multiple - definitions for IPPROTO_IP level options in different winsock versions. - -in winsock.h vs. ws2tcpip.h -#define IP_OPTIONS 1 1 -#define IP_MULTICAST_IF 2 9 -#define IP_MULTICAST_TTL 3 10 -#define IP_MULTICAST_LOOP 4 11 -#define IP_ADD_MEMBERSHIP 5 12 -#define IP_DROP_MEMBERSHIP 6 13 -#define IP_TTL 7 4 -#define IP_TOS 8 3 -#define IP_DONTFRAGMENT 9 14 -*/ -static int IPPROTO_OPTIONS[] = {-1, 1, 9, 10, 11, 12, 13, 4, 3, 14}; - -/* IMPORTANT: whenever possible, we want to use Winsock2 (ws2_32.dll) - * instead of Winsock (wsock32.dll). Other than the fact that it is - * newer, less buggy and faster than Winsock, Winsock2 lets us to work - * around the following problem: - * - * Generally speaking, it is important to shutdown a socket before - * closing it, since failing to do so can sometimes result in a TCP - * RST (abortive close) which is disturbing to the peer of the - * connection. - * - * The Winsock way to shutdown a socket is the Berkeley call - * shutdown(). We do not want to call it on Win95, since it - * sporadically leads to an OS crash in IFS_MGR.VXD. Complete hull - * breach. Blue screen. Ugly. - * - * So, in initSockTable we look for Winsock 2, and if we find it we - * assign wsassendisconnectfn function pointer. When we close, we - * first check to see if it's bound, and if it is, we call it. Winsock - * 2 will always be there on NT, and we recommend that win95 user - * install it. - * - * - br 10/11/97 - */ - -static void -initSockFnTable() { - int (PASCAL FAR* WSAStartupPtr)(WORD, LPWSADATA); - WSADATA wsadata; - OSVERSIONINFO info; - - mutexInit(&sockFnTableMutex); - mutexLock(&sockFnTableMutex); - if (sockfnptrs_initialized == FALSE) { - HANDLE hWinsock; - - /* try to load Winsock2, and if that fails, load Winsock */ - hWinsock = LoadLibrary("ws2_32.dll"); - if (hWinsock == NULL) { - hWinsock = LoadLibrary("wsock32.dll"); - winsock2Available = FALSE; - } else { - winsock2Available = TRUE; - } - - if (hWinsock == NULL) { - VM_CALL(jio_fprintf)(stderr, "Could not load Winsock 1 or 2 (error: %d)\n", - GetLastError()); - } - - /* If we loaded a DLL, then we might as well initialize it. */ - WSAStartupPtr = (int (PASCAL FAR *)(WORD, LPWSADATA)) - GetProcAddress(hWinsock, "WSAStartup"); - if (WSAStartupPtr(MAKEWORD(1,1), &wsadata) != 0) { - VM_CALL(jio_fprintf)(stderr, "Could not initialize Winsock\n"); - } - - sockfnptrs[FN_RECV] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "recv"); - sockfnptrs[FN_SEND] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "send"); - sockfnptrs[FN_LISTEN] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "listen"); - sockfnptrs[FN_BIND] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "bind"); - sockfnptrs[FN_ACCEPT] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "accept"); - sockfnptrs[FN_RECVFROM] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "recvfrom"); - sockfnptrs[FN_SENDTO] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "sendto"); - sockfnptrs[FN_SELECT] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "select"); - sockfnptrs[FN_CONNECT] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "connect"); - sockfnptrs[FN_CLOSESOCKET] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "closesocket"); - /* we don't use this */ - sockfnptrs[FN_SHUTDOWN] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "shutdown"); - sockfnptrs[FN_GETHOSTNAME] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "gethostname"); - sockfnptrs[FN_GETHOSTBYADDR] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "gethostbyaddr"); - sockfnptrs[FN_GETHOSTBYNAME] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "gethostbyname"); - sockfnptrs[FN_HTONS] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "htons"); - sockfnptrs[FN_HTONL] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "htonl"); - sockfnptrs[FN_NTOHS] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "ntohs"); - sockfnptrs[FN_NTOHL] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "ntohl"); - sockfnptrs[FN_GETSOCKOPT] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "getsockopt"); - sockfnptrs[FN_SETSOCKOPT] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "setsockopt"); - sockfnptrs[FN_GETPROTOBYNAME] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "getprotobyname"); - sockfnptrs[FN_GETSOCKNAME] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "getsockname"); - - sockfnptrs[FN_SOCKET] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "socket"); - /* in winsock 1, this will simply be 0 */ - sockfnptrs[FN_WSASENDDISCONNECT] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, - "WSASendDisconnect"); - sockfnptrs[FN_SOCKETAVAILABLE] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, - "ioctlsocket"); - } - - sysAssert(sockfnptrs[FN_RECV] != NULL); - sysAssert(sockfnptrs[FN_SEND] != NULL); - sysAssert(sockfnptrs[FN_LISTEN] != NULL); - sysAssert(sockfnptrs[FN_BIND] != NULL); - sysAssert(sockfnptrs[FN_ACCEPT] != NULL); - sysAssert(sockfnptrs[FN_RECVFROM] != NULL); - sysAssert(sockfnptrs[FN_SENDTO] != NULL); - sysAssert(sockfnptrs[FN_SELECT] != NULL); - sysAssert(sockfnptrs[FN_CONNECT] != NULL); - sysAssert(sockfnptrs[FN_CLOSESOCKET] != NULL); - sysAssert(sockfnptrs[FN_SHUTDOWN] != NULL); - sysAssert(sockfnptrs[FN_GETHOSTNAME] != NULL); - sysAssert(sockfnptrs[FN_GETHOSTBYADDR] != NULL); - sysAssert(sockfnptrs[FN_GETHOSTBYNAME] != NULL); - sysAssert(sockfnptrs[FN_HTONS] != NULL); - sysAssert(sockfnptrs[FN_HTONL] != NULL); - sysAssert(sockfnptrs[FN_NTOHS] != NULL); - sysAssert(sockfnptrs[FN_NTOHL] != NULL); - sysAssert(sockfnptrs[FN_GETSOCKOPT] != NULL); - sysAssert(sockfnptrs[FN_SETSOCKOPT] != NULL); - sysAssert(sockfnptrs[FN_GETPROTOBYNAME] != NULL); - sysAssert(sockfnptrs[FN_GETSOCKNAME] != NULL); - sysAssert(sockfnptrs[FN_SOCKET] != NULL); - - if (winsock2Available) { - sysAssert(sockfnptrs[FN_WSASENDDISCONNECT] != NULL); - } - - sysAssert(sockfnptrs[FN_SOCKETAVAILABLE] != NULL); - - sockfnptrs_initialized = TRUE; - mutexUnlock(&sockFnTableMutex); -} - -/* - * If we get a nonnull function pointer it might still be the case - * that some other thread is in the process of initializing the socket - * function pointer table, but our pointer should still be good. - */ -int -sysListen(int fd, int count) { - int (PASCAL FAR *listenfn)(); - if ((listenfn = sockfnptrs[FN_LISTEN]) == NULL) { - initSockFnTable(); - listenfn = sockfnptrs[FN_LISTEN]; - } - sysAssert(sockfnptrs_initialized == TRUE && listenfn != NULL); - return (*listenfn)(fd, (long)count); -} - -int -sysConnect(int fd, struct sockaddr *name, int namelen) { - int (PASCAL FAR *connectfn)(); - if ((connectfn = sockfnptrs[FN_CONNECT]) == NULL) { - initSockFnTable(); - connectfn = sockfnptrs[FN_CONNECT]; - } - sysAssert(sockfnptrs_initialized == TRUE); - sysAssert(connectfn != NULL); - return (*connectfn)(fd, name, namelen); -} - -int -sysBind(int fd, struct sockaddr *name, int namelen) { - int (PASCAL FAR *bindfn)(); - if ((bindfn = sockfnptrs[FN_BIND]) == NULL) { - initSockFnTable(); - bindfn = sockfnptrs[FN_BIND]; - } - sysAssert(sockfnptrs_initialized == TRUE); - sysAssert(bindfn != NULL); - return (*bindfn)(fd, name, namelen); -} - -int -sysAccept(int fd, struct sockaddr *name, int *namelen) { - int (PASCAL FAR *acceptfn)(); - if ((acceptfn = sockfnptrs[FN_ACCEPT]) == NULL) { - initSockFnTable(); - acceptfn = sockfnptrs[FN_ACCEPT]; - } - sysAssert(sockfnptrs_initialized == TRUE && acceptfn != NULL); - return (*acceptfn)(fd, name, namelen); -} - -int -sysRecvFrom(int fd, char *buf, int nBytes, - int flags, struct sockaddr *from, int *fromlen) { - int (PASCAL FAR *recvfromfn)(); - if ((recvfromfn = sockfnptrs[FN_RECVFROM]) == NULL) { - initSockFnTable(); - recvfromfn = sockfnptrs[FN_RECVFROM]; - } - sysAssert(sockfnptrs_initialized == TRUE && recvfromfn != NULL); - return (*recvfromfn)(fd, buf, nBytes, flags, from, fromlen); -} - -int -sysSendTo(int fd, char *buf, int len, - int flags, struct sockaddr *to, int tolen) { - int (PASCAL FAR *sendtofn)(); - if ((sendtofn = sockfnptrs[FN_SENDTO]) == NULL) { - initSockFnTable(); - sendtofn = sockfnptrs[FN_SENDTO]; - } - sysAssert(sockfnptrs_initialized == TRUE && sendtofn != NULL); - return (*sendtofn)(fd, buf, len, flags, to, tolen); -} - -int -sysRecv(int fd, char *buf, int nBytes, int flags) { - int (PASCAL FAR *recvfn)(); - if ((recvfn = sockfnptrs[FN_RECV]) == NULL) { - initSockFnTable(); - recvfn = sockfnptrs[FN_RECV]; - } - sysAssert(sockfnptrs_initialized == TRUE && recvfn != NULL); - return (*recvfn)(fd, buf, nBytes, flags); -} - -int -sysSend(int fd, char *buf, int nBytes, int flags) { - int (PASCAL FAR *sendfn)(); - if ((sendfn = sockfnptrs[FN_SEND]) == NULL) { - initSockFnTable(); - sendfn = sockfnptrs[FN_SEND]; - } - sysAssert(sockfnptrs_initialized == TRUE && sendfn != NULL); - return (*sendfn)(fd, buf, nBytes, flags); -} - - -int -sysGetHostName(char *hostname, int namelen) { - int (PASCAL FAR *fn)(); - if ((fn = sockfnptrs[FN_GETHOSTNAME]) == NULL) { - initSockFnTable(); - fn = sockfnptrs[FN_GETHOSTNAME]; - } - sysAssert(sockfnptrs_initialized == TRUE && fn != NULL); - return (*fn)(hostname, namelen); -} - -struct hostent * -sysGetHostByAddr(const char *hostname, int len, int type) { - struct hostent * (PASCAL FAR *fn)(); - if ((fn = (struct hostent * (PASCAL FAR *)()) sockfnptrs[FN_GETHOSTBYADDR]) == NULL) { - initSockFnTable(); - fn = (struct hostent * (PASCAL FAR *)()) sockfnptrs[FN_GETHOSTBYADDR]; - } - sysAssert(sockfnptrs_initialized == TRUE && fn != NULL); - return (*fn)(hostname, len, type); -} - -struct hostent * -sysGetHostByName(char *hostname) { - struct hostent * (PASCAL FAR *fn)(); - if ((fn = (struct hostent * (PASCAL FAR *)()) sockfnptrs[FN_GETHOSTBYNAME]) == NULL) { - initSockFnTable(); - fn = (struct hostent * (PASCAL FAR *)()) sockfnptrs[FN_GETHOSTBYNAME]; - } - sysAssert(sockfnptrs_initialized == TRUE && fn != NULL); - return (*fn)(hostname); -} - -int -sysSocket(int domain, int type, int protocol) { - int sock; - int (PASCAL FAR *socketfn)(); - if ((socketfn = sockfnptrs[FN_SOCKET]) == NULL) { - initSockFnTable(); - socketfn = sockfnptrs[FN_SOCKET]; - } - sysAssert(sockfnptrs_initialized == TRUE && socketfn != NULL); - sock = (*socketfn)(domain, type, protocol); - if (sock != INVALID_SOCKET) { - SetHandleInformation((HANDLE)(uintptr_t)sock, HANDLE_FLAG_INHERIT, FALSE); - } - return sock; -} - -int sysSocketShutdown(int fd, int how) { - if (fd > 0) { - int (PASCAL FAR *shutdownfn)(); - if ((shutdownfn = sockfnptrs[FN_SHUTDOWN]) == NULL) { - initSockFnTable(); - shutdownfn = sockfnptrs[FN_SHUTDOWN]; - } - /* At this point we are guaranteed the sockfnptrs are initialized */ - sysAssert(sockfnptrs_initialized == TRUE && shutdownfn != NULL); - (void) (*shutdownfn)(fd, how); - } -return TRUE; -} - -/* - * This function is carefully designed to work around a bug in Windows - * 95's networking winsock. Please see the beginning of this file for - * a complete description of the problem. - */ -int sysSocketClose(int fd) { - - if (fd > 0) { - int (PASCAL FAR *closesocketfn)(); - int (PASCAL FAR *wsasenddisconnectfn)(); - int dynamic_ref = -1; - - if ((closesocketfn = sockfnptrs[FN_CLOSESOCKET]) == NULL) { - initSockFnTable(); - } - /* At this point we are guaranteed the sockfnptrs are initialized */ - sysAssert(sockfnptrs_initialized == TRUE); - - closesocketfn = sockfnptrs[FN_CLOSESOCKET]; - sysAssert(closesocketfn != NULL); - - if (winsock2Available) { - struct linger l; - int len = sizeof(l); - - if (sysGetSockOpt(fd, SOL_SOCKET, SO_LINGER, (char *)&l, &len) == 0) { - if (l.l_onoff == 0) { - wsasenddisconnectfn = sockfnptrs[FN_WSASENDDISCONNECT]; - (*wsasenddisconnectfn)(fd, NULL); - } - } - } - (void) (*closesocketfn)(fd); - } - return TRUE; -} - -/* - * Poll the fd for reading for timeout ms. Returns 1 if something's - * ready, 0 if it timed out, -1 on error, -2 if interrupted (although - * interruption isn't implemented yet). Timeout in milliseconds. */ -int -sysTimeout(int fd, long timeout) { - int res; - fd_set tbl; - struct timeval t; - int (PASCAL FAR *selectfn)(); - - t.tv_sec = timeout / 1000; - t.tv_usec = (timeout % 1000) * 1000; - FD_ZERO(&tbl); - FD_SET(fd, &tbl); - - if ((selectfn = sockfnptrs[FN_SELECT]) == NULL) { - initSockFnTable(); - selectfn = sockfnptrs[FN_SELECT]; - } - sysAssert(sockfnptrs_initialized == TRUE && selectfn != NULL); - res = (*selectfn)(fd + 1, &tbl, 0, 0, &t); - return res; -} - -long -sysSocketAvailable(int fd, jint *pbytes) -{ - int (PASCAL FAR *socketfn)(); - if ((socketfn = sockfnptrs[FN_SOCKETAVAILABLE]) == NULL) { - initSockFnTable(); - socketfn = sockfnptrs[FN_SOCKETAVAILABLE]; - } - sysAssert(sockfnptrs_initialized == TRUE && socketfn != NULL); - return (*socketfn)(fd, FIONREAD, pbytes); -} - -int -sysGetSockName(int fd, struct sockaddr *name, int *namelen) { - int (PASCAL FAR *getsocknamefn)(); - if ((getsocknamefn = sockfnptrs[FN_GETSOCKNAME]) == NULL) { - initSockFnTable(); - getsocknamefn = sockfnptrs[FN_GETSOCKNAME]; - } - sysAssert(sockfnptrs_initialized == TRUE); - sysAssert(getsocknamefn != NULL); - return (*getsocknamefn)(fd, name, namelen); -} - -int -sysGetSockOpt(int fd, int level, int optname, char *optval, int *optlen ) { - int (PASCAL FAR *getsockoptfn)(); - if ((getsockoptfn = sockfnptrs[FN_GETSOCKOPT]) == NULL) { - initSockFnTable(); - getsockoptfn = sockfnptrs[FN_GETSOCKOPT]; - } - sysAssert(sockfnptrs_initialized == TRUE); - sysAssert(getsockoptfn != NULL); - - /* We need the following translation in order to deal with the multiple - definitions for IPPROTO_IP level options in different winsock versions - */ - if (winsock2Available && level == IPPROTO_IP && - optname >= IP_OPTIONS && optname <= IP_DONTFRAGMENT) { - optname = IPPROTO_OPTIONS[optname]; - } - return (*getsockoptfn)(fd, level, optname, optval, optlen); -} - -int -sysSetSockOpt(int fd, int level, int optname, const char *optval, int optlen ) { - int (PASCAL FAR *setsockoptfn)(); - if ((setsockoptfn = sockfnptrs[FN_SETSOCKOPT]) == NULL) { - initSockFnTable(); - setsockoptfn = sockfnptrs[FN_SETSOCKOPT]; - } - sysAssert(sockfnptrs_initialized == TRUE); - sysAssert(setsockoptfn != NULL); - - /* We need the following translation in order to deal with the multiple - definitions for IPPROTO_IP level options in different winsock versions - */ - if (winsock2Available && level == IPPROTO_IP && - optname >= IP_OPTIONS && optname <= IP_DONTFRAGMENT) { - optname = IPPROTO_OPTIONS[optname]; - } - - return (*setsockoptfn)(fd, level, optname, optval, optlen); -} - -struct protoent * -sysGetProtoByName(char *name) { - struct protoent * (PASCAL FAR *getprotobynamefn)(); - if ((getprotobynamefn = (struct protoent * (PASCAL FAR *)()) sockfnptrs[FN_GETPROTOBYNAME]) == NULL) { - initSockFnTable(); - getprotobynamefn = (struct protoent * (PASCAL FAR *)()) sockfnptrs[FN_GETPROTOBYNAME]; - } - sysAssert(sockfnptrs_initialized == TRUE); - sysAssert(getprotobynamefn != NULL); - return (*getprotobynamefn)(name); -} diff --git a/src/windows/hpi/src/sys_api_md.c b/src/windows/hpi/src/sys_api_md.c deleted file mode 100644 index 514b3c5529f9056f94746541c1e9fd0e8ceae1fa..0000000000000000000000000000000000000000 --- a/src/windows/hpi/src/sys_api_md.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright (c) 1997, 2004, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "hpi_impl.h" - -#include "path_md.h" - -static int MAX_INPUT_EVENTS = 2000; - -int -sysOpen(const char *path, int oflag, int mode) -{ - char pathbuf[MAX_PATH]; - - if (strlen(path) > MAX_PATH - 1) { - errno = ENAMETOOLONG; - return -1; - } - return open(sysNativePath(strcpy(pathbuf, path)), - oflag | O_BINARY | O_NOINHERIT, mode); -} - - -static int -nonSeekAvailable(int, long *); -static int -stdinAvailable(int, long *); - -int -sysAvailable(int fd, jlong *pbytes) { - jlong cur, end; - struct _stati64 stbuf64; - - if (_fstati64(fd, &stbuf64) >= 0) { - int mode = stbuf64.st_mode; - if (S_ISCHR(mode) || S_ISFIFO(mode)) { - int ret; - long lpbytes; - if (fd == 0) { - ret = stdinAvailable(fd, &lpbytes); - } else { - ret = nonSeekAvailable(fd, &lpbytes); - } - (*pbytes) = (jlong)(lpbytes); - return ret; - } - if ((cur = _lseeki64(fd, 0L, SEEK_CUR)) == -1) { - return FALSE; - } else if ((end = _lseeki64(fd, 0L, SEEK_END)) == -1) { - return FALSE; - } else if (_lseeki64(fd, cur, SEEK_SET) == -1) { - return FALSE; - } - *pbytes = end - cur; - return TRUE; - } else { - return FALSE; - } -} - -static int -nonSeekAvailable(int fd, long *pbytes) { - /* This is used for available on non-seekable devices - * (like both named and anonymous pipes, such as pipes - * connected to an exec'd process). - * Standard Input is a special case. - * - */ - HANDLE han; - - if ((han = (HANDLE) _get_osfhandle(fd)) == (HANDLE)(-1)) { - return FALSE; - } - - if (! PeekNamedPipe(han, NULL, 0, NULL, pbytes, NULL)) { - /* PeekNamedPipe fails when at EOF. In that case we - * simply make *pbytes = 0 which is consistent with the - * behavior we get on Solaris when an fd is at EOF. - * The only alternative is to raise an Exception, - * which isn't really warranted. - */ - if (GetLastError() != ERROR_BROKEN_PIPE) { - return FALSE; - } - *pbytes = 0; - } - return TRUE; -} - -static int -stdinAvailable(int fd, long *pbytes) { - HANDLE han; - DWORD numEventsRead = 0; /* Number of events read from buffer */ - DWORD numEvents = 0; /* Number of events in buffer */ - DWORD i = 0; /* Loop index */ - DWORD curLength = 0; /* Position marker */ - DWORD actualLength = 0; /* Number of bytes readable */ - BOOL error = FALSE; /* Error holder */ - INPUT_RECORD *lpBuffer; /* Pointer to records of input events */ - - if ((han = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE) { - return FALSE; - } - - /* Construct an array of input records in the console buffer */ - error = GetNumberOfConsoleInputEvents(han, &numEvents); - if (error == 0) { - return nonSeekAvailable(fd, pbytes); - } - - /* lpBuffer must fit into 64K or else PeekConsoleInput fails */ - if (numEvents > MAX_INPUT_EVENTS) { - numEvents = MAX_INPUT_EVENTS; - } - - lpBuffer = sysMalloc(numEvents * sizeof(INPUT_RECORD)); - if (lpBuffer == NULL) { - return FALSE; - } - - error = PeekConsoleInput(han, lpBuffer, numEvents, &numEventsRead); - if (error == 0) { - sysFree(lpBuffer); - return FALSE; - } - - /* Examine input records for the number of bytes available */ - for(i=0; ibKeyDown == TRUE) { - CHAR *keyPressed = (CHAR *) &(keyRecord->uChar); - curLength++; - if (*keyPressed == '\r') - actualLength = curLength; - } - } - } - if(lpBuffer != NULL) - sysFree(lpBuffer); - *pbytes = (long) actualLength; - return TRUE; -} - -/* - * This is documented to succeed on read-only files, but Win32's - * FlushFileBuffers functions fails with "access denied" in such a - * case. So we only signal an error if the error is *not* "access - * denied". - */ - -int -sysSync(int fd) { - /* - * From the documentation: - * - * On Windows NT, the function FlushFileBuffers fails if hFile - * is a handle to console output. That is because console - * output is not buffered. The function returns FALSE, and - * GetLastError returns ERROR_INVALID_HANDLE. - * - * On the other hand, on Win95, it returns without error. I cannot - * assume that 0, 1, and 2 are console, because if someone closes - * System.out and then opens a file, they might get file descriptor - * 1. An error on *that* version of 1 should be reported, whereas - * an error on System.out (which was the original 1) should be - * ignored. So I use isatty() to ensure that such an error was due - * to this bogosity, and if it was, I ignore the error. - */ - - HANDLE handle = (HANDLE)_get_osfhandle(fd); - - if (!FlushFileBuffers(handle)) { - if (GetLastError() != ERROR_ACCESS_DENIED) { /* from winerror.h */ - return -1; - } - } - return 0; -} - - -int -sysSetLength(int fd, jlong length) { - HANDLE h = (HANDLE)_get_osfhandle(fd); - long high = (long)(length >> 32); - DWORD ret; - - if (h == (HANDLE)(-1)) return -1; - ret = SetFilePointer(h, (long)(length), &high, FILE_BEGIN); - if (ret == 0xFFFFFFFF && GetLastError() != NO_ERROR) { - return -1; - } - if (SetEndOfFile(h) == FALSE) return -1; - return 0; -} - -int -sysFileSizeFD(int fd, jlong *size) -{ - struct _stati64 buf64; - - if(_fstati64(fd, &buf64) < 0) { - return -1; - } - (*size) = buf64.st_size; - - if (*size & 0xFFFFFFFF00000000) { - /* - * On Win98 accessing a non-local file we have observed a - * bogus file size of 0x100000000. So if upper 32 bits - * are non-zero we re-calculate the size using lseek. This - * should work for any file size, but it might have a - * performance impact relative to fstati64. Note: Hotspot - * doesn't have this problem because it uses stat rather - * than fstat or fstati64. - */ - - jlong curpos; - jlong endpos; - jlong newpos; - - curpos = _lseeki64(fd, 0, SEEK_CUR); - if (curpos < 0) { - return -1; - } - endpos = _lseeki64(fd, 0, SEEK_END); - if (endpos < 0) { - return -1; - } - newpos = _lseeki64(fd, curpos, SEEK_SET); - if (newpos != curpos) { - return -1; - } - (*size) = endpos; - - } - return 0; -} - -int -sysFfileMode(int fd, int *mode) -{ - int ret; - struct _stati64 buf64; - ret = _fstati64(fd, &buf64); - (*mode) = buf64.st_mode; - return ret; -} - -int -sysFileType(const char *path) -{ - int ret; - struct _stati64 buf; - - if ((ret = _stati64(path, &buf)) == 0) { - int mode = buf.st_mode & S_IFMT; - if (mode == S_IFREG) return SYS_FILETYPE_REGULAR; - if (mode == S_IFDIR) return SYS_FILETYPE_DIRECTORY; - return SYS_FILETYPE_OTHER; - } - return ret; -} - -size_t sysRead(int fd, void *buf, unsigned int nBytes) -{ - return read(fd, buf, nBytes); -} - -size_t sysWrite(int fd, const void *buf, unsigned int nBytes) -{ - return write(fd, buf, nBytes); -} - -int sysClose(int fd) -{ - return close(fd); -} - -jlong sysSeek(int fd, jlong offset, int whence) -{ - return _lseeki64(fd, offset, whence); -} diff --git a/src/windows/hpi/src/system_md.c b/src/windows/hpi/src/system_md.c deleted file mode 100644 index d45c8d657a0c2a3d4a2075553af60cdc46375e9b..0000000000000000000000000000000000000000 --- a/src/windows/hpi/src/system_md.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright (c) 1994, 2002, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include -#include /* For constants for _control87() */ -#include -#include /* For _tzset() and _ftime() */ -#include - -#include "hpi_impl.h" - -#include "jni_md.h" -#include "monitor_md.h" - - -static int pending_signals[NSIG]; -static HANDLE sigEvent; -static CRITICAL_SECTION userSigMon; - - -void sysSignalNotify(int sig) -{ - sys_thread_t *self = sysThreadSelf(); - EnterCriticalSection(&userSigMon); - pending_signals[sig]++; - LeaveCriticalSection(&userSigMon); - SetEvent(sigEvent); -} - -static int lookupSignal() -{ - int i; - EnterCriticalSection(&userSigMon); - for (i = 0; i < NSIG; i++) { - if (pending_signals[i]) { - pending_signals[i]--; - LeaveCriticalSection(&userSigMon); - return i; - } - } - LeaveCriticalSection(&userSigMon); - return -1; -} - -int sysSignalWait() -{ - int sig; - while ((sig = lookupSignal()) == -1) { - WaitForSingleObject(sigEvent, INFINITE); - } - return sig; -} - -signal_handler_t sysSignal(int sig, signal_handler_t newHandler) -{ - return (signal_handler_t)signal(sig, (void (*)(int))newHandler); -} - -void sysRaise(int sig) -{ - raise(sig); -} - -int sysThreadBootstrap(sys_thread_t **tidP, sys_mon_t **lockP, int nb) -{ - extern void InitializeMem(void); - - threadBootstrapMD(tidP, lockP, nb); - - sigEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - InitializeCriticalSection(&userSigMon); - memset(pending_signals, 0, sizeof(pending_signals)); - - /* - * Change default for std. streams stdout, stderr, - * stdin to be O_BINARY not O_TEXT. The `\r` characters - * corrupt binary files. - */ - - _setmode(0, O_BINARY); - _setmode(1, O_BINARY); - _setmode(2, O_BINARY); - - /* - * Set floating point processor to no floating point exceptions. - * See bug 4027374. Should be the same values VC++ would set them - * to, but by doing this here we ensure other dll's don't override. - */ - _control87(_MCW_EM | _RC_NEAR | _PC_53, _MCW_EM | _MCW_RC | _MCW_PC); - - InitializeMem(); - - return SYS_OK; -} - -long -sysGetMilliTicks(void) -{ - return(GetTickCount()); -} - -#define FT2INT64(ft) \ - ((jlong)(ft).dwHighDateTime << 32 | (jlong)(ft).dwLowDateTime) - -jlong -sysTimeMillis(void) -{ - static jlong fileTime_1_1_70 = 0; - SYSTEMTIME st0; - FILETIME ft0; - - if (fileTime_1_1_70 == 0) { - /* Initialize fileTime_1_1_70 -- the Win32 file time of midnight - * 1/1/70. - */ - - memset(&st0, 0, sizeof(st0)); - st0.wYear = 1970; - st0.wMonth = 1; - st0.wDay = 1; - SystemTimeToFileTime(&st0, &ft0); - fileTime_1_1_70 = FT2INT64(ft0); - } - - GetSystemTime(&st0); - SystemTimeToFileTime(&st0, &ft0); - - return (FT2INT64(ft0) - fileTime_1_1_70) / 10000; -} - -void * -sysAllocateMem(long size) -{ - return malloc(size); -} - -int sysShutdown() -{ - return SYS_OK; -} - -unsigned -sleep(unsigned seconds) -{ - Sleep(seconds * 1000); - return 0; -} - -int -sysGetLastErrorString(char *buf, int len) -{ - long errval; - - if ((errval = GetLastError()) != 0) { - /* DOS error */ - int n = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, errval, - 0, buf, len, NULL); - if (n > 3) { - /* Drop final '.', CR, LF */ - if (buf[n - 1] == '\n') n--; - if (buf[n - 1] == '\r') n--; - if (buf[n - 1] == '.') n--; - buf[n] = '\0'; - } - return n; - } - - if (errno != 0) { - /* C runtime error that has no corresponding DOS error code */ - const char *s = strerror(errno); - int n = strlen(s); - if (n >= len) n = len - 1; - strncpy(buf, s, n); - buf[n] = '\0'; - return n; - } - - return 0; -} diff --git a/src/windows/hpi/src/threads_md.c b/src/windows/hpi/src/threads_md.c deleted file mode 100644 index 7bc98038b449d95bd7ab67749b5b8e7011c94764..0000000000000000000000000000000000000000 --- a/src/windows/hpi/src/threads_md.c +++ /dev/null @@ -1,831 +0,0 @@ -/* - * Copyright (c) 1994, 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Win32 implementation of Java threads - */ - -#include "hpi_impl.h" - -#include -#include /* for _beginthreadex(), _endthreadex() */ -#include - -#include "threads_md.h" -#include "monitor_md.h" - - -/* - * Queue of active Java threads - */ -static sys_thread_t *ThreadQueue; -sys_mon_t *_sys_queue_lock; - -static int ActiveThreadCount = 0; /* All threads */ - -/* - * Set to TRUE once threads have been bootstrapped - */ -bool_t ThreadsInitialized = FALSE; - -/* - * Are we running under Window NT - */ -static bool_t windowsNT = FALSE; - -/* - * Thread local storage index used for looking up sys_thread_t struct - * (tid) associated with the current thread. - */ -#define TLS_INVALID_INDEX 0xffffffffUL -static unsigned long tls_index = TLS_INVALID_INDEX; - -static void RecordNTTIB(sys_thread_t *tid) -{ -#ifndef _WIN64 - PNT_TIB nt_tib; - __asm { - mov eax, dword ptr fs:[18h]; - mov nt_tib, eax; - } - tid->nt_tib = nt_tib; -#else - tid->nt_tib = 0; -#endif -} - -/* - * Add thread to queue of active threads. - */ -static void -queueInsert(sys_thread_t *tid) -{ - if (ThreadsInitialized) - SYS_QUEUE_LOCK(sysThreadSelf()); - ActiveThreadCount++; - tid->next = ThreadQueue; - ThreadQueue = tid; - if (ThreadsInitialized) - SYS_QUEUE_UNLOCK(sysThreadSelf()); - else - ThreadsInitialized = TRUE; -} - -/* - * Remove thread from queue of active threads. - */ -static void -removefromActiveQ(sys_thread_t *tid) -{ - sysAssert(SYS_QUEUE_LOCKED(sysThreadSelf())); - --ActiveThreadCount; - - if (ThreadQueue == tid) { - ThreadQueue = tid->next; - } else { - sys_thread_t *p; - for (p = ThreadQueue; p->next != 0; p = p->next) { - if (p->next == tid) { - p->next = tid->next; - break; - } - } - } -} - -/* - * Allocate and initialize the sys_thread_t structure for an arbitary - * native thread. - */ -int -sysThreadAlloc(sys_thread_t **tidP) -{ - HANDLE hnd = GetCurrentProcess(); - sys_thread_t *tid = allocThreadBlock(); - if (tid == NULL) { - return SYS_NOMEM; - } - - tid->state = RUNNABLE; - tid->interrupted = FALSE; - tid->interrupt_event = CreateEvent(NULL, TRUE, FALSE, NULL); - tid->id = GetCurrentThreadId(); - DuplicateHandle(hnd, GetCurrentThread(), hnd, &tid->handle, 0, FALSE, - DUPLICATE_SAME_ACCESS); - - RecordNTTIB(tid); - /* For the Invocation API: - We update the thread-specific storage before locking the - queue because sysMonitorEnter will access sysThreadSelf. - */ - TlsSetValue(tls_index, tid); - - queueInsert(tid); - tid->stack_ptr = &tid; - *tidP = tid; - return SYS_OK; -} - -/* - * Bootstrap the Java thread system by making the current thread the - * "primordial" thread. - */ -int threadBootstrapMD(sys_thread_t **tidP, sys_mon_t **lockP, int nb) -{ - OSVERSIONINFO windowsVersion; - HANDLE hnd = GetCurrentProcess(); - - nReservedBytes = (nb + 7) & (~7); - /* - * Allocate TLS index for thread-specific data. - */ - tls_index = TlsAlloc(); - if (tls_index == TLS_INVALID_INDEX) { - VM_CALL(jio_fprintf)(stderr, "TlsAlloc failed (errcode = %x)\n", - GetLastError()); - return SYS_NOMEM; - } - - /* OS properties */ - windowsVersion.dwOSVersionInfoSize = sizeof(windowsVersion); - GetVersionEx(&windowsVersion); - windowsNT = windowsVersion.dwPlatformId == VER_PLATFORM_WIN32_NT; - - /* Initialize the queue lock monitor */ - _sys_queue_lock = (sys_mon_t *)sysMalloc(sysMonitorSizeof()); - if (_sys_queue_lock == NULL) { - return SYS_ERR; - } - VM_CALL(monitorRegister)(_sys_queue_lock, "Thread queue lock"); - *lockP = _sys_queue_lock; - - return sysThreadAlloc(tidP); -} - -/* - * Return current stack pointer of specified thread. - */ -void * -sysThreadStackPointer(sys_thread_t *tid) -{ -#ifndef _WIN64 - CONTEXT context; - WORD __current_SS; - - /* REMIND: Need to fix this for Win95 */ - context.ContextFlags = CONTEXT_CONTROL; - if (!GetThreadContext(tid->handle, &context)) { - VM_CALL(jio_fprintf)(stderr, "GetThreadContext failed (errcode = %x)\n", - GetLastError()); - return 0; - } - - /* With the NT TIB stuff that Hong came up with, I don't think we - * need any of the complicated VirtualQuery calls anymore. If - * context.Esp is within the stack limit and base, we return - * context.Esp, otherwise, we can simply return nt_tib->StackLimit. - * To minimize code changes, though, I'm keeping the code the way - * it was. - */ - if (tid->nt_tib == NULL) { - /* thread hasn't started yet. */ - return 0; - } - - __asm { - mov ax, ss; - mov __current_SS, ax; - } - - if (context.SegSs == __current_SS && - context.Esp >= (uintptr_t)(tid->nt_tib->StackLimit) && - context.Esp < (uintptr_t)(tid->nt_tib->StackBase)) { - MEMORY_BASIC_INFORMATION mbi; - - VirtualQuery((PBYTE) context.Esp, &mbi, sizeof(mbi)); - - if (!(mbi.Protect & PAGE_GUARD)) { - return (void *) context.Esp; - } else { - SYSTEM_INFO si; - char *Esp = (char*) context.Esp; - DWORD dwPageSize; - - GetSystemInfo(&si); - dwPageSize = si.dwPageSize; - Esp -= (((DWORD) Esp) % dwPageSize); - do { - Esp += dwPageSize; - VirtualQuery((PBYTE) Esp, &mbi, sizeof(mbi)); - } while (mbi.Protect & PAGE_GUARD); - return Esp; - } - } else { - /* segment selectors don't match - thread is in some weird context */ - MEMORY_BASIC_INFORMATION mbi; - PBYTE pbStackHwm, pbStackBase; - SYSTEM_INFO si; - DWORD dwPageSize; - stackp_t stack_ptr = tid->stack_ptr; - - if (stack_ptr == 0) { - return 0; - } - GetSystemInfo(&si); - dwPageSize = si.dwPageSize; - VirtualQuery((PBYTE)stack_ptr - 1, &mbi, sizeof(mbi)); - pbStackBase = (PBYTE)mbi.AllocationBase; - /* step backwards till beginning of segment, non-RW page, or guard - page (guard pages only on WinNT) */ - do { - pbStackHwm = (PBYTE)mbi.BaseAddress; - if (pbStackHwm <= pbStackBase) { - break; - } - VirtualQuery(pbStackHwm - dwPageSize, &mbi, sizeof(mbi)); - } - while ((mbi.Protect & PAGE_READWRITE) && - !(mbi.Protect & PAGE_GUARD)); - /* the best we can do for now is the first page of stack - storage - it should be a stack high-water mark, anyway */ - return (void *)pbStackHwm; - } -#else - return 0; -#endif -} - -/* - * Get the end of stack (if you step beyond (above or below depending - * on your architecture) you can die. We refer to the logical top of - * stack. - * - * NOTE! There are restrictions about when you can call this method. If - * you did a sysThreadAlloc, then you can call this method as soon as - * sysThreadAlloc returns. If you called sysThreadCreate(start_function), - * then you must call sysThreadStackTop only inside start_function and not - * as soon as sysThreadCreate returns. - */ -void * -sysThreadStackTop(sys_thread_t *tid) -{ - return 0; /* FIXME: Unimplemented. */ -} - -long * -sysThreadRegs(sys_thread_t *tid, int *nregs) -{ - *nregs = N_TRACED_REGS; - return tid->regs; -} - -/* - * Thread start routine for new Java threads - */ -static unsigned __stdcall -_start(sys_thread_t *tid) -{ - /* Should thread suspend itself at this point? */ - - tid->state = RUNNABLE; - RecordNTTIB(tid); - TlsSetValue(tls_index, tid); - tid->stack_ptr = &tid; - tid->start_proc(tid->start_parm); - sysThreadFree(); - _endthreadex(0); - /* not reached */ - return 0; -} - -/* - * Create a new Java thread. The thread is initially suspended. - */ -int -sysThreadCreate(sys_thread_t **tidP, long stack_size, - void (*proc)(void *), void *arg) -{ - sys_thread_t *tid = allocThreadBlock(); - if (tid == NULL) { - return SYS_NOMEM; - } - tid->state = SUSPENDED; - tid->start_proc = proc; - tid->start_parm = arg; - - tid->interrupt_event = CreateEvent(NULL, TRUE, FALSE, NULL); - - /* - * Start the new thread. - */ - tid->handle = (HANDLE)_beginthreadex(NULL, stack_size, _start, tid, - CREATE_SUSPENDED, &tid->id); - if (tid->handle == 0) { - return SYS_NORESOURCE; /* Will be treated as though SYS_NOMEM */ - } - - queueInsert(tid); - *tidP = tid; - return SYS_OK; -} - -/* - * Free a system thread block. - * Remove from the thread queue. - */ -int -sysThreadFree() -{ - sys_thread_t *tid = sysThreadSelf(); - - /* - * remove ourselves from the thread queue. This must be done after - * the notify above since monitor operations aren't really safe if - * your thread isn't on the thread queue. (This isn't true of - * the sysMonitor* functions, only monitor*) - */ - SYS_QUEUE_LOCK(tid); - removefromActiveQ(tid); - SYS_QUEUE_UNLOCK(tid); - - /* For invocation API: later sysThreadSelf() calls will return 0 */ - TlsSetValue(tls_index, 0); - - /* - * Close the thread and interrupt event handles, and free the - * sys_thread_t structure. - */ - CloseHandle(tid->handle); - CloseHandle(tid->interrupt_event); - freeThreadBlock(tid); - return SYS_OK; -} - -/* - * Yield control to another thread. - */ -void -sysThreadYield(void) -{ - Sleep(0); -} - -/* - * Suspend execution of the specified thread. - */ -int -sysThreadSuspend(sys_thread_t *tid) -{ - /* REMIND: Fix for Win95 */ - /* Set state first so state is reflected before this thread */ - /* returns. Fix suggested by ARB of SAS */ - thread_state_t oldstate = tid->state; - sys_thread_t *self = sysThreadSelf(); - - if (tid == self) { - self->state = SUSPENDED; - } else { - switch(tid->state) { - case RUNNABLE: - tid->state = SUSPENDED; - break; - case MONITOR_WAIT: - tid->state = SUSPENDED; - tid->suspend_flags |= MONITOR_WAIT_SUSPENDED; - break; - case CONDVAR_WAIT: - tid->state = SUSPENDED; - tid->suspend_flags |= CONDVAR_WAIT_SUSPENDED; - break; - case SUSPENDED: - case MONITOR_SUSPENDED: - default: - return SYS_ERR; - } - } - if (SuspendThread(tid->handle) == 0xffffffffUL) { - tid->state = oldstate; - tid->suspend_flags = 0; - return SYS_ERR; - } - return SYS_OK; -} - -/* - * Continue execution of the specified thread. - */ -int -sysThreadResume(sys_thread_t *tid) -{ - unsigned long n; - - if (tid->suspend_flags & MONITOR_WAIT_SUSPENDED) { - tid->suspend_flags = 0; - tid->state = MONITOR_WAIT; - } else if (tid->suspend_flags & CONDVAR_WAIT_SUSPENDED) { - tid->suspend_flags = 0; - tid->state = CONDVAR_WAIT; - } else { - switch(tid->state) { - case SUSPENDED: - tid->state = RUNNABLE; - break; - case MONITOR_SUSPENDED: - tid->state = MONITOR_WAIT; - break; - case RUNNABLE: - case MONITOR_WAIT: - case CONDVAR_WAIT: - default: - return SYS_ERR; - break; - } - } - - /* Decrement thread's suspend count until no longer suspended */ - while ((n = ResumeThread(tid->handle)) > 1) { - if (n == 0xffffffffUL) { - return SYS_ERR; - } - } - return SYS_OK; -} - -/* - * Return priority of specified thread. - */ -int -sysThreadGetPriority(sys_thread_t *tid, int *pp) -{ - switch (GetThreadPriority(tid->handle)) { - case THREAD_PRIORITY_IDLE: - *pp = 0; break; - case THREAD_PRIORITY_LOWEST: - *pp = 2; break; - case THREAD_PRIORITY_BELOW_NORMAL: - *pp = 4; break; - case THREAD_PRIORITY_NORMAL: - *pp = 5; break; - case THREAD_PRIORITY_ABOVE_NORMAL: - *pp = 6; break; - case THREAD_PRIORITY_HIGHEST: - *pp = 8; break; - case THREAD_PRIORITY_TIME_CRITICAL: - *pp = 10; break; - case THREAD_PRIORITY_ERROR_RETURN: - return SYS_ERR; - } - return SYS_OK; -} - -/* - * Set priority of specified thread. - */ -int -sysThreadSetPriority(sys_thread_t *tid, int p) -{ - int priority; - - switch (p) { - case 0: - priority = THREAD_PRIORITY_IDLE; - break; - case 1: case 2: - priority = THREAD_PRIORITY_LOWEST; - break; - case 3: case 4: - priority = THREAD_PRIORITY_BELOW_NORMAL; - break; - case 5: - priority = THREAD_PRIORITY_NORMAL; - break; - case 6: case 7: - priority = THREAD_PRIORITY_ABOVE_NORMAL; - break; - case 8: case 9: - priority = THREAD_PRIORITY_HIGHEST; - break; - case 10: - priority = THREAD_PRIORITY_TIME_CRITICAL; - break; - default: - return SYS_ERR; - } - return SetThreadPriority(tid->handle, priority) ? SYS_OK : SYS_ERR; -} - -/* - * Return the thread information block of the calling thread. - */ -sys_thread_t * -sysThreadSelf(void) -{ - return tls_index == 0xffffffffUL ? 0 : TlsGetValue(tls_index); -} - -/* - * Enumerate over all threads in active queue calling a function for - * each one. Expects the caller to lock _queue_lock - */ -int -sysThreadEnumerateOver(int (*func)(sys_thread_t *, void *), void *arg) -{ - sys_thread_t *tid; - int ret = SYS_OK; - sys_thread_t *self = sysThreadSelf(); - - sysAssert(SYS_QUEUE_LOCKED(sysThreadSelf())); - - for (tid = ThreadQueue; tid != 0; tid = tid->next) { - if ((ret = (*func)(tid, arg)) != SYS_OK) { - break; - } - } - return ret; -} - -/* - * Helper function for sysThreadSingle() - */ -static int -threadSingleHelper(sys_thread_t *tid, void *self) -{ - if (tid == self) { - return SYS_OK; - } - if (SuspendThread(tid->handle) == 0xffffffffUL) { - return SYS_ERR; - } - { - CONTEXT context; - DWORD *esp = (DWORD *)tid->regs; - - context.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL; - if (!GetThreadContext(tid->handle, &context)) { - VM_CALL(jio_fprintf) - (stderr, "GetThreadContext failed (errcode = %x)\n", - GetLastError()); - return SYS_ERR; - } -#ifdef _M_AMD64 - *esp++ = context.Rax; - *esp++ = context.Rbx; - *esp++ = context.Rcx; - *esp++ = context.Rdx; - *esp++ = context.Rsi; - *esp++ = context.Rdi; - *esp = context.Rbp; -#else - *esp++ = context.Eax; - *esp++ = context.Ebx; - *esp++ = context.Ecx; - *esp++ = context.Edx; - *esp++ = context.Esi; - *esp++ = context.Edi; - *esp = context.Ebp; -#endif - } - return SYS_OK; -} - -/* - * Puts each thread in the active thread queue to sleep except for the - * calling thread. The threads must be later woken up with a corresponding - * call to 'sysThreadMulti'. Returns SYS_OK on success, or SYS_ERR if any - * of the threads could not be suspended. - */ -int -sysThreadSingle(void) -{ - return sysThreadEnumerateOver(threadSingleHelper, sysThreadSelf()); -} - -/* - * Helper function for sysThreadMulti(): Only ResumeThread once, unlike - * sysThreadResume(), which will repeatedly call ResumeThread until the - * thread is really resumed. That is, Thread.resume will unwind any - * number of Thread.suspend invocations, but sysThreadMulti() calls must - * be strictly matched with sysThreadSingle() calls. Doing this keeps - * the garbage collector, which uses thread suspension to stop threads - * while it operates, from waking up threads that were already suspended - * when GC was invoked. - */ -static int -threadMultiHelper(sys_thread_t *tid, void *self) -{ - if (tid == self || ResumeThread(tid->handle) != 0xffffffffUL) { - return SYS_OK; - } else { - return SYS_ERR; - } -} - -/* - * Wakes up each thread in active thread queue except for the calling - * thread. The mechanism uses thread suspension, and will not wake a - * thread that was already suspended. Must be matched 1-1 with calls - * to sysThreadSingle(). Returns SYS_ERR if not all threads could be - * woken up. - */ -void -sysThreadMulti(void) -{ - sysThreadEnumerateOver(threadMultiHelper, sysThreadSelf()); -} - -/* - * Dump system-specific information about threads. - */ -void * -sysThreadNativeID(sys_thread_t *tid) -{ - return (void *)(uintptr_t)tid->id; -} - -int -sysThreadCheckStack(void) -{ - return 1; -} - -/* - * The mechanics of actually signalling an exception (in the future, - * and Alarm or Interrupt) depend upon what thread implementation you - * are using. - */ -void -sysThreadPostException(sys_thread_t *tid, void *exc) -{ - /* Interrupt the thread if it's waiting; REMIND: race??? */ - SetEvent(tid->interrupt_event); -} - -/* - * Support for (Java-level) interrupts. - */ -void -sysThreadInterrupt(sys_thread_t *tid) -{ - if (tid->interrupted == FALSE) { - tid->interrupted = TRUE; - SetEvent(tid->interrupt_event); - } -} - -int -sysThreadIsInterrupted(sys_thread_t *tid, int ClearInterrupted) -{ - bool_t interrupted = tid->interrupted; - if (interrupted && ClearInterrupted) { - tid->interrupted = FALSE; - ResetEvent(tid->interrupt_event); - } - return interrupted; -} - -HPI_SysInfo * -sysGetSysInfo() -{ - static HPI_SysInfo info = {0, 0}; - - if (info.name == NULL) { - SYSTEM_INFO sysinfo; - GetSystemInfo(&sysinfo); - info.isMP = sysinfo.dwNumberOfProcessors > 1; - info.name = "native threads"; - } - return &info; -} - -#define FT2INT64(ft) \ - ((jlong)(ft).dwHighDateTime << 32 | (jlong)(ft).dwLowDateTime) - -jlong -sysThreadCPUTime() -{ - if (windowsNT) { - FILETIME CreationTime; - FILETIME ExitTime; - FILETIME KernelTime; - FILETIME UserTime; - - GetThreadTimes(GetCurrentThread(), - &CreationTime, &ExitTime, &KernelTime, &UserTime); - return FT2INT64(UserTime) * 100; - } else { - return (jlong)sysGetMilliTicks() * 1000000; - } -} - -int -sysThreadGetStatus(sys_thread_t *tid, sys_mon_t **monitorPtr) -{ - int status; - switch (tid->state) { - case RUNNABLE: - if (tid->enter_monitor) - status = SYS_THREAD_MONITOR_WAIT; - else - status = SYS_THREAD_RUNNABLE; - break; - case SUSPENDED: - if (tid->enter_monitor) - status = SYS_THREAD_SUSPENDED | SYS_THREAD_MONITOR_WAIT; - else if (tid->suspend_flags & CONDVAR_WAIT_SUSPENDED) - status = SYS_THREAD_SUSPENDED | SYS_THREAD_CONDVAR_WAIT; - else - status = SYS_THREAD_SUSPENDED; - break; - case MONITOR_SUSPENDED: - status = SYS_THREAD_SUSPENDED | SYS_THREAD_MONITOR_WAIT; - break; - case CONDVAR_WAIT: - status = SYS_THREAD_CONDVAR_WAIT; - break; - case MONITOR_WAIT: - /* - * this flag should never be in used on win32 since the - * state is actually signalled by setting self->enter_monitor - * to point at the monitor the thread is waiting to enter - */ - sysAssert(FALSE); - default: - return SYS_ERR; - } - if (monitorPtr) { - if (status & SYS_THREAD_MONITOR_WAIT) { - *monitorPtr = tid->enter_monitor; - } else if (status & SYS_THREAD_CONDVAR_WAIT) { - *monitorPtr = tid->wait_monitor; - } else { - *monitorPtr = NULL; - } - } - return status; -} - -int sysAdjustTimeSlice(int i) -{ - return JNI_ERR; -} - -void sysThreadProfSuspend(sys_thread_t *tid) -{ - SuspendThread(tid->handle); -} - -void sysThreadProfResume(sys_thread_t *tid) -{ - ResumeThread(tid->handle); -} - -bool_t sysThreadIsRunning(sys_thread_t *tid) -{ -#ifndef _M_AMD64 - unsigned int sum = 0; - unsigned int *p; - CONTEXT context; - - context.ContextFlags = CONTEXT_FULL; - GetThreadContext(tid->handle, &context); - p = &context.SegGs; - while (p <= &context.SegSs) { - sum += *p; - p++; - } - - if (sum == tid->last_sum) { - return FALSE; - } - tid->last_sum = sum; -#endif - return TRUE; -} - -void * -sysThreadInterruptEvent() -{ - return sysThreadSelf()->interrupt_event; -} diff --git a/src/windows/native/java/net/TwoStacksPlainSocketImpl.c b/src/windows/native/java/net/TwoStacksPlainSocketImpl.c index 792fc251d35af5a0828aeb08296487240db9bde7..71e2b2b124ec6df748b82cee001f4c07f1561800 100644 --- a/src/windows/native/java/net/TwoStacksPlainSocketImpl.c +++ b/src/windows/native/java/net/TwoStacksPlainSocketImpl.c @@ -1032,21 +1032,20 @@ Java_java_net_TwoStacksPlainSocketImpl_socketGetOption(JNIEnv *env, jobject this * SO_BINDADDR isn't a socket option */ if (opt == java_net_SocketOptions_SO_BINDADDR) { - SOCKET_ADDRESS him; + SOCKETADDRESS him; int len; int port; jobject iaObj; jclass iaCntrClass; jfieldID iaFieldID; - len = sizeof(struct sockaddr_in); + len = sizeof(him); if (fd == -1) { /* must be an IPV6 only socket. Case where both sockets are != -1 * is handled in java */ fd = getFD1 (env, this); - len = sizeof(struct SOCKADDR_IN6); } if (getsockname(fd, (struct sockaddr *)&him, &len) < 0) { diff --git a/src/windows/native/sun/java2d/windows/GDIBlitLoops.cpp b/src/windows/native/sun/java2d/windows/GDIBlitLoops.cpp index d9d2a000b96ab1be8fe48091a5b8b86fb6dc28b0..d3dc21dae146533964006b41f974c4143b6ee90b 100644 --- a/src/windows/native/sun/java2d/windows/GDIBlitLoops.cpp +++ b/src/windows/native/sun/java2d/windows/GDIBlitLoops.cpp @@ -107,8 +107,16 @@ Java_sun_java2d_windows_GDIBlitLoops_nativeBlit // could retain their own DIB info and we would not need to // recreate it every time. + // GetRasInfo implicitly calls GetPrimitiveArrayCritical + // and since GetDC uses JNI it needs to be called first. + HDC hDC = dstOps->GetDC(env, dstOps, 0, NULL, clip, NULL, 0); + if (hDC == NULL) { + SurfaceData_InvokeUnlock(env, srcOps, &srcInfo); + return; + } srcOps->GetRasInfo(env, srcOps, &srcInfo); if (srcInfo.rasBase == NULL) { + dstOps->ReleaseDC(env, dstOps, hDC); SurfaceData_InvokeUnlock(env, srcOps, &srcInfo); return; } @@ -174,13 +182,6 @@ Java_sun_java2d_windows_GDIBlitLoops_nativeBlit bmi.colors.dwMasks[2] = bmask; } - HDC hDC = dstOps->GetDC(env, dstOps, 0, NULL, clip, NULL, 0); - if (hDC == NULL) { - SurfaceData_InvokeRelease(env, srcOps, &srcInfo); - SurfaceData_InvokeUnlock(env, srcOps, &srcInfo); - return; - } - if (fastBlt) { // Window could go away at any time, leaving bits on the screen // from this GDI call, so make sure window still exists diff --git a/test/ProblemList.txt b/test/ProblemList.txt index be1f7850556264c091c21f0892cebd7991ddfc44..f2380764a1aed4e8ea3dacb3be281338c092d671 100644 --- a/test/ProblemList.txt +++ b/test/ProblemList.txt @@ -439,6 +439,9 @@ java/rmi/reliability/benchmark/runRmiBench.sh generic-all java/rmi/activation/rmidViaInheritedChannel/InheritedChannelNotServerSocket.java generic-all java/rmi/activation/rmidViaInheritedChannel/RmidViaInheritedChannel.java generic-all +java/rmi/transport/rapidExportUnexport/RapidExportUnexport.java generic-all +java/rmi/transport/dgcDeadLock/TestImpl_Stub.java generic-all + # Address already in use, othervm mode, solaris java/rmi/activation/Activatable/elucidateNoSuchMethod/ElucidateNoSuchMethod.java generic-all java/rmi/activation/Activatable/forceLogSnapshot/ForceLogSnapshot.java generic-all @@ -718,9 +721,6 @@ java/util/concurrent/ThreadPoolExecutor/CoreThreadTimeOut.java generic-all # 11 separate stacktraces created... file reuse problem? java/util/zip/ZipFile/ReadLongZipFileName.java generic-all -# Failing on all -client 32bit platforms starting with b77? See 6908348. -java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java generic-all - # Assert error, failures, on Linux Fedora 9 -server # Windows samevm failure, assert error "Passed = 134, failed = 2" java/util/Arrays/ArrayObjectMethods.java generic-all @@ -737,11 +737,5 @@ java/util/concurrent/locks/Lock/TimedAcquireLeak.java generic-all # Fails on solaris-sparc -server (Set not equal to copy. 1) java/util/EnumSet/EnumSetBash.java solaris-sparc -# Failing to close an input stream? "foo", triggers samevm windows failures -java/util/Formatter/Constructors.java generic-all - -# Need to be marked othervm, or changed to be samevm safe -java/util/WeakHashMap/GCDuringIteration.java generic-all - ############################################################################ diff --git a/test/com/sun/jdi/NativeInstanceFilter.java b/test/com/sun/jdi/NativeInstanceFilter.java new file mode 100644 index 0000000000000000000000000000000000000000..90e714e6889854edf50c42152c6d498f0c24ae0a --- /dev/null +++ b/test/com/sun/jdi/NativeInstanceFilter.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 6426034 + * @summary Instance filter doesn't filter event if it occurs in native method + * + * @author Keith McGuigan + * + * @library scaffold + * @run build JDIScaffold VMConnection + * @compile -XDignore.symbol.file NativeInstanceFilterTarg.java + * @run main/othervm NativeInstanceFilter + */ + +/* + * This test tests instance filters for events generated from a native method + */ + +import java.util.*; +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +public class NativeInstanceFilter extends JDIScaffold { + + static int unfilteredEvents = 0; + + public static void main(String args[]) throws Exception { + new NativeInstanceFilter().startTests(); + } + + public NativeInstanceFilter() { + super(); + } + + static EventRequestManager requestManager = null; + static MethodExitRequest request = null; + + private void listen() { + TargetAdapter adapter = new TargetAdapter() { + EventSet set = null; + ObjectReference instance = null; + + public boolean eventSetReceived(EventSet set) { + this.set = set; + return false; + } + + public boolean methodExited(MethodExitEvent event) { + String name = event.method().name(); + if (instance == null && name.equals("latch")) { + // Grab the instance (return value) and set up as filter + System.out.println("Setting up instance filter"); + instance = (ObjectReference)event.returnValue(); + requestManager.deleteEventRequest(request); + request = requestManager.createMethodExitRequest(); + request.addInstanceFilter(instance); + request.enable(); + } else if (instance != null && name.equals("intern")) { + // If not for the filter, this will be called twice + System.out.println("method exit event (String.intern())"); + ++unfilteredEvents; + } + set.resume(); + return false; + } + }; + addListener(adapter); + } + + + protected void runTests() throws Exception { + String[] args = new String[2]; + args[0] = "-connect"; + args[1] = "com.sun.jdi.CommandLineLaunch:main=NativeInstanceFilterTarg"; + + connect(args); + waitForVMStart(); + + // VM has started, but hasn't started running the test program yet. + requestManager = vm().eventRequestManager(); + ReferenceType referenceType = + resumeToPrepareOf("NativeInstanceFilterTarg").referenceType(); + + request = requestManager.createMethodExitRequest(); + request.enable(); + + listen(); + + vm().resume(); + + waitForVMDeath(); + + if (unfilteredEvents != 1) { + throw new Exception( + "Failed: Event from native frame not filtered out."); + } + System.out.println("Passed: Event filtered out."); + } +} diff --git a/test/com/sun/jdi/NativeInstanceFilterTarg.java b/test/com/sun/jdi/NativeInstanceFilterTarg.java new file mode 100644 index 0000000000000000000000000000000000000000..48a21b43aba50ccd399f294799e7bd8ee33f4346 --- /dev/null +++ b/test/com/sun/jdi/NativeInstanceFilterTarg.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import sun.misc.Version; + +public class NativeInstanceFilterTarg { + + public static void main(String args[]) { + boolean runTest = jvmSupportsJVMTI_12x(); + String s1 = "abc"; + String s2 = "def"; + latch(s1); + s1.intern(); + if (runTest) { + s2.intern(); // this is the call that generates events that ought + // to be filtered out. + } else { + System.out.println("Neutering test since JVMTI 1.2 not supported"); + } + } + + // Used by debugger to get an instance to filter with + public static String latch(String s) { return s; } + + public static boolean jvmSupportsJVMTI_12x() { + // This fix requires the JVM to support JVMTI 1.2, which doesn't + // happen until HSX 20.0, build 05. + int major = Version.jvmMajorVersion(); + int minor = Version.jvmMinorVersion(); + int micro = Version.jvmMicroVersion(); + int build = Version.jvmBuildNumber(); + + return (major > 20 || major == 20 && + (minor > 0 || micro > 0 || build >= 5)); + } +} diff --git a/test/com/sun/management/ThreadMXBean/ThreadAllocatedMemory.java b/test/com/sun/management/ThreadMXBean/ThreadAllocatedMemory.java new file mode 100644 index 0000000000000000000000000000000000000000..6a230c77eed6b3cec5d1aa28118f30e3652fcdcb --- /dev/null +++ b/test/com/sun/management/ThreadMXBean/ThreadAllocatedMemory.java @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6173675 + * @summary Basic test of ThreadMXBean.getThreadAllocatedBytes + * @author Paul Hohensee + */ + +import java.lang.management.*; + +public class ThreadAllocatedMemory { + private static com.sun.management.ThreadMXBean mbean = + (com.sun.management.ThreadMXBean)ManagementFactory.getThreadMXBean(); + private static boolean testFailed = false; + private static boolean done = false; + private static boolean done1 = false; + private static Object obj = new Object(); + private static final int NUM_THREADS = 10; + private static Thread[] threads = new Thread[NUM_THREADS]; + private static long[] sizes = new long[NUM_THREADS]; + + public static void main(String[] argv) + throws Exception { + + if (!mbean.isThreadAllocatedMemorySupported()) { + return; + } + + // disable allocated memory measurement + if (mbean.isThreadAllocatedMemoryEnabled()) { + mbean.setThreadAllocatedMemoryEnabled(false); + } + + if (mbean.isThreadAllocatedMemoryEnabled()) { + throw new RuntimeException( + "ThreadAllocatedMemory is expected to be disabled"); + } + + Thread curThread = Thread.currentThread(); + long id = curThread.getId(); + + long s = mbean.getThreadAllocatedBytes(id); + if (s != -1) { + throw new RuntimeException( + "Invalid ThreadAllocatedBytes returned = " + + s + " expected = -1"); + } + + // enable allocated memory measurement + if (!mbean.isThreadAllocatedMemoryEnabled()) { + mbean.setThreadAllocatedMemoryEnabled(true); + } + + if (!mbean.isThreadAllocatedMemoryEnabled()) { + throw new RuntimeException( + "ThreadAllocatedMemory is expected to be enabled"); + } + + long size = mbean.getThreadAllocatedBytes(id); + // implementation could have started measurement when + // measurement was enabled, in which case size can be 0 + if (size < 0) { + throw new RuntimeException( + "Invalid allocated bytes returned = " + size); + } + + doit(); + + // Expected to be size1 >= size + long size1 = mbean.getThreadAllocatedBytes(id); + if (size1 < size) { + throw new RuntimeException("Allocated bytes " + size1 + + " expected >= " + size); + } + System.out.println(curThread.getName() + + " Current thread allocated bytes = " + size + + " allocated bytes = " + size1); + + + // start threads, wait for them to block + for (int i = 0; i < NUM_THREADS; i++) { + threads[i] = new MyThread("MyThread-" + i); + threads[i].start(); + } + + // threads block after doing some allocation + waitUntilThreadBlocked(); + + for (int i = 0; i < NUM_THREADS; i++) { + sizes[i] = mbean.getThreadAllocatedBytes(threads[i].getId()); + } + + // let threads go and do some more allocation + synchronized (obj) { + done = true; + obj.notifyAll(); + } + + // wait for threads to get going again. we don't care if we + // catch them in mid-execution or if some of them haven't + // restarted after we're done sleeping. + goSleep(400); + + for (int i = 0; i < NUM_THREADS; i++) { + long newSize = mbean.getThreadAllocatedBytes(threads[i].getId()); + if (sizes[i] > newSize) { + throw new RuntimeException("TEST FAILED: " + + threads[i].getName() + + " previous allocated bytes = " + sizes[i] + + " > current allocated bytes = " + newSize); + } + System.out.println(threads[i].getName() + + " Previous allocated bytes = " + sizes[i] + + " Current allocated bytes = " + newSize); + } + + // let threads exit + synchronized (obj) { + done1 = true; + obj.notifyAll(); + } + + for (int i = 0; i < NUM_THREADS; i++) { + try { + threads[i].join(); + } catch (InterruptedException e) { + System.out.println("Unexpected exception is thrown."); + e.printStackTrace(System.out); + testFailed = true; + break; + } + } + if (testFailed) { + throw new RuntimeException("TEST FAILED"); + } + + System.out.println("Test passed"); + } + + + private static void goSleep(long ms) throws Exception { + try { + Thread.sleep(ms); + } catch (InterruptedException e) { + System.out.println("Unexpected exception is thrown."); + throw e; + } + } + + private static void waitUntilThreadBlocked() + throws Exception { + int count = 0; + while (count != NUM_THREADS) { + goSleep(100); + count = 0; + for (int i = 0; i < NUM_THREADS; i++) { + ThreadInfo info = mbean.getThreadInfo(threads[i].getId()); + if (info.getThreadState() == Thread.State.WAITING) { + count++; + } + } + } + } + + public static void doit() { + String tmp = ""; + long hashCode = 0; + for (int counter = 0; counter < 1000; counter++) { + tmp += counter; + hashCode = tmp.hashCode(); + } + System.out.println(Thread.currentThread().getName() + + " hashcode: " + hashCode); + } + + static class MyThread extends Thread { + public MyThread(String name) { + super(name); + } + + public void run() { + ThreadAllocatedMemory.doit(); + + synchronized (obj) { + while (!done) { + try { + obj.wait(); + } catch (InterruptedException e) { + System.out.println("Unexpected exception is thrown."); + e.printStackTrace(System.out); + testFailed = true; + break; + } + } + } + + long size1 = mbean.getThreadAllocatedBytes(getId()); + ThreadAllocatedMemory.doit(); + long size2 = mbean.getThreadAllocatedBytes(getId()); + + System.out.println(getName() + ": " + + "ThreadAllocatedBytes = " + size1 + + " ThreadAllocatedBytes = " + size2); + + if (size1 > size2) { + throw new RuntimeException("TEST FAILED: " + getName() + + " ThreadAllocatedBytes = " + size1 + + " > ThreadAllocatedBytes = " + size2); + } + + synchronized (obj) { + while (!done1) { + try { + obj.wait(); + } catch (InterruptedException e) { + System.out.println("Unexpected exception is thrown."); + e.printStackTrace(System.out); + testFailed = true; + break; + } + } + } + } + } +} diff --git a/test/com/sun/management/ThreadMXBean/ThreadAllocatedMemoryArray.java b/test/com/sun/management/ThreadMXBean/ThreadAllocatedMemoryArray.java new file mode 100644 index 0000000000000000000000000000000000000000..980189098cb483b95f74f62a13d666ad51104229 --- /dev/null +++ b/test/com/sun/management/ThreadMXBean/ThreadAllocatedMemoryArray.java @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6173675 + * @summary Basic test of ThreadMXBean.getThreadAllocatedBytes(long[]) + * @author Paul Hohensee + */ + +import java.lang.management.*; + +public class ThreadAllocatedMemoryArray { + private static com.sun.management.ThreadMXBean mbean = + (com.sun.management.ThreadMXBean)ManagementFactory.getThreadMXBean(); + private static boolean testFailed = false; + private static boolean done = false; + private static boolean done1 = false; + private static Object obj = new Object(); + private static final int NUM_THREADS = 10; + private static Thread[] threads = new Thread[NUM_THREADS]; + + public static void main(String[] argv) + throws Exception { + + if (!mbean.isThreadAllocatedMemorySupported()) { + return; + } + + + // start threads, wait for them to block + long[] ids = new long[NUM_THREADS]; + + for (int i = 0; i < NUM_THREADS; i++) { + threads[i] = new MyThread("MyThread-" + i); + threads[i].start(); + ids[i] = threads[i].getId(); + } + + waitUntilThreadBlocked(); + + + // disable allocated memory measurement + if (mbean.isThreadAllocatedMemoryEnabled()) { + mbean.setThreadAllocatedMemoryEnabled(false); + } + + if (mbean.isThreadAllocatedMemoryEnabled()) { + throw new RuntimeException( + "ThreadAllocatedMemory is expected to be disabled"); + } + + long sizes[] = mbean.getThreadAllocatedBytes(ids); + + if (sizes == null) { + throw new RuntimeException("Null ThreadAllocatedBytes array returned"); + } + + for (int i = 0; i < NUM_THREADS; i++) { + long s = sizes[i]; + if (s != -1) { + throw new RuntimeException( + "Invalid ThreadAllocatedBytes returned for thread " + + threads[i].getName() + " = " + s + " expected = -1"); + } + } + + // Enable allocated memory measurement + if (!mbean.isThreadAllocatedMemoryEnabled()) { + mbean.setThreadAllocatedMemoryEnabled(true); + } + + if (!mbean.isThreadAllocatedMemoryEnabled()) { + throw new RuntimeException( + "ThreadAllocatedMemory is expected to be enabled"); + } + + sizes = mbean.getThreadAllocatedBytes(ids); + + for (int i = 0; i < NUM_THREADS; i++) { + long s = sizes[i]; + if (s < 0) { + throw new RuntimeException( + "Invalid allocated bytes returned for thread " + + threads[i].getName() + " = " + s); + } + } + + // let threads go and do some more allocation + synchronized (obj) { + done = true; + obj.notifyAll(); + } + + // wait for threads to get going again. we don't care if we + // catch them in mid-execution or if some of them haven't + // restarted after we're done sleeping. + goSleep(400); + + long[] sizes1 = mbean.getThreadAllocatedBytes(ids); + + for (int i = 0; i < NUM_THREADS; i++) { + long newSize = sizes1[i]; + if (sizes[i] > newSize) { + throw new RuntimeException("TEST FAILED: " + + threads[i].getName() + + " previous allocated bytes = " + sizes[i] + + " > current allocated bytes = " + newSize); + } + System.out.println(threads[i].getName() + + " Previous allocated bytes = " + sizes[i] + + " Current allocated bytes = " + newSize); + } + + try { + sizes = mbean.getThreadAllocatedBytes(null); + } catch (NullPointerException e) { + System.out.println( + "Caught expected NullPointerException: " + e.getMessage()); + } + + try { + ids[0] = 0; + sizes = mbean.getThreadAllocatedBytes(ids); + } catch (IllegalArgumentException e) { + System.out.println( + "Caught expected IllegalArgumentException: " + e.getMessage()); + } + + + // let threads exit + synchronized (obj) { + done1 = true; + obj.notifyAll(); + } + + for (int i = 0; i < NUM_THREADS; i++) { + try { + threads[i].join(); + } catch (InterruptedException e) { + System.out.println("Unexpected exception is thrown."); + e.printStackTrace(System.out); + testFailed = true; + break; + } + } + + if (testFailed) { + throw new RuntimeException("TEST FAILED"); + } + + System.out.println("Test passed"); + } + + + private static void goSleep(long ms) throws Exception { + try { + Thread.sleep(ms); + } catch (InterruptedException e) { + System.out.println("Unexpected exception is thrown."); + throw e; + } + } + + private static void waitUntilThreadBlocked() + throws Exception { + int count = 0; + while (count != NUM_THREADS) { + goSleep(100); + count = 0; + for (int i = 0; i < NUM_THREADS; i++) { + ThreadInfo info = mbean.getThreadInfo(threads[i].getId()); + if (info.getThreadState() == Thread.State.WAITING) { + count++; + } + } + } + } + + public static void doit() { + String tmp = ""; + long hashCode = 0; + for (int counter = 0; counter < 1000; counter++) { + tmp += counter; + hashCode = tmp.hashCode(); + } + System.out.println(Thread.currentThread().getName() + + " hashcode: " + hashCode); + } + + static class MyThread extends Thread { + public MyThread(String name) { + super(name); + } + + public void run() { + ThreadAllocatedMemoryArray.doit(); + + synchronized (obj) { + while (!done) { + try { + obj.wait(); + } catch (InterruptedException e) { + System.out.println("Unexpected exception is thrown."); + e.printStackTrace(System.out); + testFailed = true; + break; + } + } + } + + ThreadAllocatedMemoryArray.doit(); + + synchronized (obj) { + while (!done1) { + try { + obj.wait(); + } catch (InterruptedException e) { + System.out.println("Unexpected exception is thrown."); + e.printStackTrace(System.out); + testFailed = true; + break; + } + } + } + + } + } +} diff --git a/test/com/sun/management/ThreadMXBean/ThreadCpuTimeArray.java b/test/com/sun/management/ThreadMXBean/ThreadCpuTimeArray.java new file mode 100644 index 0000000000000000000000000000000000000000..67dea226bd11cddeab952b8c98fa2e4c6c2ca28b --- /dev/null +++ b/test/com/sun/management/ThreadMXBean/ThreadCpuTimeArray.java @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6173675 + * @summary Basic test of ThreadMXBean.getThreadCpuTime(long[]) and + * getThreadUserTime(long[]). + * @author Paul Hohensee + */ + +import java.lang.management.*; + +public class ThreadCpuTimeArray { + private static com.sun.management.ThreadMXBean mbean = + (com.sun.management.ThreadMXBean)ManagementFactory.getThreadMXBean(); + private static boolean testFailed = false; + private static boolean done = false; + private static Object obj = new Object(); + private static final int NUM_THREADS = 10; + private static Thread[] threads = new Thread[NUM_THREADS]; + + // careful about this value + private static final int DELTA = 100; + + public static void main(String[] argv) + throws Exception { + + if (!mbean.isThreadCpuTimeSupported()) { + return; + } + + + // disable CPU time + if (mbean.isThreadCpuTimeEnabled()) { + mbean.setThreadCpuTimeEnabled(false); + } + + if (mbean.isThreadCpuTimeEnabled()) { + throw new RuntimeException("ThreadCpuTime is expected to be disabled"); + } + + // start threads, wait for them to block + long[] ids = new long[NUM_THREADS]; + + for (int i = 0; i < NUM_THREADS; i++) { + threads[i] = new MyThread("MyThread-" + i); + threads[i].start(); + ids[i] = threads[i].getId(); + } + + // threads block after doing some computation + waitUntilThreadBlocked(); + + + long times[] = mbean.getThreadCpuTime(ids); + long userTimes[] = mbean.getThreadUserTime(ids); + + if (times == null) { + throw new RuntimeException("Null ThreadCpuTime array returned"); + } + + for (int i = 0; i < NUM_THREADS; i++) { + long t = times[i]; + if (t != -1) { + throw new RuntimeException( + "Invalid ThreadCpuTime returned for thread " + + threads[i].getName() + " = " + t + " expected = -1"); + } + long ut = userTimes[i]; + if (ut != -1) { + throw new RuntimeException( + "Invalid ThreadUserTime returned for thread " + + threads[i].getName() + " = " + ut + " expected = -1"); + } + } + + + // Enable CPU Time measurement + if (!mbean.isThreadCpuTimeEnabled()) { + mbean.setThreadCpuTimeEnabled(true); + } + + if (!mbean.isThreadCpuTimeEnabled()) { + throw new RuntimeException("ThreadCpuTime is expected to be enabled"); + } + + times = mbean.getThreadCpuTime(ids); + userTimes = mbean.getThreadUserTime(ids); + + goSleep(200); + + for (int i = 0; i < NUM_THREADS; i++) { + long t = times[i]; + if (t < 0) { + throw new RuntimeException( + "Invalid CPU time returned for thread " + + threads[i].getName() + " = " + t); + } + long ut = userTimes[i]; + if (ut < 0) { + throw new RuntimeException( + "Invalid user time returned for thread " + + threads[i].getName() + " = " + ut); + } + } + + long[] times1 = mbean.getThreadCpuTime(ids); + long[] userTimes1 = mbean.getThreadUserTime(ids); + + for (int i = 0; i < NUM_THREADS; i++) { + long newTime = times1[i]; + long newUserTime = userTimes1[i]; + + if (times[i] > newTime) { + throw new RuntimeException("TEST FAILED: " + + threads[i].getName() + + " previous CPU time = " + times[i] + + " > current CPU time = " + newTime); + } + if ((times[i] + DELTA) < newTime) { + throw new RuntimeException("TEST FAILED: " + + threads[i].getName() + + " CPU time = " + newTime + + " previous CPU time " + times[i] + + " out of expected range"); + } + + System.out.println(threads[i].getName() + + " Previous Cpu Time = " + times[i] + + " Current CPU time = " + newTime); + + System.out.println(threads[i].getName() + + " Previous User Time = " + userTimes[i] + + " Current User time = " + newUserTime); + } + + + try { + times = mbean.getThreadCpuTime(null); + } catch (NullPointerException e) { + System.out.println( + "Caught expected NullPointerException: " + e.getMessage()); + } + + try { + ids[0] = 0; + times = mbean.getThreadCpuTime(ids); + } catch (IllegalArgumentException e) { + System.out.println( + "Caught expected IllegalArgumentException: " + e.getMessage()); + } + + + // let threads exit + synchronized (obj) { + done = true; + obj.notifyAll(); + } + + for (int i = 0; i < NUM_THREADS; i++) { + try { + threads[i].join(); + } catch (InterruptedException e) { + System.out.println("Unexpected exception is thrown."); + e.printStackTrace(System.out); + testFailed = true; + break; + } + } + + if (testFailed) { + throw new RuntimeException("TEST FAILED"); + } + + System.out.println("Test passed"); + } + + + private static void goSleep(long ms) throws Exception { + try { + Thread.sleep(ms); + } catch (InterruptedException e) { + System.out.println("Unexpected exception is thrown."); + throw e; + } + } + + private static void waitUntilThreadBlocked() + throws Exception { + int count = 0; + while (count != NUM_THREADS) { + goSleep(100); + count = 0; + for (int i = 0; i < NUM_THREADS; i++) { + ThreadInfo info = mbean.getThreadInfo(threads[i].getId()); + if (info.getThreadState() == Thread.State.WAITING) { + count++; + } + } + } + } + + public static void doit() { + double sum = 0; + for (int i = 0; i < 5000; i++) { + double r = Math.random(); + double x = Math.pow(3, r); + sum += x - r; + } + System.out.println(Thread.currentThread().getName() + + " sum = " + sum); + } + + static class MyThread extends Thread { + public MyThread(String name) { + super(name); + } + + public void run() { + ThreadCpuTimeArray.doit(); + + synchronized (obj) { + while (!done) { + try { + obj.wait(); + } catch (InterruptedException e) { + System.out.println("Unexpected exception is thrown."); + e.printStackTrace(System.out); + testFailed = true; + break; + } + } + } + + ThreadCpuTimeArray.doit(); + } + } +} diff --git a/test/com/sun/security/auth/module/LdapLoginModule/CheckConfigs.java b/test/com/sun/security/auth/module/LdapLoginModule/CheckConfigs.java index 12c1db497da199b58c5fa7d3d06e0f4f8659f1fb..f74e69079eda248eb4d5692b7dcb3cfc63f88cbc 100644 --- a/test/com/sun/security/auth/module/LdapLoginModule/CheckConfigs.java +++ b/test/com/sun/security/auth/module/LdapLoginModule/CheckConfigs.java @@ -178,7 +178,7 @@ class SearchFirstMode extends LdapConfiguration { public SearchFirstMode() { super(); - Map options = new HashMap(4); + Map options = new HashMap<>(4); options.put("userProvider", "ldap://localhost:23456/dc=example,dc=com"); options.put("userFilter", "(&(uid={USERNAME})(objectClass=inetOrgPerson))"); @@ -213,7 +213,7 @@ class AuthFirstMode extends LdapConfiguration { public AuthFirstMode() { super(); - Map options = new HashMap(5); + Map options = new HashMap<>(5); options.put("userProvider", "ldap://localhost:23456/dc=example,dc=com"); options.put("authIdentity", "{USERNAME}"); options.put("userFilter", @@ -248,7 +248,7 @@ class AuthOnlyMode extends LdapConfiguration { public AuthOnlyMode() { super(); - Map options = new HashMap(4); + Map options = new HashMap<>(4); options.put("userProvider", "ldap://localhost:23456 ldap://localhost:23457"); options.put("authIdentity", diff --git a/test/com/sun/security/auth/module/LdapLoginModule/CheckOptions.java b/test/com/sun/security/auth/module/LdapLoginModule/CheckOptions.java index fb175ca717abcfaedfa76ab98bea99372d89acdb..3f7d8e3bac237d9fd18ec7936faff45c38f2a214 100644 --- a/test/com/sun/security/auth/module/LdapLoginModule/CheckOptions.java +++ b/test/com/sun/security/auth/module/LdapLoginModule/CheckOptions.java @@ -73,7 +73,7 @@ public class CheckOptions { // bad value for userProvider option - Map options = new HashMap(); + Map options = new HashMap<>(); options.put(USER_PROVIDER_OPTION, "ldap://localhost:23456"); ldap.initialize(subject, null, null, options); @@ -93,7 +93,7 @@ public class CheckOptions { LdapLoginModule ldap = new LdapLoginModule(); Subject subject = new Subject(); - Map options = new HashMap(); + Map options = new HashMap<>(); ldap.initialize(subject, null, null, options); try { @@ -110,7 +110,7 @@ public class CheckOptions { LdapLoginModule ldap = new LdapLoginModule(); Subject subject = new Subject(); - Map options = new HashMap(); + Map options = new HashMap<>(); CallbackHandler goodHandler = new MyCallbackHandler(true); ldap.initialize(subject, goodHandler, null, options); diff --git a/test/demo/zipfs/PathOps.java b/test/demo/zipfs/PathOps.java index e31ffe96607d8257b50597a321bbbadf69083d6c..64b78e64ce442bad3cd85069b2221781adb216c1 100644 --- a/test/demo/zipfs/PathOps.java +++ b/test/demo/zipfs/PathOps.java @@ -193,6 +193,17 @@ public class PathOps { return this; } + PathOps isSameFile(String target) { + try { + out.println("check two paths are same"); + checkPath(); + check(path.isSameFile(test(target).path()), true); + } catch (IOException ioe) { + fail(); + } + return this; + } + PathOps invalid() { if (!(exc instanceof InvalidPathException)) { out.println("InvalidPathException not thrown as expected"); @@ -344,7 +355,12 @@ public class PathOps { .normalize("foo"); test("/foo/bar/gus/../..") .normalize("/foo"); - + test("/./.") + .normalize("/"); + test("/.") + .normalize("/"); + test("/./abc") + .normalize("/abc"); // invalid test("foo\u0000bar") .invalid(); @@ -365,6 +381,10 @@ public class PathOps { .root("/") .parent("/foo") .name("bar"); + + // isSameFile + test("/fileDoesNotExist") + .isSameFile("/fileDoesNotExist"); } static void npes() { diff --git a/test/demo/zipfs/ZipFSTester.java b/test/demo/zipfs/ZipFSTester.java index 8c5a104bac233a30910d122d1f12c1013273608f..d4c5b44007bcadeed00726e2436442e171673265 100644 --- a/test/demo/zipfs/ZipFSTester.java +++ b/test/demo/zipfs/ZipFSTester.java @@ -28,6 +28,7 @@ import java.nio.file.*; import java.nio.file.attribute.*; import java.net.*; import java.util.*; +import java.util.zip.*; import static java.nio.file.StandardOpenOption.*; import static java.nio.file.StandardCopyOption.*; @@ -42,7 +43,8 @@ public class ZipFSTester { FileSystem fs = null; try { fs = newZipFileSystem(Paths.get(args[0]), new HashMap()); - test(fs); + test0(fs); + test1(fs); test2(fs); // more tests } finally { if (fs != null) @@ -50,11 +52,31 @@ public class ZipFSTester { } } - static void test(FileSystem fs) + static void test0(FileSystem fs) throws Exception { - Random rdm = new Random(); + List list = new LinkedList<>(); + try (ZipFile zf = new ZipFile(fs.toString())) { + Enumeration zes = zf.entries(); + while (zes.hasMoreElements()) { + list.add(zes.nextElement().getName()); + } + for (String pname : list) { + Path path = fs.getPath(pname); + if (!path.exists()) + throw new RuntimeException("path existence check failed!"); + while ((path = path.getParent()) != null) { + if (!path.exists()) + throw new RuntimeException("parent existence check failed!"); + } + } + } + } + static void test1(FileSystem fs) + throws Exception + { + Random rdm = new Random(); // clone a fs and test on it Path tmpfsPath = getTempPath(); Map env = new HashMap(); diff --git a/test/demo/zipfs/basic.sh b/test/demo/zipfs/basic.sh index c6cfb77caf385fbb622da2fff7a319d20f569abd..a79cce34b6fd284c2fc03fec5103c62bb9bc083e 100644 --- a/test/demo/zipfs/basic.sh +++ b/test/demo/zipfs/basic.sh @@ -21,7 +21,7 @@ # questions. # # @test -# @bug 6990846 +# @bug 6990846 7009092 7009085 # @summary Test ZipFileSystem demo # @build Basic PathOps ZipFSTester # @run shell basic.sh diff --git a/test/java/awt/font/StyledMetrics/BoldSpace.java b/test/java/awt/font/StyledMetrics/BoldSpace.java new file mode 100644 index 0000000000000000000000000000000000000000..bbdff5feebede308183ee0c72ac3628eff4ad6ad --- /dev/null +++ b/test/java/awt/font/StyledMetrics/BoldSpace.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 6686365 7017637 + @summary Confirm that styling does not affect metrics of zero advance glyphs +*/ + +import java.awt.*; +import java.awt.image.*; + +public class BoldSpace { + public static void main(String[] s) { + BufferedImage bi = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB); + + String errMsg = "ZWJ Space char should have 0 advance\n"; + + Graphics g = bi.getGraphics(); + + // It turns out that some fonts inexplicably treat this as + // a standard character. In this 14 pt font, if we see an advance + // that's clearly bigger than we'd have introduced in bolding we'll + // not error out this test, presuming that its a consequence of + // the actual font data. A Linux font 'TLwg Type Bold' is the case + // in point. + int errorMargin = 4; + g.setFont(new Font("monospaced", Font.BOLD, 14)); + //g.setFont(new Font("Lucida Sans Regular", Font.BOLD, 14)); + FontMetrics fm = g.getFontMetrics(); + System.out.println("Bold: " + fm.charWidth('\u200b')); + int cwid = fm.charWidth('\u200b'); + if (cwid > 0 && cwid < errorMargin) { + throw new RuntimeException(errMsg); + } + + ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, + RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB); + fm = g.getFontMetrics(); + System.out.println("Bold + LCD: "+fm.charWidth('\u200b')); + cwid = fm.charWidth('\u200b'); + if (cwid > 0 && cwid < errorMargin) { + throw new RuntimeException(errMsg); + } + + + ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, + RenderingHints.VALUE_FRACTIONALMETRICS_ON); + ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, + RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + fm = g.getFontMetrics(); + System.out.println("Bold FM OFF + AA: " + fm.charWidth('\u200b')); + cwid = fm.charWidth('\u200b'); + if (cwid > 0 && cwid < errorMargin) { + throw new RuntimeException(errMsg); + } + + ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, + RenderingHints.VALUE_FRACTIONALMETRICS_OFF); + ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, + RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + fm = g.getFontMetrics(); + System.out.println("Bold FM ON + AA: " + fm.charWidth('\u200b')); + cwid = fm.charWidth('\u200b'); + if (cwid > 0 && cwid < errorMargin) { + throw new RuntimeException(errMsg); + } + + ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, + RenderingHints.VALUE_FRACTIONALMETRICS_ON); + ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, + RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); + fm = g.getFontMetrics(); + System.out.println("Bold FM ON + nonAA: " + fm.charWidth('\u200b')); + cwid = fm.charWidth('\u200b'); + if (cwid > 0 && cwid < errorMargin) { + throw new RuntimeException(errMsg); + } + + System.out.println("All printed values should be 0 to PASS"); + } +} diff --git a/test/java/awt/print/PrinterJob/ImagePrinting/ImageTypes.java b/test/java/awt/print/PrinterJob/ImagePrinting/ImageTypes.java new file mode 100644 index 0000000000000000000000000000000000000000..b8536c09e9c493ed9d7c6a60001fde28d3615c25 --- /dev/null +++ b/test/java/awt/print/PrinterJob/ImagePrinting/ImageTypes.java @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * + * @test + * @bug 4521945 7006865 + * @summary Test printing images of different types. + * @author prr + * @run main/manual=yesno/timeout=900 ImageTypes + */ + +import java.io.*; +import static java.awt.Color.*; +import java.awt.*; +import java.awt.geom.*; +import java.awt.event.*; +import java.awt.print.*; +import java.awt.image.*; +import static java.awt.image.BufferedImage.*; +import javax.print.*; +import javax.print.attribute.*; +import javax.print.attribute.standard.*; + +public class ImageTypes extends Frame implements ActionListener { + + private ImageCanvas c; + + public static void main(String args[]) { + + ImageTypes f = new ImageTypes(); + f.show(); + } + + public ImageTypes () { + super("Image Types Printing Test"); + c = new ImageCanvas(); + add("Center", c); + + Button printThisButton = new Button("Print"); + printThisButton.addActionListener(this); + Panel p = new Panel(); + p.add(printThisButton); + add("South", p); + add("North", getInstructions()); + addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + System.exit(0); + } + }); + + pack(); + } + + private TextArea getInstructions() { + TextArea ta = new TextArea(10, 60); + ta.setFont(new Font("Dialog", Font.PLAIN, 11)); + ta.setText + ("This is a manual test as it requires that you compare "+ + "the on-screen rendering with the printed output.\n"+ + "Select the 'Print' button to print out the test.\n"+ + "For each image compare the printed one to the on-screen one.\n"+ + "The test PASSES if the onscreen and printed rendering match."); + return ta; + } + + public void actionPerformed(ActionEvent e) { + PrinterJob pj = PrinterJob.getPrinterJob(); + + PrintRequestAttributeSet attrs = new HashPrintRequestAttributeSet(); + if (pj != null && pj.printDialog(attrs)) { + pj.setPrintable(c); + try { + pj.print(attrs); + } catch (PrinterException pe) { + pe.printStackTrace(); + throw new RuntimeException("Exception whilst printing."); + } finally { + System.out.println("PRINT RETURNED OK."); + } + } + } +} + +class ImageCanvas extends Component implements Printable { + + IndexColorModel icm2 = null; + IndexColorModel icm4 = null; + BufferedImage opaqueImg = null; + BufferedImage transImg = null; + int sw=99, sh=99; + + void paintImage(BufferedImage bi, Color c1, Color c2) { + + GradientPaint tp= new GradientPaint(0.0f, 0.0f, c1, 10f, 8f, c2, true); + Graphics2D g2d = (Graphics2D)bi.getGraphics(); + g2d.setPaint(tp); + g2d.fillRect(0, 0, sw, sh); + g2d.setColor(gray); + int cnt=0; + Font font = new Font("Serif", Font.PLAIN, 11); + g2d.setFont(font); + FontMetrics fm = g2d.getFontMetrics(); + for (int y=12;y 0) { + return Printable.NO_SUCH_PAGE; + } + Graphics2D g2d = (Graphics2D)g; + g2d.translate(pgFmt.getImageableX(), pgFmt.getImageableY()); + paint(g2d); + return Printable.PAGE_EXISTS; + } + + private void drawImage(Graphics g, int biType, IndexColorModel icm) { + + BufferedImage bi; + if (icm != null) { + bi = new BufferedImage(sw, sh, biType, icm); + } else { + bi = new BufferedImage(sw, sh, biType); + } + + Graphics big = bi.getGraphics(); + if (bi.getColorModel().getPixelSize() <=2) { + big.drawImage(opaqueImg, 0, 0, null); + } else { + big.drawImage(transImg, 0, 0, null); + } + g.drawImage(bi, 0, 0, null); + } + + public void paint(Graphics g) { + + int incX = sw+10, incY = sh+10; + + g.translate(10, 10); + + drawImage(g, TYPE_INT_RGB, null); + g.translate(incX, 0); + + drawImage(g, TYPE_INT_BGR, null); + g.translate(incX, 0); + + drawImage(g, TYPE_INT_ARGB, null); + g.translate(incX, 0); + + drawImage(g, TYPE_INT_ARGB_PRE, null); + g.translate(-3*incX, incY); + + drawImage(g, TYPE_3BYTE_BGR, null); + g.translate(incX, 0); + + drawImage(g, TYPE_4BYTE_ABGR, null); + g.translate(incX, 0); + + drawImage(g, TYPE_4BYTE_ABGR_PRE, null); + g.translate(incX, 0); + + drawImage(g, TYPE_USHORT_555_RGB, null); + g.translate(-3*incX, incY); + + drawImage(g, TYPE_USHORT_555_RGB, null); + g.translate(incX, 0); + + drawImage(g, TYPE_USHORT_GRAY, null); + g.translate(incX, 0); + + drawImage(g, TYPE_BYTE_GRAY, null); + g.translate(incX, 0); + + drawImage(g, TYPE_BYTE_INDEXED, null); + g.translate(-3*incX, incY); + + drawImage(g, TYPE_BYTE_BINARY, null); + g.translate(incX, 0); + + drawImage(g, TYPE_BYTE_BINARY, icm2); + g.translate(incX, 0); + + drawImage(g, TYPE_BYTE_BINARY, icm4); + g.translate(incX, 0); + + drawImage(g, TYPE_BYTE_INDEXED, icm2); + g.translate(-3*incX, incY); + + drawImage(g, TYPE_BYTE_INDEXED, icm4); + g.translate(incX, 0); + } + + + + /* Size is chosen to match default imageable width of a NA letter + * page. This means there will be clipping, what is clipped will + * depend on PageFormat orientation. + */ + public Dimension getPreferredSize() { + return new Dimension(468, 600); + } + +} diff --git a/test/java/io/PrintStream/FailingConstructors.java b/test/java/io/PrintStream/FailingConstructors.java new file mode 100644 index 0000000000000000000000000000000000000000..1022bb9d311e39c17632d2451ba4f36f8de2a441 --- /dev/null +++ b/test/java/io/PrintStream/FailingConstructors.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 7000511 + * @summary PrintStream, PrintWriter, Formatter, Scanner leave files open when + * exception thrown + */ + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.PrintStream; +import java.io.UnsupportedEncodingException; + +public class FailingConstructors { + static final String fileName = "FailingConstructorsTest"; + static final String UNSUPPORTED_CHARSET = "unknownCharset"; + static final String FILE_CONTENTS = "This is a small file!"; + + private static void realMain(String[] args) throws Throwable { + test(false, new File(fileName)); + + /* create the file and write its contents */ + File file = File.createTempFile(fileName, null); + file.deleteOnExit(); + FileOutputStream fos = new FileOutputStream(file); + fos.write(FILE_CONTENTS.getBytes()); + fos.close(); + + test(true, file); + file.delete(); + } + + private static void test(boolean exists, File file) throws Throwable { + /* PrintStream(File file, String csn) */ + try { + new PrintStream(file, UNSUPPORTED_CHARSET); + fail(); + } catch(FileNotFoundException|UnsupportedEncodingException e) { + pass(); + } + + check(exists, file); + + try { + new PrintStream(file, null); + fail(); + } catch(FileNotFoundException|NullPointerException e) { + pass(); + } + + check(exists, file); + + /* PrintStream(String fileName, String csn) */ + try { + new PrintStream(file.getName(), UNSUPPORTED_CHARSET); + fail(); + } catch(FileNotFoundException|UnsupportedEncodingException e) { + pass(); + } + + check(exists, file); + + try { + new PrintStream(file.getName(), null); + fail(); + } catch(FileNotFoundException|NullPointerException e) { + pass(); + } + + check(exists, file); + } + + private static void check(boolean exists, File file) { + if (exists) { + /* the file should be unchanged */ + verifyContents(file); + } else { + /* the file should not have been created */ + if (file.exists()) { fail(file + " should not have been created"); } + } + } + + private static void verifyContents(File file) { + try (FileInputStream fis = new FileInputStream(file)) { + byte[] contents = FILE_CONTENTS.getBytes(); + int read, count = 0; + while ((read = fis.read()) != -1) { + if (read != contents[count++]) { + fail("file contents have been altered"); + return; + } + } + } catch (IOException ioe) { + unexpected(ioe); + } + } + + //--------------------- Infrastructure --------------------------- + static volatile int passed = 0, failed = 0; + static void pass() {passed++;} + static void fail() {failed++; Thread.dumpStack();} + static void fail(String message) {System.out.println(message); fail(); } + static void unexpected(Throwable t) {failed++; t.printStackTrace();} + public static void main(String[] args) throws Throwable { + try {realMain(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +} diff --git a/test/java/io/PrintWriter/FailingConstructors.java b/test/java/io/PrintWriter/FailingConstructors.java new file mode 100644 index 0000000000000000000000000000000000000000..af4fa108473b99d3e5ca439232cbbb15ee158192 --- /dev/null +++ b/test/java/io/PrintWriter/FailingConstructors.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 7000511 + * @summary PrintStream, PrintWriter, Formatter, Scanner leave files open when + * exception thrown + */ + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; + +public class FailingConstructors { + static final String fileName = "FailingConstructorsTest"; + static final String UNSUPPORTED_CHARSET = "unknownCharset"; + static final String FILE_CONTENTS = "This is a small file!"; + + private static void realMain(String[] args) throws Throwable { + test(false, new File(fileName)); + + /* create the file and write its contents */ + File file = File.createTempFile(fileName, null); + file.deleteOnExit(); + FileOutputStream fos = new FileOutputStream(file); + fos.write(FILE_CONTENTS.getBytes()); + fos.close(); + + test(true, file); + file.delete(); + } + + private static void test(boolean exists, File file) throws Throwable { + /* PrintWriter(File file, String csn) */ + try { + new PrintWriter(file, UNSUPPORTED_CHARSET); + fail(); + } catch(FileNotFoundException|UnsupportedEncodingException e) { + pass(); + } + + check(exists, file); + + try { + new PrintWriter(file, null); + fail(); + } catch(FileNotFoundException|NullPointerException e) { + pass(); + } + + check(exists, file); + + /* PrintWriter(String fileName, String csn) */ + try { + new PrintWriter(file.getName(), UNSUPPORTED_CHARSET); + fail(); + } catch(FileNotFoundException|UnsupportedEncodingException e) { + pass(); + } + + check(exists, file); + + try { + new PrintWriter(file.getName(), null); + fail(); + } catch(FileNotFoundException|NullPointerException e) { + pass(); + } + + check(exists, file); + } + + private static void check(boolean exists, File file) { + if (exists) { + /* the file should be unchanged */ + verifyContents(file); + } else { + /* the file should not have been created */ + if (file.exists()) { fail(file + " should not have been created"); } + } + } + + private static void verifyContents(File file) { + try (FileInputStream fis = new FileInputStream(file)) { + byte[] contents = FILE_CONTENTS.getBytes(); + int read, count = 0; + while ((read = fis.read()) != -1) { + if (read != contents[count++]) { + fail("file contents have been altered"); + return; + } + } + } catch (IOException ioe) { + unexpected(ioe); + } + } + + //--------------------- Infrastructure --------------------------- + static volatile int passed = 0, failed = 0; + static void pass() {passed++;} + static void fail() {failed++; Thread.dumpStack();} + static void fail(String message) {System.out.println(message); fail(); } + static void unexpected(Throwable t) {failed++; t.printStackTrace();} + public static void main(String[] args) throws Throwable { + try {realMain(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +} diff --git a/test/java/net/InetAddress/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor b/test/java/net/InetAddress/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor deleted file mode 100644 index efcf23784824b62a19b70cd47a2636fc1fe54f68..0000000000000000000000000000000000000000 --- a/test/java/net/InetAddress/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor +++ /dev/null @@ -1,2 +0,0 @@ -Simple1NameServiceDescriptor -Simple2NameServiceDescriptor diff --git a/test/java/net/NetworkInterface/Equals.java b/test/java/net/NetworkInterface/Equals.java new file mode 100644 index 0000000000000000000000000000000000000000..003fb7113ab9fb45a1e674d99c4bbc213e91d11e --- /dev/null +++ b/test/java/net/NetworkInterface/Equals.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 7003398 + * @run main/othervm Equals + */ +import java.net.NetworkInterface; +import java.net.InetAddress; +import java.util.Enumeration; +import java.util.HashMap; + +public class Equals { + + public static void main(String args[]) throws Exception { + + Enumeration nifs1 = NetworkInterface.getNetworkInterfaces(); + HashMap hashes = new HashMap<>(); + HashMap nicMap = new HashMap<>(); + + while (nifs1.hasMoreElements()) { + NetworkInterface ni = (NetworkInterface)nifs1.nextElement(); + hashes.put(ni.getName(),ni.hashCode()); + nicMap.put(ni.getName(),ni); + } + + System.setSecurityManager(new SecurityManager()); + + Enumeration nifs2 = NetworkInterface.getNetworkInterfaces(); + while (nifs2.hasMoreElements()) { + NetworkInterface ni = (NetworkInterface)nifs2.nextElement(); + NetworkInterface niOrig = nicMap.get(ni.getName()); + + int h = hashes.get(ni.getName()); + if (h != ni.hashCode()) { + throw new RuntimeException ("Hashcodes different for " + + ni.getName()); + } + if (!ni.equals(niOrig)) { + throw new RuntimeException ("equality different for " + + ni.getName()); + } + } + } +} diff --git a/test/java/net/Socks/SocksProxyVersion.java b/test/java/net/Socks/SocksProxyVersion.java new file mode 100644 index 0000000000000000000000000000000000000000..19298e59c6b095a01725eafbc8c76386bece7bf7 --- /dev/null +++ b/test/java/net/Socks/SocksProxyVersion.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6964547 + * @run main/othervm SocksProxyVersion + * @summary test socksProxyVersion system property + */ + +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketException; +import java.io.DataInputStream; +import java.io.IOException; + +public class SocksProxyVersion implements Runnable { + ServerSocket ss; + volatile boolean failed; + + public static void main(String[] args) throws Exception { + new SocksProxyVersion(); + } + + public SocksProxyVersion() throws Exception { + ss = new ServerSocket(0); + int port = ss.getLocalPort(); + Thread serverThread = new Thread(this); + serverThread.start(); + + System.setProperty("socksProxyHost", "localhost"); + System.setProperty("socksProxyPort", Integer.toString(port)); + + // SOCKS V4 + System.setProperty("socksProxyVersion", Integer.toString(4)); + try (Socket s = new Socket()) { + s.connect(new InetSocketAddress("localhost", port)); + } catch (SocketException e) { + // java.net.SocketException: Malformed reply from SOCKS server + // This exception is OK, since the "server" does not implement + // the socks protocol. It just verifies the version and closes. + } + + // SOCKS V5 + System.setProperty("socksProxyVersion", Integer.toString(5)); + try (Socket s = new Socket()) { + s.connect(new InetSocketAddress("localhost", port)); + } catch (SocketException e) { /* OK */ } + + serverThread.join(); + if (failed) { + throw new RuntimeException("socksProxyVersion not being set correctly"); + } + } + + public void run() { + try (ss) { + Socket s = ss.accept(); + int version = (s.getInputStream()).read(); + if (version != 4) { + System.out.println("Got " + version + ", expected 4"); + failed = true; + } + s.close(); + + s = ss.accept(); + version = (s.getInputStream()).read(); + if (version != 5) { + System.out.println("Got " + version + ", expected 5"); + failed = true; + } + s.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/test/java/net/URLClassLoader/B6896088.java b/test/java/net/URLClassLoader/B6896088.java new file mode 100644 index 0000000000000000000000000000000000000000..4e0792b034517bb35e4699cd7ac50470e5a0976c --- /dev/null +++ b/test/java/net/URLClassLoader/B6896088.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 6896088 + * @run main/othervm B6896088 + * @summary URLClassLoader.close() apparently not working for JAR URLs on Windows + */ + +import java.net.*; +import java.io.*; +import java.nio.file.Path; + +public class B6896088 { + + public static void main(String[] args) throws Exception { + + String dir = System.getProperty ("test.classes"); + File jarf = new File (dir, "foo.jar"); + FileOutputStream fos = new FileOutputStream (jarf); + fos.write(bytes(nums)); + fos.close(); + + // Create URL using JAR protocol + String jarName = (jarf.toURI()).toString(); + URL url = new URL("jar", "", jarName + "!/"); + + // Create URLClassLoader from the URL + URLClassLoader loader = new URLClassLoader(new URL[]{url}); + Class c = loader.loadClass("Foo"); + + // Close the URLClassLoader so we can delete/update the jar file + loader.close(); + + // Now try to delete the jar file + + if (jarf.delete() && !jarf.exists()) { + System.out.println(jarf.getName()+" File Deleted"); + } else { + System.out.println(jarf.getName()+" File Not Deleted"); + throw new RuntimeException ("File not deleted"); + } + } + + static byte[] bytes (int[] i) { + byte[] buf = new byte [i.length]; + + for (int j=0; j= 0) { - o.write (buf, 0, count); - } - i.close(); - o.close(); - } catch (IOException e) { - throw new RuntimeException (e); - } - } - - static void rm_minus_rf (File path) { - if (!path.exists()) { - return; - } - if (path.isFile()) { - if (!path.delete()) { - throw new RuntimeException ("Could not delete " + path); - } - } else if (path.isDirectory ()) { - String[] names = path.list(); - File[] files = path.listFiles(); - for (int i=0; i= 0) { + o.write (buf, 0, count); + } + i.close(); + o.close(); + } catch (IOException e) { + throw new RuntimeException (e); + } + } + + static void rm_minus_rf (File path) { + if (!path.exists()) { + return; + } + if (path.isFile()) { + if (!path.delete()) { + throw new RuntimeException ("Could not delete " + path); + } + } else if (path.isDirectory ()) { + String[] names = path.list(); + File[] files = path.listFiles(); + for (int i=0; i ${TESTCLASSES}/test3/hello.txt +echo "Bye world" > ${TESTCLASSES}/test3/bye.txt +cp ${TESTSRC}/test1/com/foo/TestClass.java ${TESTCLASSES}/test3 +cd ${TESTCLASSES}/test3 +${JAVAC} -d . TestClass.java + +${JAR} cvf foo.jar hello.txt bye.txt com/foo/TestClass.class +rm -f ../foo.jar +mv foo.jar .. diff --git a/test/java/util/Formatter/Constructors.java b/test/java/util/Formatter/Constructors.java index 3748b5d123d08cd927e7a93ab324ec4a6added06..c542e1bbfb807f50f3742456b3281d4094256424 100644 --- a/test/java/util/Formatter/Constructors.java +++ b/test/java/util/Formatter/Constructors.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,7 +22,7 @@ */ /* @test - * @bug 4981811 4984465 5064492 6240171 + * @bug 4981811 4984465 5064492 6240171 7000511 * @summary Unit test for all constructors introduced by the formatter feature */ @@ -85,10 +85,8 @@ public class Constructors { } public static void main(String [] args) { - // Formatter() - try { - Formatter f = new Formatter(); + try (Formatter f = new Formatter()) { pass(); out(f, StringBuilder.class); locale(f); @@ -97,8 +95,7 @@ public class Constructors { } // Formatter(Appendable a) - try { - Formatter f = new Formatter((Appendable) null); + try (Formatter f = new Formatter((Appendable) null)) { pass(); out(f, StringBuilder.class); locale(f); @@ -107,8 +104,7 @@ public class Constructors { } // Formatter(Locale l) - try { - Formatter f = new Formatter((Locale) null); + try (Formatter f = new Formatter((Locale) null)) { pass(); out(f, StringBuilder.class); locale(f, null); @@ -117,8 +113,7 @@ public class Constructors { } // Formatter(Appendable a, Locale l) - try { - Formatter f = new Formatter((Appendable) null, (Locale) null); + try (Formatter f = new Formatter((Appendable) null, (Locale) null)) { pass(); out(f, StringBuilder.class); locale(f, null); @@ -127,8 +122,7 @@ public class Constructors { } // Formatter(String fileName) - try { - Formatter f = new Formatter("foo"); + try (Formatter f = new Formatter("foo")) { pass(); out(f, BufferedWriter.class); locale(f); @@ -137,7 +131,7 @@ public class Constructors { } try { - Formatter f = new Formatter((String)null); + new Formatter((String)null); fail("new Formatter((String)null)"); } catch (NullPointerException x) { pass(); @@ -146,8 +140,7 @@ public class Constructors { } // Formatter(String fileName, String csn) - try { - Formatter f = new Formatter("foo", "UTF-8"); + try (Formatter f = new Formatter("foo", "UTF-8")) { pass(); out(f, BufferedWriter.class); locale(f); @@ -167,15 +160,14 @@ public class Constructors { try { new Formatter(".", "bar"); fail("new Formatter(\".\", \"bar\")"); - } catch (FileNotFoundException x) { + } catch (FileNotFoundException|UnsupportedEncodingException x) { pass(); } catch (Exception x) { fail("new Formatter(\".\", \"bar\")", x); } // Formatter(String fileName, String csn, Locale l) - try { - Formatter f = new Formatter("foo", "ISO-8859-1", Locale.GERMANY); + try (Formatter f = new Formatter("foo", "ISO-8859-1", Locale.GERMANY)) { pass(); out(f, BufferedWriter.class); locale(f, Locale.GERMANY); @@ -183,8 +175,7 @@ public class Constructors { fail("new Formatter(\"foo\", \"ISO-8859-1\", Locale.GERMANY)", x); } - try { - Formatter f = new Formatter("foo", "ISO-8859-1", null); + try (Formatter f = new Formatter("foo", "ISO-8859-1", null)) { pass(); locale(f, null); out(f, BufferedWriter.class); @@ -193,8 +184,7 @@ public class Constructors { } // Formatter(File) - try { - Formatter f = new Formatter(new File("foo")); + try (Formatter f = new Formatter(new File("foo"))) { pass(); locale(f); out(f, BufferedWriter.class); @@ -203,7 +193,7 @@ public class Constructors { } try { - Formatter f = new Formatter((File)null); + new Formatter((File)null); fail("new Formatter((File)null)"); } catch (NullPointerException x) { pass(); @@ -231,8 +221,7 @@ public class Constructors { fail("new Formatter((PrintStream) null)", x); } - try { - Formatter f = new Formatter(new PrintStream("foo")); + try (Formatter f = new Formatter(new PrintStream("foo"))) { pass(); locale(f); out(f, PrintStream.class); @@ -242,9 +231,8 @@ public class Constructors { fail("new Formatter(new PrintStream(\"foo\")", x); } - try { - Formatter f = new Formatter(new PrintStream("foo"), - Locale.JAPANESE); + try (Formatter f = new Formatter(new PrintStream("foo"), + Locale.JAPANESE)) { pass(); locale(f, Locale.JAPANESE); out(f, PrintStream.class); @@ -254,12 +242,11 @@ public class Constructors { fail("new Formatter(new PrintStream(\"foo\")", x); } - try { + try (PrintStream ps = new PrintStream("foo")) { // The cast here is necessary to avoid an ambiguity error // between Formatter(Appendable a, Locale l) - // and Formatter(OutputStream os, String csn) - Formatter f = new Formatter(new PrintStream("foo"), - (String)null); + // and Formatter(OutputStream os, String csn) + new Formatter(ps, (String)null); fail("new Formatter(new PrintStream(\"foo\"), (String)null)"); } catch (FileNotFoundException x) { fail("new Formatter(new PrintStream(\"foo\"), (String)null)", x); @@ -271,12 +258,11 @@ public class Constructors { fail("new Formatter(new PrintStream(\"foo\"), (String)null)", x); } - try { - // The cast here is necessary to avoid an ambiguity error - // between Formatter(Appendable a, Locale l) - // and Formatter(OutputStream os, String csn) - Formatter f = new Formatter(new PrintStream("foo"), - (Locale)null); + // The cast here is necessary to avoid an ambiguity error + // between Formatter(Appendable a, Locale l) + // and Formatter(OutputStream os, String csn) + try (Formatter f = new Formatter(new PrintStream("foo"), + (Locale)null)) { pass(); locale(f, null); out(f, PrintStream.class); @@ -286,9 +272,8 @@ public class Constructors { fail("new Formatter(new PrintStream(\"foo\"), (Locale)null)", x); } - try { - Formatter f = new Formatter(new PrintStream("foo"), - Locale.KOREAN); + try (Formatter f = new Formatter(new PrintStream("foo"), + Locale.KOREAN)) { pass(); locale(f, Locale.KOREAN); out(f, PrintStream.class); @@ -298,9 +283,8 @@ public class Constructors { fail("new Formatter(new PrintStream(\"foo\"), Locale.KOREAN)", x); } - try { - Formatter f = new Formatter(new PrintStream("foo"), - "UTF-16BE", null); + try (Formatter f = new Formatter(new PrintStream("foo"), + "UTF-16BE", null)) { pass(); locale(f, null); out(f, BufferedWriter.class); @@ -312,9 +296,8 @@ public class Constructors { fail("new Formatter(new PrintStream(\"foo\"), \"UTF-16BE\", null"); } - try { - Formatter f = new Formatter(new PrintStream("foo"), - "UTF-16BE", Locale.ITALIAN); + try (Formatter f = new Formatter(new PrintStream("foo"), + "UTF-16BE", Locale.ITALIAN)) { pass(); locale(f, Locale.ITALIAN); out(f, BufferedWriter.class); @@ -361,8 +344,7 @@ public class Constructors { fail("new Formatter((OutputStream) null)", x); } - try { - Formatter f = new Formatter((OutputStream) new PrintStream("foo")); + try (Formatter f = new Formatter((OutputStream) new PrintStream("foo"))) { pass(); locale(f); out(f, BufferedWriter.class); @@ -380,8 +362,8 @@ public class Constructors { fail("new Formatter((OutputStream) null, \"ISO-8859-1\")", x); } - try { - new Formatter((OutputStream) new PrintStream("foo"), null); + try (PrintStream ps = new PrintStream("foo")) { + new Formatter((OutputStream) ps, null); fail("new Formatter((OutputStream) new PrintStream(\"foo\"), null"); } catch (NullPointerException x) { pass(); @@ -390,8 +372,8 @@ public class Constructors { x); } - try { - new Formatter(new PrintStream("foo"), "bar"); + try (PrintStream ps = new PrintStream("foo")) { + new Formatter(ps, "bar"); fail("new Formatter(new PrintStream(\"foo\"), \"bar\")"); } catch (UnsupportedEncodingException x) { pass(); @@ -399,8 +381,7 @@ public class Constructors { fail("new Formatter(new PrintStream(\"foo\"), \"bar\")", x); } - try { - Formatter f = new Formatter(new PrintStream("foo"), "UTF-8"); + try (Formatter f = new Formatter(new PrintStream("foo"), "UTF-8")) { pass(); locale(f); out(f, BufferedWriter.class); @@ -419,8 +400,8 @@ public class Constructors { x); } - try { - new Formatter(new PrintStream("foo"), null, Locale.UK); + try (PrintStream ps = new PrintStream("foo")) { + new Formatter(ps, null, Locale.UK); fail("new Formatter(new PrintStream(\"foo\"), null, Locale.UK)"); } catch (NullPointerException x) { pass(); @@ -429,8 +410,8 @@ public class Constructors { x); } - try { - new Formatter(new PrintStream("foo"), "bar", Locale.UK); + try (PrintStream ps = new PrintStream("foo")) { + new Formatter(ps, "bar", Locale.UK); fail("new Formatter(new PrintStream(\"foo\"), \"bar\", Locale.UK)"); } catch (UnsupportedEncodingException x) { pass(); @@ -439,9 +420,7 @@ public class Constructors { x); } - try { - Formatter f - = new Formatter(new PrintStream("foo"), "UTF-8", Locale.UK); + try (Formatter f = new Formatter(new PrintStream("foo"), "UTF-8", Locale.UK)) { pass(); out(f, BufferedWriter.class); locale(f, Locale.UK); @@ -451,8 +430,7 @@ public class Constructors { } // PrintStream(String fileName) - try { - new PrintStream("foo"); + try (PrintStream ps = new PrintStream("foo")) { pass(); } catch (Exception x) { fail("new PrintStream(\"foo\")", x); @@ -469,8 +447,7 @@ public class Constructors { } // PrintStream(File file) - try { - new PrintStream(new File("foo")); + try (PrintStream ps = new PrintStream(new File("foo"))) { pass(); } catch (Exception x) { fail("new PrintStream(new File(\"foo\"))", x); @@ -487,8 +464,7 @@ public class Constructors { } // PrintWriter(String fileName) - try { - new PrintWriter("foo"); + try (PrintWriter pw = new PrintWriter("foo")) { pass(); } catch (Exception x) { fail("new PrintWriter(\"foo\")", x); @@ -505,8 +481,7 @@ public class Constructors { } // PrintWriter(File file) - try { - new PrintWriter(new File("foo")); + try (PrintWriter pw = new PrintWriter(new File("foo"))) { pass(); } catch (Exception x) { fail("new PrintWriter(new File(\"foo\"))", x); diff --git a/test/java/util/Formatter/FailingConstructors.java b/test/java/util/Formatter/FailingConstructors.java new file mode 100644 index 0000000000000000000000000000000000000000..8ef99f146a40ad5299b19f55fe772f6bdb69faec --- /dev/null +++ b/test/java/util/Formatter/FailingConstructors.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 7000511 + * @summary PrintStream, PrintWriter, Formatter, Scanner leave files open when + * exception thrown + */ + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.Formatter; + +public class FailingConstructors { + static final String fileName = "FailingConstructorsTest"; + static final String UNSUPPORTED_CHARSET = "unknownCharset"; + static final String FILE_CONTENTS = "This is a small file!"; + + private static void realMain(String[] args) throws Throwable { + test(false, new File(fileName)); + + /* create the file and write its contents */ + File file = File.createTempFile(fileName, null); + file.deleteOnExit(); + FileOutputStream fos = new FileOutputStream(file); + fos.write(FILE_CONTENTS.getBytes()); + fos.close(); + + test(true, file); + file.delete(); + } + + private static void test(boolean exists, File file) throws Throwable { + /* Formatter(File file, String csn) */ + try { + new Formatter(file, UNSUPPORTED_CHARSET); + fail(); + } catch(FileNotFoundException|UnsupportedEncodingException e) { + pass(); + } + + check(exists, file); + + try { + new Formatter(file, null); + fail(); + } catch(FileNotFoundException|NullPointerException e) { + pass(); + } + + check(exists, file); + + /* Formatter(String fileName, String csn) */ + try { + new Formatter(file.getName(), UNSUPPORTED_CHARSET); + fail(); + } catch(FileNotFoundException|UnsupportedEncodingException e) { + pass(); + } + + check(exists, file); + + try { + new Formatter(file.getName(), null); + fail(); + } catch(FileNotFoundException|NullPointerException e) { + pass(); + } + + check(exists, file); + } + + private static void check(boolean exists, File file) { + if (exists) { + /* the file should be unchanged */ + verifyContents(file); + } else { + /* the file should not have been created */ + if (file.exists()) { fail(file + " should not have been created"); } + } + } + + private static void verifyContents(File file) { + try (FileInputStream fis = new FileInputStream(file)) { + byte[] contents = FILE_CONTENTS.getBytes(); + int read, count = 0; + while ((read = fis.read()) != -1) { + if (read != contents[count++]) { + fail("file contents have been altered"); + return; + } + } + } catch (IOException ioe) { + unexpected(ioe); + } + } + + //--------------------- Infrastructure --------------------------- + static volatile int passed = 0, failed = 0; + static void pass() {passed++;} + static void fail() {failed++; Thread.dumpStack();} + static void fail(String message) {System.out.println(message); fail(); } + static void unexpected(Throwable t) {failed++; t.printStackTrace();} + public static void main(String[] args) throws Throwable { + try {realMain(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +} diff --git a/test/java/util/Scanner/FailingConstructors.java b/test/java/util/Scanner/FailingConstructors.java new file mode 100644 index 0000000000000000000000000000000000000000..476c000ae1a536def6ba62a6f0d4df51516a16a6 --- /dev/null +++ b/test/java/util/Scanner/FailingConstructors.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 7000511 + * @summary PrintStream, PrintWriter, Formatter, Scanner leave files open when + * exception thrown + */ + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Scanner; + +public class FailingConstructors { + static final String fileName = "FailingConstructorsTest"; + static final String UNSUPPORTED_CHARSET = "unknownCharset"; + static final String FILE_CONTENTS = "This is a small file!"; + + private static void realMain(String[] args) throws Throwable { + test(false, new File(fileName)); + + /* create the file and write its contents */ + File file = File.createTempFile(fileName, null); + file.deleteOnExit(); + FileOutputStream fos = new FileOutputStream(file); + fos.write(FILE_CONTENTS.getBytes()); + fos.close(); + + test(true, file); + file.delete(); + } + + private static void test(boolean exists, File file) throws Throwable { + /* Scanner(File source, String charsetName) */ + try { + new Scanner(file, UNSUPPORTED_CHARSET); + fail(); + } catch(FileNotFoundException|IllegalArgumentException e) { + pass(); + } + + check(exists, file); + + try { + new Scanner(file, null); + fail(); + } catch(FileNotFoundException|NullPointerException e) { + pass(); + } + + check(exists, file); + + /* Scanner(FileRef source, String charsetName) */ + try { + new Scanner(file.toPath(), UNSUPPORTED_CHARSET); + fail(); + } catch(FileNotFoundException|IllegalArgumentException e) { + pass(); + } + + check(exists, file); + + try { + new Scanner(file.toPath(), null); + fail(); + } catch(FileNotFoundException|NullPointerException e) { + pass(); + } + + check(exists, file); + } + + private static void check(boolean exists, File file) { + if (exists) { + /* the file should be unchanged */ + verifyContents(file); + } else { + /* the file should not have been created */ + if (file.exists()) { fail(file + " should not have been created"); } + } + } + + private static void verifyContents(File file) { + try (FileInputStream fis = new FileInputStream(file)) { + byte[] contents = FILE_CONTENTS.getBytes(); + int read, count = 0; + while ((read = fis.read()) != -1) { + if (read != contents[count++]) { + fail("file contents have been altered"); + return; + } + } + } catch (IOException ioe) { + unexpected(ioe); + } + } + + //--------------------- Infrastructure --------------------------- + static volatile int passed = 0, failed = 0; + static void pass() {passed++;} + static void fail() {failed++; Thread.dumpStack();} + static void fail(String message) {System.out.println(message); fail(); } + static void unexpected(Throwable t) {failed++; t.printStackTrace();} + public static void main(String[] args) throws Throwable { + try {realMain(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +} diff --git a/test/java/util/WeakHashMap/GCDuringIteration.java b/test/java/util/WeakHashMap/GCDuringIteration.java index 938322b7db20ed067a6890f749e11ecb89dc7478..482d04426ca1805b6e5a7b6574a483380007af60 100644 --- a/test/java/util/WeakHashMap/GCDuringIteration.java +++ b/test/java/util/WeakHashMap/GCDuringIteration.java @@ -33,18 +33,17 @@ import java.util.*; import java.util.concurrent.CountDownLatch; public class GCDuringIteration { - static void finalizeTillYouDrop() { - System.gc(); // Enqueue all finalizables - - System.runFinalization(); // Drain finalizer queue + private static void waitForFinalizersToRun() { + for (int i = 0; i < 2; i++) + tryWaitForFinalizersToRun(); + } - // There may be a straggler finalizable object still being - // finalized by the dedicated finalizer thread. Enqueue one - // more finalizable object, and wait for it to be finalized. - final CountDownLatch latch = new CountDownLatch(1); - new Object() { protected void finalize() { latch.countDown(); }}; + private static void tryWaitForFinalizersToRun() { + System.gc(); + final CountDownLatch fin = new CountDownLatch(1); + new Object() { protected void finalize() { fin.countDown(); }}; System.gc(); - try { latch.await(); } + try { fin.await(); } catch (InterruptedException ie) { throw new Error(ie); } } @@ -101,7 +100,9 @@ public class GCDuringIteration { { int first = firstValue(map); final Iterator> it = map.entrySet().iterator(); - foos[first] = null; finalizeTillYouDrop(); + foos[first] = null; + for (int i = 0; i < 10 && map.size() != first; i++) + tryWaitForFinalizersToRun(); equal(map.size(), first); checkIterator(it, first-1); equal(map.size(), first); @@ -113,11 +114,14 @@ public class GCDuringIteration { final Iterator> it = map.entrySet().iterator(); it.next(); // protects first entry System.out.println(map.values()); - foos[first] = null; finalizeTillYouDrop(); + foos[first] = null; + tryWaitForFinalizersToRun() equal(map.size(), first+1); System.out.println(map.values()); checkIterator(it, first-1); - finalizeTillYouDrop(); // first entry no longer protected + // first entry no longer protected + for (int i = 0; i < 10 && map.size() != first; i++) + tryWaitForFinalizersToRun(); equal(map.size(), first); equal(firstValue(map), first-1); } @@ -127,12 +131,15 @@ public class GCDuringIteration { final Iterator> it = map.entrySet().iterator(); it.next(); // protects first entry System.out.println(map.values()); - foos[first] = foos[first-1] = null; finalizeTillYouDrop(); + foos[first] = foos[first-1] = null; + tryWaitForFinalizersToRun(); equal(map.size(), first); equal(firstValue(map), first); System.out.println(map.values()); checkIterator(it, first-2); - finalizeTillYouDrop(); // first entry no longer protected + // first entry no longer protected + for (int i = 0; i < 10 && map.size() != first-1; i++) + tryWaitForFinalizersToRun(); equal(map.size(), first-1); equal(firstValue(map), first-2); } @@ -143,12 +150,15 @@ public class GCDuringIteration { it.next(); // protects first entry it.hasNext(); // protects second entry System.out.println(map.values()); - foos[first] = foos[first-1] = null; finalizeTillYouDrop(); + foos[first] = foos[first-1] = null; + tryWaitForFinalizersToRun(); equal(firstValue(map), first); equal(map.size(), first+1); System.out.println(map.values()); checkIterator(it, first-1); - finalizeTillYouDrop(); // first entry no longer protected + // first entry no longer protected + for (int i = 0; i < 10 && map.size() != first-1; i++) + tryWaitForFinalizersToRun(); equal(map.size(), first-1); equal(firstValue(map), first-2); } @@ -158,13 +168,16 @@ public class GCDuringIteration { final Iterator> it = map.entrySet().iterator(); it.next(); // protects first entry System.out.println(map.values()); - foos[first] = foos[first-1] = null; finalizeTillYouDrop(); + foos[first] = foos[first-1] = null; + tryWaitForFinalizersToRun(); it.remove(); equal(firstValue(map), first-2); equal(map.size(), first-1); System.out.println(map.values()); checkIterator(it, first-2); - finalizeTillYouDrop(); + // first entry no longer protected + for (int i = 0; i < 10 && map.size() != first-1; i++) + tryWaitForFinalizersToRun(); equal(map.size(), first-1); equal(firstValue(map), first-2); } @@ -176,12 +189,14 @@ public class GCDuringIteration { it.remove(); it.hasNext(); // protects second entry System.out.println(map.values()); - foos[first] = foos[first-1] = null; finalizeTillYouDrop(); + foos[first] = foos[first-1] = null; + tryWaitForFinalizersToRun(); equal(firstValue(map), first-1); equal(map.size(), first); System.out.println(map.values()); checkIterator(it, first-1); - finalizeTillYouDrop(); + for (int i = 0; i < 10 && map.size() != first-1; i++) + tryWaitForFinalizersToRun(); equal(map.size(), first-1); equal(firstValue(map), first-2); } @@ -191,12 +206,13 @@ public class GCDuringIteration { final Iterator> it = map.entrySet().iterator(); it.hasNext(); // protects first entry Arrays.fill(foos, null); - finalizeTillYouDrop(); + tryWaitForFinalizersToRun(); equal(map.size(), 1); System.out.println(map.values()); equal(it.next().getValue(), first); check(! it.hasNext()); - finalizeTillYouDrop(); + for (int i = 0; i < 10 && map.size() != 0; i++) + tryWaitForFinalizersToRun(); equal(map.size(), 0); check(map.isEmpty()); } diff --git a/test/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java b/test/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java index c12a57ec70896c4a8e862ee431181e4a94ef0e86..34f0722d8bd8ffb69c418c37c3cd5fd4b97b0193 100644 --- a/test/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java +++ b/test/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java @@ -34,7 +34,7 @@ /* * @test * @bug 4486658 - * @compile CancelledProducerConsumerLoops.java + * @compile -source 1.5 CancelledProducerConsumerLoops.java * @run main/timeout=7000 CancelledProducerConsumerLoops * @summary Checks for responsiveness of blocking queues to cancellation. * Runs under the assumption that ITERS computations require more than @@ -119,48 +119,24 @@ public class CancelledProducerConsumerLoops { } } - static final class LTQasSQ extends LinkedTransferQueue { - LTQasSQ() { super(); } - public void put(T x) { - try { super.transfer(x); } - catch (InterruptedException ex) { throw new Error(); } - } - private final static long serialVersionUID = 42; - } - - static final class HalfSyncLTQ extends LinkedTransferQueue { - HalfSyncLTQ() { super(); } - public void put(T x) { - if (ThreadLocalRandom.current().nextBoolean()) - super.put(x); - else { - try { super.transfer(x); } - catch (InterruptedException ex) { throw new Error(); } - } - } - private final static long serialVersionUID = 42; - } - static void oneTest(int pairs, int iters) throws Exception { oneRun(new ArrayBlockingQueue(CAPACITY), pairs, iters); oneRun(new LinkedBlockingQueue(CAPACITY), pairs, iters); oneRun(new LinkedBlockingDeque(CAPACITY), pairs, iters); + oneRun(new LinkedTransferQueue(), pairs, iters); oneRun(new SynchronousQueue(), pairs, iters / 8); - /* TODO: unbounded queue implementations are prone to OOME + /* PriorityBlockingQueue is unbounded oneRun(new PriorityBlockingQueue(iters / 2 * pairs), pairs, iters / 4); - oneRun(new LinkedTransferQueue(), pairs, iters); - oneRun(new LTQasSQ(), pairs, iters); - oneRun(new HalfSyncLTQ(), pairs, iters); */ } - static abstract class Stage implements Callable { + abstract static class Stage implements Callable { final BlockingQueue queue; final CyclicBarrier barrier; final int iters; - Stage (BlockingQueue q, CyclicBarrier b, int iters) { + Stage(BlockingQueue q, CyclicBarrier b, int iters) { queue = q; barrier = b; this.iters = iters; diff --git a/test/java/util/concurrent/BlockingQueue/MultipleProducersSingleConsumerLoops.java b/test/java/util/concurrent/BlockingQueue/MultipleProducersSingleConsumerLoops.java index 1f85c511e5976c13c807791db58d2cfdebd1aa6a..d57939fc3746491d1b51b3c89e5c7969a8f4482d 100644 --- a/test/java/util/concurrent/BlockingQueue/MultipleProducersSingleConsumerLoops.java +++ b/test/java/util/concurrent/BlockingQueue/MultipleProducersSingleConsumerLoops.java @@ -34,7 +34,7 @@ /* * @test * @bug 4486658 - * @compile MultipleProducersSingleConsumerLoops.java + * @compile -source 1.5 MultipleProducersSingleConsumerLoops.java * @run main/timeout=3600 MultipleProducersSingleConsumerLoops * @summary multiple producers and single consumer using blocking queues */ @@ -87,35 +87,11 @@ public class MultipleProducersSingleConsumerLoops { throw new Error(); } - static final class LTQasSQ extends LinkedTransferQueue { - LTQasSQ() { super(); } - public void put(T x) { - try { super.transfer(x); } - catch (InterruptedException ex) { throw new Error(); } - } - private final static long serialVersionUID = 42; - } - - static final class HalfSyncLTQ extends LinkedTransferQueue { - HalfSyncLTQ() { super(); } - public void put(T x) { - if (ThreadLocalRandom.current().nextBoolean()) - super.put(x); - else { - try { super.transfer(x); } - catch (InterruptedException ex) { throw new Error(); } - } - } - private final static long serialVersionUID = 42; - } - static void oneTest(int producers, int iters) throws Exception { oneRun(new ArrayBlockingQueue(CAPACITY), producers, iters); oneRun(new LinkedBlockingQueue(CAPACITY), producers, iters); oneRun(new LinkedBlockingDeque(CAPACITY), producers, iters); oneRun(new LinkedTransferQueue(), producers, iters); - oneRun(new LTQasSQ(), producers, iters); - oneRun(new HalfSyncLTQ(), producers, iters); // Don't run PBQ since can legitimately run out of memory // if (print) @@ -129,11 +105,11 @@ public class MultipleProducersSingleConsumerLoops { oneRun(new ArrayBlockingQueue(CAPACITY, true), producers, iters); } - static abstract class Stage implements Runnable { + abstract static class Stage implements Runnable { final int iters; final BlockingQueue queue; final CyclicBarrier barrier; - Stage (BlockingQueue q, CyclicBarrier b, int iters) { + Stage(BlockingQueue q, CyclicBarrier b, int iters) { queue = q; barrier = b; this.iters = iters; diff --git a/test/java/util/concurrent/BlockingQueue/ProducerConsumerLoops.java b/test/java/util/concurrent/BlockingQueue/ProducerConsumerLoops.java index f2b4a5b334d565209d398e444fecef2d9403d958..9f18ab53c892ae3e1bc92a8548b568a7ae518450 100644 --- a/test/java/util/concurrent/BlockingQueue/ProducerConsumerLoops.java +++ b/test/java/util/concurrent/BlockingQueue/ProducerConsumerLoops.java @@ -34,7 +34,7 @@ /* * @test * @bug 4486658 - * @compile ProducerConsumerLoops.java + * @compile -source 1.5 ProducerConsumerLoops.java * @run main/timeout=3600 ProducerConsumerLoops * @summary multiple producers and consumers using blocking queues */ @@ -87,35 +87,11 @@ public class ProducerConsumerLoops { throw new Error(); } - static final class LTQasSQ extends LinkedTransferQueue { - LTQasSQ() { super(); } - public void put(T x) { - try { super.transfer(x); } - catch (InterruptedException ex) { throw new Error(); } - } - private final static long serialVersionUID = 42; - } - - static final class HalfSyncLTQ extends LinkedTransferQueue { - HalfSyncLTQ() { super(); } - public void put(T x) { - if (ThreadLocalRandom.current().nextBoolean()) - super.put(x); - else { - try { super.transfer(x); } - catch (InterruptedException ex) { throw new Error(); } - } - } - private final static long serialVersionUID = 42; - } - static void oneTest(int pairs, int iters) throws Exception { oneRun(new ArrayBlockingQueue(CAPACITY), pairs, iters); oneRun(new LinkedBlockingQueue(CAPACITY), pairs, iters); oneRun(new LinkedBlockingDeque(CAPACITY), pairs, iters); oneRun(new LinkedTransferQueue(), pairs, iters); - oneRun(new LTQasSQ(), pairs, iters); - oneRun(new HalfSyncLTQ(), pairs, iters); oneRun(new PriorityBlockingQueue(), pairs, iters); oneRun(new SynchronousQueue(), pairs, iters); @@ -126,11 +102,11 @@ public class ProducerConsumerLoops { oneRun(new ArrayBlockingQueue(CAPACITY, true), pairs, iters); } - static abstract class Stage implements Runnable { + abstract static class Stage implements Runnable { final int iters; final BlockingQueue queue; final CyclicBarrier barrier; - Stage (BlockingQueue q, CyclicBarrier b, int iters) { + Stage(BlockingQueue q, CyclicBarrier b, int iters) { queue = q; barrier = b; this.iters = iters; diff --git a/test/java/util/concurrent/BlockingQueue/SingleProducerMultipleConsumerLoops.java b/test/java/util/concurrent/BlockingQueue/SingleProducerMultipleConsumerLoops.java index 1550bb2227724440df1960e9b3490f954714ff40..85699bc7d56185548e473536b7e288fe6faddca1 100644 --- a/test/java/util/concurrent/BlockingQueue/SingleProducerMultipleConsumerLoops.java +++ b/test/java/util/concurrent/BlockingQueue/SingleProducerMultipleConsumerLoops.java @@ -34,7 +34,7 @@ /* * @test * @bug 4486658 - * @compile SingleProducerMultipleConsumerLoops.java + * @compile -source 1.5 SingleProducerMultipleConsumerLoops.java * @run main/timeout=600 SingleProducerMultipleConsumerLoops * @summary check ordering for blocking queues with 1 producer and multiple consumers */ @@ -73,35 +73,11 @@ public class SingleProducerMultipleConsumerLoops { throw new Error(); } - static final class LTQasSQ extends LinkedTransferQueue { - LTQasSQ() { super(); } - public void put(T x) { - try { super.transfer(x); } - catch (InterruptedException ex) { throw new Error(); } - } - private final static long serialVersionUID = 42; - } - - static final class HalfSyncLTQ extends LinkedTransferQueue { - HalfSyncLTQ() { super(); } - public void put(T x) { - if (ThreadLocalRandom.current().nextBoolean()) - super.put(x); - else { - try { super.transfer(x); } - catch (InterruptedException ex) { throw new Error(); } - } - } - private final static long serialVersionUID = 42; - } - static void oneTest(int consumers, int iters) throws Exception { oneRun(new ArrayBlockingQueue(CAPACITY), consumers, iters); oneRun(new LinkedBlockingQueue(CAPACITY), consumers, iters); oneRun(new LinkedBlockingDeque(CAPACITY), consumers, iters); oneRun(new LinkedTransferQueue(), consumers, iters); - oneRun(new LTQasSQ(), consumers, iters); - oneRun(new HalfSyncLTQ(), consumers, iters); oneRun(new PriorityBlockingQueue(), consumers, iters); oneRun(new SynchronousQueue(), consumers, iters); if (print) @@ -110,12 +86,12 @@ public class SingleProducerMultipleConsumerLoops { oneRun(new ArrayBlockingQueue(CAPACITY, true), consumers, iters); } - static abstract class Stage implements Runnable { + abstract static class Stage implements Runnable { final int iters; final BlockingQueue queue; final CyclicBarrier barrier; volatile int result; - Stage (BlockingQueue q, CyclicBarrier b, int iters) { + Stage(BlockingQueue q, CyclicBarrier b, int iters) { queue = q; barrier = b; this.iters = iters; diff --git a/test/java/util/concurrent/ConcurrentQueues/IteratorWeakConsistency.java b/test/java/util/concurrent/ConcurrentQueues/IteratorWeakConsistency.java index 78ce8d71194dd9aad1690a36a4141800364d1aea..dabb2b9de2a7189854d78d905b0b75a59b79641e 100644 --- a/test/java/util/concurrent/ConcurrentQueues/IteratorWeakConsistency.java +++ b/test/java/util/concurrent/ConcurrentQueues/IteratorWeakConsistency.java @@ -53,7 +53,9 @@ public class IteratorWeakConsistency { test(new LinkedTransferQueue()); // Other concurrent queues (e.g. ArrayBlockingQueue) do not // currently have weakly consistent iterators. - // test(new ArrayBlockingQueue(20)); + // As of 2010-09, ArrayBlockingQueue passes this test, but + // does not fully implement weak consistency. + test(new ArrayBlockingQueue(20)); } void test(Queue q) { diff --git a/test/java/util/concurrent/Executors/AutoShutdown.java b/test/java/util/concurrent/Executors/AutoShutdown.java index e6f7c1a3d5a8f1d4cdba50a9df8e61deea51b75b..fb4976ff87840461ea7fda2f46837f480916715b 100644 --- a/test/java/util/concurrent/Executors/AutoShutdown.java +++ b/test/java/util/concurrent/Executors/AutoShutdown.java @@ -24,6 +24,7 @@ /* * @test * @bug 6399443 + * @run main/othervm AutoShutdown * @summary Check for auto-shutdown and gc of singleThreadExecutors * @author Martin Buchholz */ diff --git a/test/java/util/concurrent/Phaser/Basic.java b/test/java/util/concurrent/Phaser/Basic.java index e394cee94f668bc66d3c9427b5e790a7d5659806..a358873c2ece837b79e420f3cc0166632452b335 100644 --- a/test/java/util/concurrent/Phaser/Basic.java +++ b/test/java/util/concurrent/Phaser/Basic.java @@ -52,15 +52,16 @@ public class Basic { check(phaser.isTerminated()); int unarriverParties = phaser.getUnarrivedParties(); int registeredParties = phaser.getRegisteredParties(); - equal(phaser.arrive(), -1); - equal(phaser.arriveAndDeregister(), -1); - equal(phaser.arriveAndAwaitAdvance(), -1); - equal(phaser.bulkRegister(10), -1); - equal(phaser.getPhase(), -1); - equal(phaser.register(), -1); + int phase = phaser.getPhase(); + check(phase < 0); + equal(phase, phaser.arrive()); + equal(phase, phaser.arriveAndDeregister()); + equal(phase, phaser.arriveAndAwaitAdvance()); + equal(phase, phaser.bulkRegister(10)); + equal(phase, phaser.register()); try { - equal(phaser.awaitAdvanceInterruptibly(0), -1); - equal(phaser.awaitAdvanceInterruptibly(0, 10, SECONDS), -1); + equal(phase, phaser.awaitAdvanceInterruptibly(0)); + equal(phase, phaser.awaitAdvanceInterruptibly(0, 10, SECONDS)); } catch (Exception ie) { unexpected(ie); } @@ -94,10 +95,9 @@ public class Basic { } int phase = atTheStartingGate.getPhase(); equal(phase, atTheStartingGate.arrive()); - int AwaitPhase = atTheStartingGate.awaitAdvanceInterruptibly(phase, - 10, - SECONDS); - if (expectNextPhase) check(AwaitPhase == (phase + 1)); + int awaitPhase = atTheStartingGate.awaitAdvanceInterruptibly + (phase, 10, SECONDS); + if (expectNextPhase) check(awaitPhase == (phase + 1)); pass(); } catch (Throwable t) { @@ -271,18 +271,19 @@ public class Basic { // Phaser is terminated while threads are waiting //---------------------------------------------------------------- try { - Phaser phaser = new Phaser(3); - Iterator awaiters = awaiterIterator(phaser); for (int i = 0; i < 4; i++) { + Phaser phaser = new Phaser(3); + Iterator awaiters = awaiterIterator(phaser); Arriver a1 = awaiters.next(); a1.start(); Arriver a2 = awaiters.next(); a2.start(); toTheStartingGate(); while (phaser.getArrivedParties() < 2) Thread.yield(); + equal(0, phaser.getPhase()); phaser.forceTermination(); a1.join(); a2.join(); - check(a1.phase == -1); - check(a2.phase == -1); + equal(0 + Integer.MIN_VALUE, a1.phase); + equal(0 + Integer.MIN_VALUE, a2.phase); int arrivedParties = phaser.getArrivedParties(); checkTerminated(phaser); equal(phaser.getArrivedParties(), arrivedParties); diff --git a/test/java/util/concurrent/Phaser/FickleRegister.java b/test/java/util/concurrent/Phaser/FickleRegister.java new file mode 100644 index 0000000000000000000000000000000000000000..9ce91c5de442a6ef175bf6953102f990ac069127 --- /dev/null +++ b/test/java/util/concurrent/Phaser/FickleRegister.java @@ -0,0 +1,150 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/licenses/publicdomain + */ + +/* + * @test + * @summary stress test for register/arriveAndDeregister + * @run main FickleRegister 300 + */ + +import java.util.*; +import java.util.concurrent.*; +import java.util.concurrent.atomic.*; + +public class FickleRegister { + final AtomicLong count = new AtomicLong(0); + final long testDurationMillisDefault = 10L * 1000L; + final long testDurationMillis; + final long quittingTimeNanos; + final int chunkSize = 1000; + + FickleRegister(String[] args) { + testDurationMillis = (args.length > 0) ? + Long.valueOf(args[0]) : testDurationMillisDefault; + quittingTimeNanos = System.nanoTime() + + testDurationMillis * 1000L * 1000L; + } + + class Runner extends CheckedRunnable { + final Phaser p; + Runner(Phaser phaser) { p = phaser; } + public void realRun() { + int prevPhase = -1; + for (int k = 1;; k++) { + for (int i = 0; i < chunkSize; i++) { + int phase = p.register(); + if (phase < 0) break; + check(phase > prevPhase); + prevPhase = phase; + equal(phase, p.arriveAndDeregister()); + check(phase < p.awaitAdvance(phase)); + } + if (System.nanoTime() - quittingTimeNanos > 0) { + count.getAndAdd(k * chunkSize); + break; + } + } + } + } + + void test(String[] args) throws Throwable { + final Phaser parent = new Phaser() { + protected boolean onAdvance(int phase, int parties) { + return false; + } + }; + + final Phaser child1 = new Phaser(parent); + final Phaser child2 = new Phaser(parent); + final Phaser subchild1 = new Phaser(child1); + final Phaser subchild2 = new Phaser(child2); + final Phaser[] phasers = { + parent, child1, child2, subchild1, subchild2 + }; + + int reps = 4; + ArrayList threads = new ArrayList(); + for (int j = 0; j < reps; ++j) { + threads.add(new Thread(new Runner(subchild1))); + threads.add(new Thread(new Runner(child1))); + threads.add(new Thread(new Runner(parent))); + threads.add(new Thread(new Runner(child2))); + threads.add(new Thread(new Runner(subchild2))); + } + + for (Thread thread : threads) + thread.start(); + + for (Thread thread : threads) + thread.join(); + + System.out.println("Parent: " + parent); + System.out.println("Child1: " + child1); + System.out.println("Child2: " + child2); + System.out.println("Subchild1: " + subchild1); + System.out.println("Subchild2: " + subchild2); + System.out.println("Iterations:" + count.get()); + + for (Phaser phaser : phasers) { + check(phaser.getPhase() > 0); + equal(0, phaser.getRegisteredParties()); + equal(0, phaser.getUnarrivedParties()); + equal(parent.getPhase(), phaser.getPhase()); + } + } + + //--------------------- Infrastructure --------------------------- + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++; Thread.dumpStack();} + void fail(String msg) {System.err.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond) {if (cond) pass(); else fail();} + void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + new FickleRegister(args).instanceMain(args);} + public void instanceMain(String[] args) throws Throwable { + try {test(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} + + abstract class CheckedRunnable implements Runnable { + protected abstract void realRun() throws Throwable; + + public final void run() { + try {realRun();} catch (Throwable t) {unexpected(t);} + } + } +} diff --git a/test/java/util/concurrent/Phaser/PhaseOverflow.java b/test/java/util/concurrent/Phaser/PhaseOverflow.java new file mode 100644 index 0000000000000000000000000000000000000000..da8b5367072bf15c20806e37bd817e72e3010afc --- /dev/null +++ b/test/java/util/concurrent/Phaser/PhaseOverflow.java @@ -0,0 +1,158 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Martin Buchholz and Doug Lea with assistance from + * members of JCP JSR-166 Expert Group and released to the public + * domain, as explained at + * http://creativecommons.org/licenses/publicdomain + */ + +/* + * @test + * @summary Test Phaser phase integer overflow behavior + */ + +import java.util.concurrent.Phaser; +import java.lang.reflect.Field; + +public class PhaseOverflow { + Field stateField; + + void checkState(Phaser phaser, + int phase, int parties, int unarrived) { + equal(phase, phaser.getPhase()); + equal(parties, phaser.getRegisteredParties()); + equal(unarrived, phaser.getUnarrivedParties()); + } + + void test(String[] args) throws Throwable { + stateField = Phaser.class.getDeclaredField("state"); + stateField.setAccessible(true); + testLeaf(); + testTiered(); + } + + void testLeaf() throws Throwable { + Phaser phaser = new Phaser(); + // this is extremely dependent on internal representation + stateField.setLong(phaser, ((Integer.MAX_VALUE - 1L) << 32) | 1L); + checkState(phaser, Integer.MAX_VALUE - 1, 0, 0); + phaser.register(); + checkState(phaser, Integer.MAX_VALUE - 1, 1, 1); + phaser.arrive(); + checkState(phaser, Integer.MAX_VALUE, 1, 1); + phaser.arrive(); + checkState(phaser, 0, 1, 1); + phaser.arrive(); + checkState(phaser, 1, 1, 1); + } + + int phaseInc(int phase) { return (phase + 1) & Integer.MAX_VALUE; } + + void testTiered() throws Throwable { + Phaser root = new Phaser(); + // this is extremely dependent on internal representation + stateField.setLong(root, ((Integer.MAX_VALUE - 1L) << 32) | 1L); + checkState(root, Integer.MAX_VALUE - 1, 0, 0); + Phaser p1 = new Phaser(root, 1); + checkState(root, Integer.MAX_VALUE - 1, 1, 1); + checkState(p1, Integer.MAX_VALUE - 1, 1, 1); + Phaser p2 = new Phaser(root, 2); + checkState(root, Integer.MAX_VALUE - 1, 2, 2); + checkState(p2, Integer.MAX_VALUE - 1, 2, 2); + int ph = Integer.MAX_VALUE - 1; + for (int k = 0; k < 5; k++) { + checkState(root, ph, 2, 2); + checkState(p1, ph, 1, 1); + checkState(p2, ph, 2, 2); + p1.arrive(); + checkState(root, ph, 2, 1); + checkState(p1, ph, 1, 0); + checkState(p2, ph, 2, 2); + p2.arrive(); + checkState(root, ph, 2, 1); + checkState(p1, ph, 1, 0); + checkState(p2, ph, 2, 1); + p2.arrive(); + ph = phaseInc(ph); + checkState(root, ph, 2, 2); + checkState(p1, ph, 1, 1); + checkState(p2, ph, 2, 2); + } + equal(3, ph); + } + + void xtestTiered() throws Throwable { + Phaser root = new Phaser(); + stateField.setLong(root, ((Integer.MAX_VALUE - 1L) << 32) | 1L); + checkState(root, Integer.MAX_VALUE - 1, 0, 0); + Phaser p1 = new Phaser(root, 1); + checkState(root, Integer.MAX_VALUE - 1, 1, 1); + checkState(p1, Integer.MAX_VALUE - 1, 1, 1); + Phaser p2 = new Phaser(root, 2); + checkState(root, Integer.MAX_VALUE - 1, 2, 2); + checkState(p2, Integer.MAX_VALUE - 1, 2, 2); + int ph = Integer.MAX_VALUE - 1; + for (int k = 0; k < 5; k++) { + checkState(root, ph, 2, 2); + checkState(p1, ph, 1, 1); + checkState(p2, ph, 2, 2); + p1.arrive(); + checkState(root, ph, 2, 1); + checkState(p1, ph, 1, 0); + checkState(p2, ph, 2, 2); + p2.arrive(); + checkState(root, ph, 2, 1); + checkState(p1, ph, 1, 0); + checkState(p2, ph, 2, 1); + p2.arrive(); + ph = phaseInc(ph); + checkState(root, ph, 2, 2); + checkState(p1, ph, 1, 1); + checkState(p2, ph, 2, 2); + } + equal(3, ph); + } + + //--------------------- Infrastructure --------------------------- + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++; Thread.dumpStack();} + void fail(String msg) {System.err.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond) {if (cond) pass(); else fail();} + void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + new PhaseOverflow().instanceMain(args);} + public void instanceMain(String[] args) throws Throwable { + try {test(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +} diff --git a/test/java/util/concurrent/Phaser/TieredArriveLoops.java b/test/java/util/concurrent/Phaser/TieredArriveLoops.java new file mode 100644 index 0000000000000000000000000000000000000000..33a03f08dab08efbda646f0873bff3f4c3c607bd --- /dev/null +++ b/test/java/util/concurrent/Phaser/TieredArriveLoops.java @@ -0,0 +1,117 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/licenses/publicdomain + */ + +/* + * @test + * @summary stress test for arrivals in a tiered phaser + * @run main TieredArriveLoops 300 + */ +import java.util.*; +import java.util.concurrent.*; + +public class TieredArriveLoops { + final long testDurationMillisDefault = 10L * 1000L; + final long testDurationMillis; + final long quittingTimeNanos; + + TieredArriveLoops(String[] args) { + testDurationMillis = (args.length > 0) ? + Long.valueOf(args[0]) : testDurationMillisDefault; + quittingTimeNanos = System.nanoTime() + + testDurationMillis * 1000L * 1000L; + } + + Runnable runner(final Phaser p) { + return new CheckedRunnable() { public void realRun() { + int prevPhase = p.register(); + while (!p.isTerminated()) { + int phase = p.awaitAdvance(p.arrive()); + if (phase < 0) + return; + equal(phase, (prevPhase + 1) & Integer.MAX_VALUE); + int ph = p.getPhase(); + check(ph < 0 || ph == phase); + prevPhase = phase; + } + }}; + } + + void test(String[] args) throws Throwable { + final Phaser parent = new Phaser(); + final Phaser child1 = new Phaser(parent); + final Phaser child2 = new Phaser(parent); + + Thread t1 = new Thread(runner(child1)); + Thread t2 = new Thread(runner(child2)); + t1.start(); + t2.start(); + + for (int prevPhase = 0, phase; ; prevPhase = phase) { + phase = child2.getPhase(); + check(phase >= prevPhase); + if (System.nanoTime() - quittingTimeNanos > 0) { + System.err.printf("phase=%d%n", phase); + child1.forceTermination(); + break; + } + } + + t1.join(); + t2.join(); + } + + //--------------------- Infrastructure --------------------------- + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++; Thread.dumpStack();} + void fail(String msg) {System.err.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond) {if (cond) pass(); else fail();} + void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + new TieredArriveLoops(args).instanceMain(args);} + public void instanceMain(String[] args) throws Throwable { + try {test(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} + + abstract class CheckedRunnable implements Runnable { + protected abstract void realRun() throws Throwable; + + public final void run() { + try {realRun();} catch (Throwable t) {unexpected(t);} + } + } +} diff --git a/test/java/util/concurrent/ThreadPoolExecutor/CoreThreadTimeOut.java b/test/java/util/concurrent/ThreadPoolExecutor/CoreThreadTimeOut.java index 6bd37fe7035eabb8de60d8e4ea88da5ac1e6d0ed..547cd2130f0bf4ef7b28717e474f05df0905a9d7 100644 --- a/test/java/util/concurrent/ThreadPoolExecutor/CoreThreadTimeOut.java +++ b/test/java/util/concurrent/ThreadPoolExecutor/CoreThreadTimeOut.java @@ -31,47 +31,79 @@ import java.util.concurrent.*; public class CoreThreadTimeOut { - static volatile int passed = 0, failed = 0; - static void pass() { passed++; } - static void fail() { failed++; Thread.dumpStack(); } - static void unexpected(Throwable t) { failed++; t.printStackTrace(); } - static void check(boolean cond) { if (cond) pass(); else fail(); } - static void equal(Object x, Object y) { - if (x == null ? y == null : x.equals(y)) pass(); - else {System.out.println(x + " not equal to " + y); fail(); }} - static int countExecutorThreads() { + static class IdentifiableThreadFactory implements ThreadFactory { + static ThreadFactory defaultThreadFactory + = Executors.defaultThreadFactory(); + + public Thread newThread(Runnable r) { + Thread t = defaultThreadFactory.newThread(r); + t.setName("CoreThreadTimeOut-" + t.getName()); + return t; + } + } + + int countExecutorThreads() { Thread[] threads = new Thread[Thread.activeCount()+100]; Thread.enumerate(threads); int count = 0; for (Thread t : threads) - if (t != null && t.getName().matches("pool-[0-9]+-thread-[0-9]+")) + if (t != null && + t.getName().matches + ("CoreThreadTimeOut-pool-[0-9]+-thread-[0-9]+")) count++; return count; } - public static void main(String[] args) throws Throwable { + long millisElapsedSince(long t0) { + return (System.nanoTime() - t0) / (1000L * 1000L); + } + + void test(String[] args) throws Throwable { final int threadCount = 10; + final int timeoutMillis = 30; BlockingQueue q = new ArrayBlockingQueue(2*threadCount); ThreadPoolExecutor tpe = new ThreadPoolExecutor(threadCount, threadCount, - 30, TimeUnit.MILLISECONDS, - q); + timeoutMillis, TimeUnit.MILLISECONDS, + q, new IdentifiableThreadFactory()); equal(tpe.getCorePoolSize(), threadCount); check(! tpe.allowsCoreThreadTimeOut()); tpe.allowCoreThreadTimeOut(true); check(tpe.allowsCoreThreadTimeOut()); equal(countExecutorThreads(), 0); + long t0 = System.nanoTime(); for (int i = 0; i < threadCount; i++) tpe.submit(new Runnable() { public void run() {}}); - equal(countExecutorThreads(), threadCount); - Thread.sleep(500); + int count = countExecutorThreads(); + if (millisElapsedSince(t0) < timeoutMillis) + equal(count, threadCount); + while (countExecutorThreads() > 0 && + millisElapsedSince(t0) < 10 * 1000); equal(countExecutorThreads(), 0); tpe.shutdown(); check(tpe.allowsCoreThreadTimeOut()); + check(tpe.awaitTermination(10, TimeUnit.SECONDS)); System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); if (failed > 0) throw new Exception("Some tests failed"); } + + //--------------------- Infrastructure --------------------------- + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++; Thread.dumpStack();} + void fail(String msg) {System.err.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond) {if (cond) pass(); else fail();} + void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + new CoreThreadTimeOut().instanceMain(args);} + public void instanceMain(String[] args) throws Throwable { + try {test(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} } diff --git a/test/javax/script/CauseExceptionTest.java b/test/javax/script/CauseExceptionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..535717609e97f40eebaeb59777edb4ab81d6d9a1 --- /dev/null +++ b/test/javax/script/CauseExceptionTest.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6869617 + * @summary RhinoScriptEngine bug : ScriptException cause not set (with fix) + */ + +import javax.script.*; +import java.io.*; + +public class CauseExceptionTest { + public static void main(String[] args) throws ScriptException, NoSuchMethodException { + ScriptEngineManager sem = new ScriptEngineManager(); + ScriptEngine engine = sem.getEngineByName("js"); + engine.eval("function hello_world() { println('hello world'); throw 'out of here'; } "); + Invocable invocable = (Invocable) engine; + try { + invocable.invokeFunction("hello_world", (Object[])null); + } catch (ScriptException se) { + Throwable cause = se.getCause(); + if (cause == null) { + throw new RuntimeException("null cause"); + } + System.out.println(cause); + } + } +}; diff --git a/test/javax/script/StringWriterPrintTest.java b/test/javax/script/StringWriterPrintTest.java new file mode 100644 index 0000000000000000000000000000000000000000..65b401ce637bb324f7a2698b1a3d625b560e0f0c --- /dev/null +++ b/test/javax/script/StringWriterPrintTest.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6759414 + * @summary javascript engine can not write to StringWriter. + */ + +import javax.script.*; +import java.io.*; + +public class StringWriterPrintTest { + public static void main(String[] args) throws ScriptException { + ScriptEngineManager sem = new ScriptEngineManager(); + ScriptEngine engine = sem.getEngineByName("js"); + StringWriter sw = new StringWriter(); + engine.eval("print(\"hello world 1\\n\")"); + engine.getContext().setWriter(sw); + // the following "print" call throws exception + engine.eval("print(\"hello world 2\\n\")"); + System.out.println(sw.toString()); + } +}; diff --git a/src/solaris/hpi/export/hpi_md.h b/test/javax/script/UnescapedBracketRegExTest.java similarity index 61% rename from src/solaris/hpi/export/hpi_md.h rename to test/javax/script/UnescapedBracketRegExTest.java index 92b96f50fc333fe9eceaab0fe1baf6e10f1b31e9..d444ec74aaa799c21639e097fb7d18c9b0500196 100644 --- a/src/solaris/hpi/export/hpi_md.h +++ b/test/javax/script/UnescapedBracketRegExTest.java @@ -1,12 +1,10 @@ /* - * Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. + * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or @@ -23,14 +21,20 @@ * questions. */ -#ifndef _JAVASOFT_HPI_MD_H_ -#define _JAVASOFT_HPI_MD_H_ - -#include "timeval_md.h" -#include "io_md.h" -#include "path_md.h" -#include "byteorder_md.h" +/* + * @test + * @bug 7012701 + * @summary 7012701 Add a test to check that Rhino's RegExp parser accepts unescaped '[' + */ -#define HPI_TIMEOUT_INFINITY ((jlong)(-1)) +import javax.script.*; +import java.io.*; -#endif /* !_JAVASOFT_HPI_MD_H_ */ +public class UnescapedBracketRegExTest { + public static void main(String[] args) throws ScriptException { + ScriptEngineManager sem = new ScriptEngineManager(); + ScriptEngine engine = sem.getEngineByName("js"); + // the following throws exception + engine.eval("var x = /[a-zA-Z+/=]/;"); + } +}; diff --git a/test/javax/swing/JFileChooser/6342301/bug6342301.java b/test/javax/swing/JFileChooser/6342301/bug6342301.java new file mode 100644 index 0000000000000000000000000000000000000000..54b4128d96678f0c5a86757e9f62846a4cd1dda0 --- /dev/null +++ b/test/javax/swing/JFileChooser/6342301/bug6342301.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + @bug 6342301 + @summary Bad interaction between setting the ui and file filters in JFileChooser + @author Pavel Porvatov +*/ + +import javax.swing.*; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.metal.MetalFileChooserUI; +import javax.swing.plaf.metal.MetalLookAndFeel; +import java.io.File; + +public class bug6342301 { + private static String tempDir; + + public static void main(String[] args) throws Exception { + tempDir = System.getProperty("java.io.tmpdir"); + + if (tempDir.length() == 0) { //'java.io.tmpdir' isn't guaranteed to be defined + tempDir = System.getProperty("user.home"); + } + + System.out.println("Temp directory: " + tempDir); + + UIManager.setLookAndFeel(new MetalLookAndFeel()); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + HackedFileChooser openChooser = new HackedFileChooser(); + + openChooser.setUI(new MetalFileChooserUI(openChooser)); + openChooser.setCurrentDirectory(new File(tempDir)); + } + }); + } + + private static class HackedFileChooser extends JFileChooser { + public void setUI(ComponentUI newUI) { + super.setUI(newUI); + } + } +} diff --git a/test/javax/swing/JLabel/7004134/bug7004134.java b/test/javax/swing/JLabel/7004134/bug7004134.java new file mode 100644 index 0000000000000000000000000000000000000000..09be54bee06526d198f03c7f3e2c4f00d29b50b7 --- /dev/null +++ b/test/javax/swing/JLabel/7004134/bug7004134.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + @bug 7004134 + @summary JLabel containing a ToolTipText does no longer show ToolTip after browser refresh + @author Pavel Porvatov +*/ + +import sun.awt.SunToolkit; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.MouseEvent; +import java.lang.reflect.Field; + +public class bug7004134 { + private static volatile JFrame frame; + + private static volatile JLabel label; + + private static volatile int toolTipWidth; + + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + label = new JLabel("A JLabel used as object for an HTML-formatted tooltip"); + label.setToolTipText("An HTML-formatted ToolTip"); + + frame = new JFrame(); + + frame.add(label); + frame.pack(); + frame.setVisible(true); + + ToolTipManager toolTipManager = ToolTipManager.sharedInstance(); + + toolTipManager.setInitialDelay(0); + toolTipManager.mouseMoved(new MouseEvent(label, 0, 0, 0, 0, 0, 0, false)); + } + }); + + Thread.sleep(500); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + toolTipWidth = getTipWindow().getWidth(); + + frame.dispose(); + } + }); + + Thread thread = new Thread(new ThreadGroup("Some ThreadGroup"), new Runnable() { + public void run() { + SunToolkit.createNewAppContext(); + + try { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame = new JFrame(); + + frame.add(label); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.pack(); + frame.setVisible(true); + + ToolTipManager toolTipManager = ToolTipManager.sharedInstance(); + + toolTipManager.setInitialDelay(0); + toolTipManager.mouseMoved(new MouseEvent(label, 0, 0, 0, 0, 0, 0, false)); + } + }); + + Thread.sleep(500); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + int newToolTipWidth = getTipWindow().getWidth(); + + frame.dispose(); + + if (toolTipWidth != newToolTipWidth) { + throw new RuntimeException("Tooltip width is different. Initial: " + toolTipWidth + + ", new: " + newToolTipWidth); + } + } + }); + } catch (Exception e) { + throw new RuntimeException(e); + } + + } + }); + + thread.start(); + thread.join(); + } + + private static Component getTipWindow() { + try { + Field tipWindowField = ToolTipManager.class.getDeclaredField("tipWindow"); + + tipWindowField.setAccessible(true); + + Popup value = (Popup) tipWindowField.get(ToolTipManager.sharedInstance()); + + Field componentField = Popup.class.getDeclaredField("component"); + + componentField.setAccessible(true); + + return (Component) componentField.get(value); + } catch (Exception e) { + throw new RuntimeException("getToolTipComponent failed", e); + } + } +} diff --git a/test/javax/swing/text/NavigationFilter/6735293/bug6735293.java b/test/javax/swing/text/NavigationFilter/6735293/bug6735293.java new file mode 100644 index 0000000000000000000000000000000000000000..4d077ceba15ebde66271a4a2bf45f49147df3e12 --- /dev/null +++ b/test/javax/swing/text/NavigationFilter/6735293/bug6735293.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6735293 + * @summary javax.swing.text.NavigationFilter.getNextVisualPositionFrom() not always throws BadLocationException + * @author Pavel Porvatov + */ + +import javax.swing.*; +import javax.swing.text.BadLocationException; +import javax.swing.text.NavigationFilter; +import javax.swing.text.Position; + +public class bug6735293 { + private static volatile JFormattedTextField jtf; + + private static volatile NavigationFilter nf; + + private static volatile JFrame jFrame; + + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + jtf = new JFormattedTextField(); + nf = new NavigationFilter(); + jtf.setText("A text message"); + + jFrame = new JFrame(); + jFrame.getContentPane().add(jtf); + jFrame.pack(); + jFrame.setVisible(true); + } + }); + + Thread.sleep(1000); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + Position.Bias[] biasRet = {Position.Bias.Forward}; + + for (int direction : new int[]{ + SwingConstants.EAST, + SwingConstants.WEST, + // the following constants still will lead to "BadLocationException: Length must be positive" + SwingConstants.SOUTH, + SwingConstants.NORTH, + }) { + for (int position : new int[]{-100, Integer.MIN_VALUE}) { + for (Position.Bias bias : new Position.Bias[]{Position.Bias.Backward, Position.Bias.Forward}) { + try { + nf.getNextVisualPositionFrom(jtf, position, bias, direction, biasRet); + + throw new RuntimeException("BadLocationException was not thrown: position = " + + position + ", bias = " + bias + ", direction = " + direction); + } catch (BadLocationException e) { + // Ok + } + } + } + } + + jFrame.dispose(); + } + }); + } +} diff --git a/test/javax/swing/text/html/parser/Parser/6990651/bug6990651.java b/test/javax/swing/text/html/parser/Parser/6990651/bug6990651.java new file mode 100644 index 0000000000000000000000000000000000000000..e956140aee7d8c641ae6c02902dadcde1761f0b8 --- /dev/null +++ b/test/javax/swing/text/html/parser/Parser/6990651/bug6990651.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + @bug 6990651 + @summary Regression: NPE when refreshing applet since 6u22-b01 + @author Pavel Porvatov +*/ +import sun.awt.SunToolkit; + +import javax.swing.*; + +public class bug6990651 { + private static volatile JEditorPane editor; + + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + editor = new JEditorPane("text/html", "Hello world!"); + } + }); + + Thread thread = new Thread(new ThreadGroup("Some ThreadGroup"), new Runnable() { + public void run() { + SunToolkit.createNewAppContext(); + + try { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + editor.setText("Hello world!"); + } + }); + } catch (Exception e) { + throw new RuntimeException(e); + } + + } + }); + + thread.start(); + thread.join(); + } +} diff --git a/test/sun/net/InetAddress/nameservice/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor b/test/sun/net/InetAddress/nameservice/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor deleted file mode 100644 index 6fc851da50fd2b07458d698f7c1b2c8dc88f06fb..0000000000000000000000000000000000000000 --- a/test/sun/net/InetAddress/nameservice/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor +++ /dev/null @@ -1,2 +0,0 @@ -# name service provider descriptor -SimpleNameServiceDescriptor diff --git a/test/sun/net/InetAddress/nameservice/chaining/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor b/test/sun/net/InetAddress/nameservice/chaining/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor new file mode 100644 index 0000000000000000000000000000000000000000..5ed3b8ea7550dcc287b8d3f1e8a0472e77b3acf3 --- /dev/null +++ b/test/sun/net/InetAddress/nameservice/chaining/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor @@ -0,0 +1,23 @@ +# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions + +Simple1NameServiceDescriptor +Simple2NameServiceDescriptor diff --git a/test/java/net/InetAddress/B4762344.java b/test/sun/net/InetAddress/nameservice/chaining/Providers.java similarity index 90% rename from test/java/net/InetAddress/B4762344.java rename to test/sun/net/InetAddress/nameservice/chaining/Providers.java index 0e287059d008c2dce504e5f934b7ac4e205e99e3..590f4e25a94b0c110d23394a9bed378d76db6e0d 100644 --- a/test/java/net/InetAddress/B4762344.java +++ b/test/sun/net/InetAddress/nameservice/chaining/Providers.java @@ -25,15 +25,17 @@ * @test * @bug 4762344 * @summary 2nd nameservice provider is non functional - * @build B4762344 SimpleNameService Simple1NameServiceDescriptor Simple2NameServiceDescriptor - * @run main/othervm -Dsun.net.spi.nameservice.provider.1=simple1,sun -Dsun.net.spi.nameservice.provider.2=simple2,sun B4762344 + * @compile -XDignore.symbol.file=true SimpleNameService.java + * Simple1NameServiceDescriptor.java + * Simple2NameServiceDescriptor.java + * @run main/othervm -Dsun.net.spi.nameservice.provider.1=simple1,sun -Dsun.net.spi.nameservice.provider.2=simple2,sun Providers */ import java.net.*; import java.util.*; -public class B4762344 { +public class Providers { private static String[][] hostnames = new String[][] { // both providers know this host, but with different address new String[] {"blade", "10.0.0.1"}, diff --git a/test/java/net/InetAddress/Simple1NameServiceDescriptor.java b/test/sun/net/InetAddress/nameservice/chaining/Simple1NameServiceDescriptor.java similarity index 100% rename from test/java/net/InetAddress/Simple1NameServiceDescriptor.java rename to test/sun/net/InetAddress/nameservice/chaining/Simple1NameServiceDescriptor.java diff --git a/test/java/net/InetAddress/Simple2NameServiceDescriptor.java b/test/sun/net/InetAddress/nameservice/chaining/Simple2NameServiceDescriptor.java similarity index 100% rename from test/java/net/InetAddress/Simple2NameServiceDescriptor.java rename to test/sun/net/InetAddress/nameservice/chaining/Simple2NameServiceDescriptor.java diff --git a/test/java/net/InetAddress/SimpleNameService.java b/test/sun/net/InetAddress/nameservice/chaining/SimpleNameService.java similarity index 100% rename from test/java/net/InetAddress/SimpleNameService.java rename to test/sun/net/InetAddress/nameservice/chaining/SimpleNameService.java diff --git a/test/sun/net/InetAddress/nameservice/deadlock/Hang.java b/test/sun/net/InetAddress/nameservice/deadlock/Hang.java new file mode 100644 index 0000000000000000000000000000000000000000..79246ea8d891916d38bf7d095d2454ecfb421247 --- /dev/null +++ b/test/sun/net/InetAddress/nameservice/deadlock/Hang.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 7012768 + * @compile -XDignore.symbol.file=true ThrowingNameService.java + * ThrowingNameServiceDescriptor.java + * @run main/othervm/timeout=30 -Dsun.net.spi.nameservice.provider.1=throwing,sun Hang + * @summary InetAddress lookupTable leaks/deadlocks when using unsupported + * name service spi + */ + +import java.net.InetAddress; + +public class Hang { + public static void main(String[] args) throws Exception { + try { + // 1st attempt - IllegalStateException caught below + InetAddress.getByName("host.company.com"); + } catch (IllegalStateException e) { } + + // 2nd attempt - Stuck here forever if bug exists + InetAddress.getByName("host.company.com"); + } +} diff --git a/make/java/hpi/native/mapfile-vers b/test/sun/net/InetAddress/nameservice/deadlock/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor similarity index 71% rename from make/java/hpi/native/mapfile-vers rename to test/sun/net/InetAddress/nameservice/deadlock/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor index c7b9e6d9ead0140c2a6a1dd754c1386dcc249068..3490a904f5f2b94cea87ca4fbc91390f917b87ef 100644 --- a/make/java/hpi/native/mapfile-vers +++ b/test/sun/net/InetAddress/nameservice/deadlock/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor @@ -1,12 +1,9 @@ -# -# Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. +# published by the Free Software Foundation. # # This code is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or @@ -21,12 +18,5 @@ # Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA # or visit www.oracle.com if you need additional information or have any # questions. -# - -SUNWprivate_1.1 { - global: - DLL_Initialize; - local: - *; -}; +ThrowingNameServiceDescriptor diff --git a/src/solaris/hpi/include/hpi_init.h b/test/sun/net/InetAddress/nameservice/deadlock/ThrowingNameService.java similarity index 52% rename from src/solaris/hpi/include/hpi_init.h rename to test/sun/net/InetAddress/nameservice/deadlock/ThrowingNameService.java index b657a86ccf4af0b2dac58fb4de300a975b03c97b..292b31dda882403d8ad9a17883cf5b905d143990 100644 --- a/src/solaris/hpi/include/hpi_init.h +++ b/test/sun/net/InetAddress/nameservice/deadlock/ThrowingNameService.java @@ -1,12 +1,10 @@ /* - * Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. + * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or @@ -23,15 +21,27 @@ * questions. */ -#ifndef _JAVASOFT_SOLARIS_HPI_INIT_H_ -#define _JAVASOFT_SOLARIS_HPI_INIT_H_ +import java.net.InetAddress; +import java.net.UnknownHostException; +import sun.net.spi.nameservice.NameService; -#ifndef NATIVE -extern void InitializeSbrk(void); -extern void InitializeAsyncIO(void); -extern void InitializeHelperThreads(void); -#endif /* NATIVE */ +public class ThrowingNameService implements NameService { + static boolean firstCall = true; -extern void InitializeMem(void); + @Override + public InetAddress[] lookupAllHostAddr(String host) throws UnknownHostException { + if (firstCall) { + firstCall = false; + // throw unchecked exception first time round + throw new IllegalStateException(); + } -#endif /* _JAVASOFT_SOLARIS_HPI_INIT_H_ */ + // return any valid address + return new InetAddress[] { InetAddress.getLoopbackAddress() }; + } + + @Override + public String getHostByAddr(byte[] addr) throws UnknownHostException { + throw new IllegalStateException(); + } +} diff --git a/src/windows/hpi/export/hpi_md.h b/test/sun/net/InetAddress/nameservice/deadlock/ThrowingNameServiceDescriptor.java similarity index 65% rename from src/windows/hpi/export/hpi_md.h rename to test/sun/net/InetAddress/nameservice/deadlock/ThrowingNameServiceDescriptor.java index 92b96f50fc333fe9eceaab0fe1baf6e10f1b31e9..3075412857fd6b4f6effca1c964e9b250a9b4e82 100644 --- a/src/windows/hpi/export/hpi_md.h +++ b/test/sun/net/InetAddress/nameservice/deadlock/ThrowingNameServiceDescriptor.java @@ -1,12 +1,10 @@ /* - * Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. + * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or @@ -23,14 +21,20 @@ * questions. */ -#ifndef _JAVASOFT_HPI_MD_H_ -#define _JAVASOFT_HPI_MD_H_ +import sun.net.spi.nameservice.*; -#include "timeval_md.h" -#include "io_md.h" -#include "path_md.h" -#include "byteorder_md.h" +public class ThrowingNameServiceDescriptor implements NameServiceDescriptor { + public NameService createNameService() { + return new ThrowingNameService(); + } -#define HPI_TIMEOUT_INFINITY ((jlong)(-1)) + @Override + public String getProviderName() { + return "sun"; + } -#endif /* !_JAVASOFT_HPI_MD_H_ */ + @Override + public String getType() { + return "throwing"; + } +} diff --git a/test/sun/net/InetAddress/nameservice/CacheTest.java b/test/sun/net/InetAddress/nameservice/simple/CacheTest.java similarity index 96% rename from test/sun/net/InetAddress/nameservice/CacheTest.java rename to test/sun/net/InetAddress/nameservice/simple/CacheTest.java index b6bf0e19ffcdad45ba7ededaed252bb76cb987af..0aadfd399ca7d83343af05d867fceb737392df58 100644 --- a/test/sun/net/InetAddress/nameservice/CacheTest.java +++ b/test/sun/net/InetAddress/nameservice/simple/CacheTest.java @@ -26,8 +26,8 @@ * @summary Check that InetAddress doesn't continue to throw UHE * after the name service has recovered and the negative ttl * on the initial lookup has expired. - * - * @build CacheTest SimpleNameService SimpleNameServiceDescriptor + * @compile -XDignore.symbol.file=true SimpleNameService.java + * SimpleNameServiceDescriptor.java * @run main/othervm/timeout=200 -Dsun.net.spi.nameservice.provider.1=simple,sun CacheTest */ import java.net.InetAddress; diff --git a/test/sun/net/InetAddress/nameservice/B6442088.java b/test/sun/net/InetAddress/nameservice/simple/DefaultCaching.java similarity index 94% rename from test/sun/net/InetAddress/nameservice/B6442088.java rename to test/sun/net/InetAddress/nameservice/simple/DefaultCaching.java index a68f7983052323ad3d15429d67b4de87f61aac93..f1010daa55f573b4c61de915627fabc400c1429b 100644 --- a/test/sun/net/InetAddress/nameservice/B6442088.java +++ b/test/sun/net/InetAddress/nameservice/simple/DefaultCaching.java @@ -25,15 +25,15 @@ * @bug 6442088 * @summary Change default DNS caching behavior for code not running under * security manager. - * - * @build B6442088 SimpleNameService SimpleNameServiceDescriptor - * @run main/othervm/timeout=200 -Dsun.net.inetaddr.ttl=20 -Dsun.net.spi.nameservice.provider.1=simple,sun B6442088 + * @compile -XDignore.symbol.file=true SimpleNameService.java + * SimpleNameServiceDescriptor.java + * @run main/othervm/timeout=200 -Dsun.net.inetaddr.ttl=20 -Dsun.net.spi.nameservice.provider.1=simple,sun DefaultCaching */ import java.net.InetAddress; import java.net.UnknownHostException; import java.security.Security; -public class B6442088 { +public class DefaultCaching { public static void main(String args[]) throws Exception { diff --git a/test/sun/net/InetAddress/nameservice/simple/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor b/test/sun/net/InetAddress/nameservice/simple/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor new file mode 100644 index 0000000000000000000000000000000000000000..b7527c070740f2a42159f97a17fb2dde107def49 --- /dev/null +++ b/test/sun/net/InetAddress/nameservice/simple/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor @@ -0,0 +1,22 @@ +# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. + +SimpleNameServiceDescriptor # name service provider descriptor diff --git a/test/sun/net/InetAddress/nameservice/SimpleNameService.java b/test/sun/net/InetAddress/nameservice/simple/SimpleNameService.java similarity index 100% rename from test/sun/net/InetAddress/nameservice/SimpleNameService.java rename to test/sun/net/InetAddress/nameservice/simple/SimpleNameService.java diff --git a/test/sun/net/InetAddress/nameservice/SimpleNameServiceDescriptor.java b/test/sun/net/InetAddress/nameservice/simple/SimpleNameServiceDescriptor.java similarity index 100% rename from test/sun/net/InetAddress/nameservice/SimpleNameServiceDescriptor.java rename to test/sun/net/InetAddress/nameservice/simple/SimpleNameServiceDescriptor.java diff --git a/test/sun/security/krb5/IPv6.java b/test/sun/security/krb5/IPv6.java index 58abbe9739eea0f7eb2ffd657c9f41dd8f92a7b3..4b4f2a88767623db4780f07f93cb4fdf60c828ad 100644 --- a/test/sun/security/krb5/IPv6.java +++ b/test/sun/security/krb5/IPv6.java @@ -78,8 +78,8 @@ public class IPv6 { try { Subject subject = new Subject(); Krb5LoginModule krb5 = new Krb5LoginModule(); - Map map = new HashMap(); - Map shared = new HashMap(); + Map map = new HashMap<>(); + Map shared = new HashMap<>(); map.put("debug", "true"); map.put("doNotPrompt", "true"); diff --git a/test/sun/security/krb5/auto/CleanState.java b/test/sun/security/krb5/auto/CleanState.java index cc6e7e54322132e50c16f6e7d237a98272ad24d6..316a730edfe577f5a1e95683c0cfd10b9c11ecc7 100644 --- a/test/sun/security/krb5/auto/CleanState.java +++ b/test/sun/security/krb5/auto/CleanState.java @@ -49,11 +49,11 @@ public class CleanState { final char[] password = OneKDC.PASS; char[] badpassword = "hellokitty".toCharArray(); - Map map = new HashMap(); + Map map = new HashMap<>(); map.put("useTicketCache", "false"); map.put("doNotPrompt", "false"); map.put("tryFirstPass", "true"); - Map shared = new HashMap(); + Map shared = new HashMap<>(); shared.put("javax.security.auth.login.name", name); shared.put("javax.security.auth.login.password", badpassword); diff --git a/test/sun/security/krb5/auto/Context.java b/test/sun/security/krb5/auto/Context.java index 86726e3f7b9d6606361de7526adcdcc39362ed17..4c67109121fbe91dad6efae50dac96d067a688c6 100644 --- a/test/sun/security/krb5/auto/Context.java +++ b/test/sun/security/krb5/auto/Context.java @@ -117,8 +117,8 @@ public class Context { out.name = user; out.s = new Subject(); Krb5LoginModule krb5 = new Krb5LoginModule(); - Map map = new HashMap(); - Map shared = new HashMap(); + Map map = new HashMap<>(); + Map shared = new HashMap<>(); if (pass != null) { map.put("useFirstPass", "true"); @@ -151,7 +151,7 @@ public class Context { out.name = user; out.s = new Subject(); Krb5LoginModule krb5 = new Krb5LoginModule(); - Map map = new HashMap(); + Map map = new HashMap<>(); map.put("doNotPrompt", "true"); map.put("useTicketCache", "false"); diff --git a/test/sun/security/krb5/auto/HttpNegotiateServer.java b/test/sun/security/krb5/auto/HttpNegotiateServer.java index 96323b76553ea93535cd515c975ce9d4edb2608f..e25e60d6ab54dd8497fab111d00dc35dd11daad9 100644 --- a/test/sun/security/krb5/auto/HttpNegotiateServer.java +++ b/test/sun/security/krb5/auto/HttpNegotiateServer.java @@ -297,8 +297,8 @@ public class HttpNegotiateServer { } Krb5LoginModule krb5 = new Krb5LoginModule(); - Map map = new HashMap(); - Map shared = new HashMap(); + Map map = new HashMap<>(); + Map shared = new HashMap<>(); map.put("storeKey", "true"); map.put("isInitiator", "false"); diff --git a/test/sun/security/krb5/auto/KDC.java b/test/sun/security/krb5/auto/KDC.java index 796415bb03e3f63493bb10e45865c8c0aa127bdc..36dc08b4ae677133cadfaab2b55ba60ee7474a83 100644 --- a/test/sun/security/krb5/auto/KDC.java +++ b/test/sun/security/krb5/auto/KDC.java @@ -132,7 +132,7 @@ public class KDC { // Principal db. principal -> pass. A case-insensitive TreeMap is used // so that even if the client provides a name with different case, the KDC // can still locate the principal and give back correct salt. - private TreeMap passwords = new TreeMap + private TreeMap passwords = new TreeMap<> (String.CASE_INSENSITIVE_ORDER); // Realm name @@ -142,9 +142,9 @@ public class KDC { // Service port number private int port; // The request/response job queue - private BlockingQueue q = new ArrayBlockingQueue(100); + private BlockingQueue q = new ArrayBlockingQueue<>(100); // Options - private Map options = new HashMap(); + private Map options = new HashMap<>(); private Thread thread1, thread2, thread3; DatagramSocket u1 = null; @@ -537,7 +537,7 @@ public class KDC { } } - private Map policies = new HashMap(); + private Map policies = new HashMap<>(); public void setPolicy(String rule, String value) { if (value == null) { @@ -760,7 +760,7 @@ public class KDC { private byte[] processAsReq(byte[] in) throws Exception { ASReq asReq = new ASReq(in); int[] eTypes = null; - List outPAs = new ArrayList(); + List outPAs = new ArrayList<>(); try { System.out.println(realm + "> " + asReq.reqBody.cname + diff --git a/test/sun/security/krb5/auto/LoginModuleOptions.java b/test/sun/security/krb5/auto/LoginModuleOptions.java index 44c4a414d0db801a9bc90f10eb1dc756e4931d5e..f22f774316fee21f63a19119effec86503d39ada 100644 --- a/test/sun/security/krb5/auto/LoginModuleOptions.java +++ b/test/sun/security/krb5/auto/LoginModuleOptions.java @@ -135,8 +135,8 @@ public class LoginModuleOptions { throws Exception { Krb5LoginModule krb5 = new Krb5LoginModule(); Subject subject = new Subject(); - Map map = new HashMap(); - Map shared = new HashMap(); + Map map = new HashMap<>(); + Map shared = new HashMap<>(); int count = options.length / 2; for (int i = 0; i < count; i++) { diff --git a/test/sun/security/krb5/tools/KtabCheck.java b/test/sun/security/krb5/tools/KtabCheck.java index 0fe8b783168cc9acdfd953bc8c2c33b28b43cc9a..e82b83ac740af5f5815e5e8b0a9dee999779534d 100644 --- a/test/sun/security/krb5/tools/KtabCheck.java +++ b/test/sun/security/krb5/tools/KtabCheck.java @@ -39,7 +39,7 @@ public class KtabCheck { public static void main(String[] args) throws Exception { System.out.println("Checking " + Arrays.toString(args)); KeyTab ktab = KeyTab.getInstance(args[0]); - Set expected = new HashSet(); + Set expected = new HashSet<>(); for (int i=1; i> map = new HashMap>(); - List l = new ArrayList(); + Map> map = new HashMap<>(); + List l = new ArrayList<>(); l.add(cookies.get("Cookie")); map.put("Cookie",l); return Collections.unmodifiableMap(map);