6993732: Remove the HPI
Reviewed-by: ohair, lancea, chegar, mduigou, mchung, mr
This commit is contained in:
parent
fb91d40572
commit
5182f947a2
@ -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
|
||||
#
|
||||
|
@ -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.
|
||||
#
|
||||
|
@ -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
|
||||
|
@ -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".
|
||||
#
|
||||
|
@ -222,7 +222,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.
|
||||
@ -415,8 +415,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
|
||||
|
@ -133,7 +133,6 @@ JRE_DOCFILES += $(JRE_NAMECHANGE_DOCLIST:%=$(JRE_IMAGE_DIR)/%$(TEXT_SUFFIX))
|
||||
# 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
|
||||
@ -802,7 +801,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.
|
||||
@ -1089,8 +1088,7 @@ 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
|
||||
|
@ -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
|
||||
|
@ -24,7 +24,7 @@
|
||||
#
|
||||
|
||||
#
|
||||
# Makefile for native threads HPI.
|
||||
# Makefile for fdlibm
|
||||
#
|
||||
# Note:
|
||||
# The fdlibm libraries are built using special rules in Library.gmk.
|
||||
|
@ -1,41 +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.
|
||||
#
|
||||
|
||||
#
|
||||
# Build HPI (Host Porting Interface) libraries
|
||||
#
|
||||
|
||||
BUILDDIR = ../..
|
||||
include $(BUILDDIR)/common/Defs.gmk
|
||||
|
||||
#
|
||||
# Build specified the HPI implementations
|
||||
#
|
||||
SUBDIRS = $(HPIS)
|
||||
include $(BUILDDIR)/common/Subdirs.gmk
|
||||
|
||||
all build clean clobber::
|
||||
$(SUBDIRS-loop)
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -1,32 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2000, 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.
|
||||
#
|
||||
|
||||
SUNWprivate_1.1 {
|
||||
global:
|
||||
DLL_Initialize;
|
||||
|
||||
local:
|
||||
*;
|
||||
};
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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_ */
|
@ -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 <jni.h>
|
||||
|
||||
/* 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_ */
|
@ -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 <stdio.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -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 <string.h>
|
||||
|
||||
#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;
|
||||
}
|
@ -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 <netinet/in.h>
|
||||
|
||||
#endif /* !_JAVASOFT_SOLARIS_BYTE_MD_H_ */
|
@ -1,36 +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_HPI_MD_H_
|
||||
#define _JAVASOFT_HPI_MD_H_
|
||||
|
||||
#include "timeval_md.h"
|
||||
#include "io_md.h"
|
||||
#include "path_md.h"
|
||||
#include "byteorder_md.h"
|
||||
|
||||
#define HPI_TIMEOUT_INFINITY ((jlong)(-1))
|
||||
|
||||
#endif /* !_JAVASOFT_HPI_MD_H_ */
|
@ -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 <sys/param.h>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#define LINE_SEPARATOR "\n"
|
||||
|
||||
/* file system macros moved to sysmacros_md.h */
|
||||
|
||||
#endif /* !_JAVASOFT_SOLARIS_IO_MD_H_ */
|
@ -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_ */
|
@ -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_ */
|
@ -1,37 +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_SOLARIS_HPI_INIT_H_
|
||||
#define _JAVASOFT_SOLARIS_HPI_INIT_H_
|
||||
|
||||
#ifndef NATIVE
|
||||
extern void InitializeSbrk(void);
|
||||
extern void InitializeAsyncIO(void);
|
||||
extern void InitializeHelperThreads(void);
|
||||
#endif /* NATIVE */
|
||||
|
||||
extern void InitializeMem(void);
|
||||
|
||||
#endif /* _JAVASOFT_SOLARIS_HPI_INIT_H_ */
|
@ -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_ */
|
@ -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_ */
|
@ -1,36 +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_LINUX_LARGEFILE_SUPPORT_H_
|
||||
#define _JAVASOFT_LINUX_LARGEFILE_SUPPORT_H_
|
||||
|
||||
/*
|
||||
* For building on glibc-2.0 we need to define stat64 here.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#endif /* _JAVASOFT_LINUX_LARGEFILE_SUPPORT_H_ */
|
@ -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 <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/**
|
||||
* 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_ */
|
@ -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_ */
|
@ -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 <mutex_md.h>
|
||||
#include <condvar_md.h>
|
||||
#include <threads_md.h>
|
||||
|
||||
/*
|
||||
* 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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -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 <thread.h>
|
||||
#include <sys/lwp.h>
|
||||
#include <synch.h>
|
||||
|
||||
#else /* USE_PTHREADS */
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
/* 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 <semaphore.h>
|
||||
#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_ */
|
@ -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_ */
|
@ -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 <errno.h>
|
||||
#include <time.h>
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
#include <limits.h>
|
||||
|
||||
#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);
|
||||
}
|
@ -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 <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#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;
|
||||
}
|
@ -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 <errno.h>
|
||||
#include <limits.h>
|
||||
|
||||
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;
|
||||
}
|
@ -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 <errno.h>
|
||||
|
||||
#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;
|
||||
}
|
@ -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 <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef HAVE_FILIOH
|
||||
#include <sys/filio.h>
|
||||
#else
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
#ifndef USE_SELECT
|
||||
#include <poll.h>
|
||||
#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 <sys/resource.h>
|
||||
|
||||
#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))
|
||||
}
|
@ -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 <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
|
||||
#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;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -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 <thread.h>
|
||||
#include <sys/lwp.h>
|
||||
#include <signal.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/procfs.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/syscall.h>
|
||||
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<lwpid_list_len; ++i) {
|
||||
if (lwpid_list[i] != oldlwpid_list[i]) {
|
||||
changed = B_TRUE; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!changed) break;
|
||||
|
||||
{
|
||||
id_t *tmplwpid_list = oldlwpid_list;
|
||||
oldlwpid_list = lwpid_list; oldlwpid_list_len = lwpid_list_len;
|
||||
lwpid_list = 0; lwpid_list_len = 0;
|
||||
lwpid_list = tmplwpid_list;
|
||||
}
|
||||
}
|
||||
|
||||
/* record regs for threads that were not on LWPs */
|
||||
record_thread_regs();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Restart all lwps in process. */
|
||||
static void
|
||||
restart_lwps()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < Mystatus.pr_nlwp; i++) {
|
||||
if (lwpid_list[i] == _lwp_self()) continue;
|
||||
if (_lwp_continue(lwpid_list[i]) < 0) {
|
||||
#ifdef MY_DEBUG
|
||||
VM_CALL(jio_fprintf)(stderr, "Failed to restart lwp %d\n",lwpid_list[i]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* restore the old priority of the thread */
|
||||
thr_setprio(thr_self(), gcprio);
|
||||
/* restore the oldmask */
|
||||
syscall(SYS_sigprocmask, SIG_SETMASK, &gcmask, NULL);
|
||||
|
||||
print_lwps();
|
||||
}
|
@ -1,171 +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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Threads interrupt dispatch
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
#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);
|
||||
}
|
@ -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 <stdio.h>
|
||||
#include <dlfcn.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#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;
|
||||
}
|
@ -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 <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h> /* For perror() */
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#include "hpi_impl.h"
|
||||
|
||||
#ifndef USE_MALLOC
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <fcntl.h>
|
||||
#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);
|
||||
}
|
@ -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 <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h> /* timeval */
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <netdb.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
#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
|
||||
}
|
@ -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_ */
|
@ -1,36 +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_HPI_MD_H_
|
||||
#define _JAVASOFT_HPI_MD_H_
|
||||
|
||||
#include "timeval_md.h"
|
||||
#include "io_md.h"
|
||||
#include "path_md.h"
|
||||
#include "byteorder_md.h"
|
||||
|
||||
#define HPI_TIMEOUT_INFINITY ((jlong)(-1))
|
||||
|
||||
#endif /* !_JAVASOFT_HPI_MD_H_ */
|
@ -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 <stdio.h>
|
||||
#include <io.h> /* For read(), lseek() etc. */
|
||||
#include <direct.h> /* For mkdir() */
|
||||
#include <windows.h>
|
||||
#include <winsock.h>
|
||||
#include <sys/types.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -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 <windows.h>
|
||||
|
||||
#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_ */
|
@ -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 <windows.h>
|
||||
|
||||
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_ */
|
@ -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 <windows.h>
|
||||
|
||||
#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_ */
|
@ -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 <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#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);
|
||||
}
|
@ -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 <windows.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#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);
|
||||
}
|
@ -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 <windows.h>
|
||||
|
||||
#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;
|
||||
}
|
@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <windows.h>
|
||||
#include <errno.h>
|
||||
|
||||
#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;
|
||||
}
|
@ -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 <windef.h>
|
||||
#include <winsock.h>
|
||||
|
||||
#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);
|
||||
}
|
@ -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 <io.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <limits.h>
|
||||
|
||||
#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; i<numEvents; i++) {
|
||||
if (lpBuffer[i].EventType == KEY_EVENT) {
|
||||
KEY_EVENT_RECORD *keyRecord = (KEY_EVENT_RECORD *)
|
||||
&(lpBuffer[i].Event);
|
||||
if (keyRecord->bKeyDown == 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);
|
||||
}
|
@ -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 <windows.h>
|
||||
#include <float.h> /* For constants for _control87() */
|
||||
#include <signal.h>
|
||||
#include <time.h> /* For _tzset() and _ftime() */
|
||||
#include <errno.h>
|
||||
|
||||
#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;
|
||||
}
|
@ -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 <windows.h>
|
||||
#include <process.h> /* for _beginthreadex(), _endthreadex() */
|
||||
#include <stdlib.h>
|
||||
|
||||
#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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user