6993732: Remove the HPI

Reviewed-by: ohair, lancea, chegar, mduigou, mchung, mr
This commit is contained in:
Alan Bateman 2011-01-07 15:49:44 +00:00
parent fb91d40572
commit 5182f947a2
67 changed files with 9 additions and 10670 deletions

View File

@ -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
#

View File

@ -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.
#

View File

@ -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

View File

@ -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".
#

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -24,7 +24,7 @@
#
#
# Makefile for native threads HPI.
# Makefile for fdlibm
#
# Note:
# The fdlibm libraries are built using special rules in Library.gmk.

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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:
*;
};

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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;
}

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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))
}

View File

@ -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

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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
}

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}