aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--agent/make/Makefile12
-rw-r--r--agent/src/os/bsd/BsdDebuggerLocal.c413
-rw-r--r--agent/src/os/bsd/Makefile78
-rw-r--r--agent/src/os/bsd/StubDebuggerLocal.c120
-rw-r--r--agent/src/os/bsd/elfmacros.h58
-rw-r--r--agent/src/os/bsd/libproc.h127
-rw-r--r--agent/src/os/bsd/libproc_impl.c452
-rw-r--r--agent/src/os/bsd/libproc_impl.h130
-rw-r--r--agent/src/os/bsd/mapfile66
-rw-r--r--agent/src/os/bsd/ps_core.c1023
-rw-r--r--agent/src/os/bsd/ps_proc.c444
-rw-r--r--agent/src/os/bsd/salibelf.c126
-rw-r--r--agent/src/os/bsd/salibelf.h52
-rw-r--r--agent/src/os/bsd/symtab.c239
-rw-r--r--agent/src/os/bsd/symtab.h50
-rw-r--r--agent/src/os/bsd/test.c59
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/BsdVtblAccess.java51
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/HotSpotAgent.java34
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/bugspot/BugSpotAgent.java36
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdAddress.java399
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdCDebugger.java121
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebugger.java82
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java595
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdOopHandle.java61
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThread.java81
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThreadContextFactory.java42
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/SharedObject.java48
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/amd64/BsdAMD64CFrame.java75
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/amd64/BsdAMD64ThreadContext.java46
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/x86/BsdX86CFrame.java75
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/x86/BsdX86ThreadContext.java46
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java68
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/runtime/Threads.java9
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/runtime/bsd/BsdSignals.java70
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/runtime/bsd_amd64/BsdAMD64JavaThreadPDAccess.java132
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/runtime/bsd_x86/BsdSignals.java70
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/runtime/bsd_x86/BsdX86JavaThreadPDAccess.java131
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/runtime/vmSymbols.java61
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java18
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java8
-rw-r--r--make/Makefile20
-rw-r--r--make/bsd/Makefile371
-rw-r--r--make/bsd/README26
-rw-r--r--make/bsd/adlc_updater20
-rw-r--r--make/bsd/build.sh95
-rw-r--r--make/bsd/makefiles/adjust-mflags.sh87
-rw-r--r--make/bsd/makefiles/adlc.make226
-rw-r--r--make/bsd/makefiles/amd64.make39
-rw-r--r--make/bsd/makefiles/arm.make29
-rw-r--r--make/bsd/makefiles/build_vm_def.sh12
-rw-r--r--make/bsd/makefiles/buildtree.make409
-rw-r--r--make/bsd/makefiles/compiler1.make31
-rw-r--r--make/bsd/makefiles/compiler2.make31
-rw-r--r--make/bsd/makefiles/core.make33
-rw-r--r--make/bsd/makefiles/cscope.make160
-rw-r--r--make/bsd/makefiles/debug.make44
-rw-r--r--make/bsd/makefiles/defs.make170
-rw-r--r--make/bsd/makefiles/dtrace.make27
-rw-r--r--make/bsd/makefiles/fastdebug.make64
-rw-r--r--make/bsd/makefiles/gcc.make267
-rw-r--r--make/bsd/makefiles/hp.make29
-rw-r--r--make/bsd/makefiles/hp1.make29
-rw-r--r--make/bsd/makefiles/i486.make34
-rw-r--r--make/bsd/makefiles/ia64.make43
-rw-r--r--make/bsd/makefiles/jsig.make67
-rw-r--r--make/bsd/makefiles/jvmg.make41
-rw-r--r--make/bsd/makefiles/jvmti.make117
-rw-r--r--make/bsd/makefiles/launcher.make93
-rw-r--r--make/bsd/makefiles/mapfile-vers-debug291
-rw-r--r--make/bsd/makefiles/mapfile-vers-jsig40
-rw-r--r--make/bsd/makefiles/mapfile-vers-product286
-rw-r--r--make/bsd/makefiles/optimized.make44
-rw-r--r--make/bsd/makefiles/ppc.make30
-rw-r--r--make/bsd/makefiles/product.make58
-rw-r--r--make/bsd/makefiles/profiled.make30
-rw-r--r--make/bsd/makefiles/rules.make216
-rw-r--r--make/bsd/makefiles/sa.make121
-rw-r--r--make/bsd/makefiles/saproc.make107
-rw-r--r--make/bsd/makefiles/shark.make32
-rw-r--r--make/bsd/makefiles/sparc.make24
-rw-r--r--make/bsd/makefiles/sparcWorks.make104
-rw-r--r--make/bsd/makefiles/sparcv9.make27
-rw-r--r--make/bsd/makefiles/tiered.make31
-rw-r--r--make/bsd/makefiles/top.make142
-rw-r--r--make/bsd/makefiles/vm.make329
-rw-r--r--make/bsd/makefiles/zero.make32
-rw-r--r--make/bsd/makefiles/zeroshark.make62
-rw-r--r--make/bsd/platform_amd6415
-rw-r--r--make/bsd/platform_amd64.suncc17
-rw-r--r--make/bsd/platform_i48615
-rw-r--r--make/bsd/platform_i486.suncc17
-rw-r--r--make/bsd/platform_ia6415
-rw-r--r--make/bsd/platform_sparc15
-rw-r--r--make/bsd/platform_sparcv915
-rw-r--r--make/bsd/platform_zero.in17
-rw-r--r--make/cscope.make2
-rw-r--r--make/defs.make14
-rw-r--r--make/linux/build.sh5
-rw-r--r--make/linux/makefiles/arm.make21
-rw-r--r--make/linux/makefiles/defs.make14
-rw-r--r--make/linux/makefiles/ppc.make21
-rw-r--r--make/linux/makefiles/sa.make26
-rw-r--r--make/sa.files13
-rw-r--r--make/solaris/makefiles/defs.make33
-rw-r--r--make/solaris/makefiles/sa.make26
-rw-r--r--make/windows/makefiles/defs.make11
-rw-r--r--make/windows/makefiles/sa.make5
-rw-r--r--src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp5
-rw-r--r--src/cpu/sparc/vm/stubGenerator_sparc.cpp4
-rw-r--r--src/cpu/x86/vm/bytes_x86.hpp3
-rw-r--r--src/cpu/x86/vm/c1_LIRAssembler_x86.cpp4
-rw-r--r--src/cpu/x86/vm/c1_LIRGenerator_x86.cpp5
-rw-r--r--src/cpu/x86/vm/copy_x86.hpp3
-rw-r--r--src/cpu/x86/vm/globals_x86.hpp4
-rw-r--r--src/cpu/x86/vm/interp_masm_x86_32.cpp7
-rw-r--r--src/cpu/x86/vm/interp_masm_x86_64.cpp3
-rw-r--r--src/cpu/x86/vm/jni_x86.h2
-rw-r--r--src/cpu/x86/vm/stubGenerator_x86_32.cpp3
-rw-r--r--src/cpu/x86/vm/stubGenerator_x86_64.cpp3
-rw-r--r--src/cpu/x86/vm/stubRoutines_x86_32.cpp3
-rw-r--r--src/cpu/x86/vm/stubRoutines_x86_64.cpp3
-rw-r--r--src/cpu/x86/vm/vm_version_x86.cpp3
-rw-r--r--src/cpu/zero/vm/bytes_zero.hpp3
-rw-r--r--src/cpu/zero/vm/globals_zero.hpp4
-rw-r--r--src/cpu/zero/vm/interp_masm_zero.cpp3
-rw-r--r--src/cpu/zero/vm/stubGenerator_zero.cpp3
-rw-r--r--src/cpu/zero/vm/stubRoutines_zero.cpp3
-rw-r--r--src/cpu/zero/vm/vm_version_zero.cpp3
-rw-r--r--src/os/bsd/vm/attachListener_bsd.cpp520
-rw-r--r--src/os/bsd/vm/c1_globals_bsd.hpp36
-rw-r--r--src/os/bsd/vm/c2_globals_bsd.hpp36
-rw-r--r--src/os/bsd/vm/chaitin_bsd.cpp42
-rw-r--r--src/os/bsd/vm/decoder_bsd.cpp66
-rw-r--r--src/os/bsd/vm/dtraceJSDT_bsd.cpp47
-rw-r--r--src/os/bsd/vm/globals_bsd.hpp55
-rw-r--r--src/os/bsd/vm/interfaceSupport_bsd.hpp34
-rw-r--r--src/os/bsd/vm/jsig.c225
-rw-r--r--src/os/bsd/vm/jvm_bsd.cpp192
-rw-r--r--src/os/bsd/vm/jvm_bsd.h120
-rw-r--r--src/os/bsd/vm/mutex_bsd.cpp33
-rw-r--r--src/os/bsd/vm/mutex_bsd.inline.hpp37
-rw-r--r--src/os/bsd/vm/osThread_bsd.cpp67
-rw-r--r--src/os/bsd/vm/osThread_bsd.hpp165
-rw-r--r--src/os/bsd/vm/os_bsd.cpp5709
-rw-r--r--src/os/bsd/vm/os_bsd.hpp368
-rw-r--r--src/os/bsd/vm/os_bsd.inline.hpp302
-rw-r--r--src/os/bsd/vm/os_share_bsd.hpp37
-rw-r--r--src/os/bsd/vm/perfMemory_bsd.cpp1041
-rw-r--r--src/os/bsd/vm/stubRoutines_bsd.cpp27
-rw-r--r--src/os/bsd/vm/threadCritical_bsd.cpp67
-rw-r--r--src/os/bsd/vm/thread_bsd.inline.hpp47
-rw-r--r--src/os/bsd/vm/vmError_bsd.cpp115
-rw-r--r--src/os/linux/vm/os_linux.cpp2
-rw-r--r--src/os/posix/launcher/java_md.c74
-rw-r--r--src/os/posix/launcher/launcher.script2
-rw-r--r--src/os_cpu/bsd_x86/vm/assembler_bsd_x86.cpp87
-rw-r--r--src/os_cpu/bsd_x86/vm/atomic_bsd_x86.inline.hpp221
-rw-r--r--src/os_cpu/bsd_x86/vm/bsd_x86_32.ad160
-rw-r--r--src/os_cpu/bsd_x86/vm/bsd_x86_32.s689
-rw-r--r--src/os_cpu/bsd_x86/vm/bsd_x86_64.ad173
-rw-r--r--src/os_cpu/bsd_x86/vm/bsd_x86_64.s410
-rw-r--r--src/os_cpu/bsd_x86/vm/bytes_bsd_x86.inline.hpp116
-rw-r--r--src/os_cpu/bsd_x86/vm/copy_bsd_x86.inline.hpp309
-rw-r--r--src/os_cpu/bsd_x86/vm/globals_bsd_x86.hpp54
-rw-r--r--src/os_cpu/bsd_x86/vm/orderAccess_bsd_x86.inline.hpp215
-rw-r--r--src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp1124
-rw-r--r--src/os_cpu/bsd_x86/vm/os_bsd_x86.hpp37
-rw-r--r--src/os_cpu/bsd_x86/vm/prefetch_bsd_x86.inline.hpp47
-rw-r--r--src/os_cpu/bsd_x86/vm/threadLS_bsd_x86.cpp92
-rw-r--r--src/os_cpu/bsd_x86/vm/threadLS_bsd_x86.hpp56
-rw-r--r--src/os_cpu/bsd_x86/vm/thread_bsd_x86.cpp84
-rw-r--r--src/os_cpu/bsd_x86/vm/thread_bsd_x86.hpp70
-rw-r--r--src/os_cpu/bsd_x86/vm/vmStructs_bsd_x86.hpp65
-rw-r--r--src/os_cpu/bsd_x86/vm/vm_version_bsd_x86.cpp27
-rw-r--r--src/os_cpu/bsd_zero/vm/assembler_bsd_zero.cpp32
-rw-r--r--src/os_cpu/bsd_zero/vm/atomic_bsd_zero.inline.hpp323
-rw-r--r--src/os_cpu/bsd_zero/vm/bytes_bsd_zero.inline.hpp67
-rw-r--r--src/os_cpu/bsd_zero/vm/globals_bsd_zero.hpp48
-rw-r--r--src/os_cpu/bsd_zero/vm/orderAccess_bsd_zero.inline.hpp176
-rw-r--r--src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp558
-rw-r--r--src/os_cpu/bsd_zero/vm/os_bsd_zero.hpp56
-rw-r--r--src/os_cpu/bsd_zero/vm/prefetch_bsd_zero.inline.hpp37
-rw-r--r--src/os_cpu/bsd_zero/vm/threadLS_bsd_zero.cpp40
-rw-r--r--src/os_cpu/bsd_zero/vm/threadLS_bsd_zero.hpp35
-rw-r--r--src/os_cpu/bsd_zero/vm/thread_bsd_zero.cpp32
-rw-r--r--src/os_cpu/bsd_zero/vm/thread_bsd_zero.hpp121
-rw-r--r--src/os_cpu/bsd_zero/vm/vmStructs_bsd_zero.hpp50
-rw-r--r--src/os_cpu/bsd_zero/vm/vm_version_bsd_zero.cpp30
-rw-r--r--src/os_cpu/linux_zero/vm/globals_linux_zero.hpp1
-rw-r--r--src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java33
-rw-r--r--src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCompilation.java4
-rw-r--r--src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java9
-rw-r--r--src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Phase.java4
-rw-r--r--src/share/vm/adlc/adlc.hpp4
-rw-r--r--src/share/vm/adlc/formssel.cpp2
-rw-r--r--src/share/vm/c1/c1_LIR.cpp11
-rw-r--r--src/share/vm/c1/c1_LIR.hpp2
-rw-r--r--src/share/vm/c1/c1_LIRGenerator.cpp4
-rw-r--r--src/share/vm/c1/c1_globals.hpp3
-rw-r--r--src/share/vm/ci/ciEnv.cpp30
-rw-r--r--src/share/vm/classfile/classLoader.cpp3
-rw-r--r--src/share/vm/classfile/javaClasses.cpp5
-rw-r--r--src/share/vm/classfile/vmSymbols.hpp3
-rw-r--r--src/share/vm/code/stubs.hpp3
-rw-r--r--src/share/vm/compiler/disassembler.hpp3
-rw-r--r--src/share/vm/gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.cpp3
-rw-r--r--src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.cpp3
-rw-r--r--src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp3
-rw-r--r--src/share/vm/gc_implementation/concurrentMarkSweep/freeBlockDictionary.cpp3
-rw-r--r--src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp3
-rw-r--r--src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp3
-rw-r--r--src/share/vm/gc_implementation/g1/ptrQueue.cpp3
-rw-r--r--src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp3
-rw-r--r--src/share/vm/gc_implementation/parallelScavenge/psVirtualspace.cpp3
-rw-r--r--src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp3
-rw-r--r--src/share/vm/gc_interface/collectedHeap.cpp3
-rw-r--r--src/share/vm/gc_interface/collectedHeap.hpp1
-rw-r--r--src/share/vm/gc_interface/collectedHeap.inline.hpp20
-rw-r--r--src/share/vm/interpreter/abstractInterpreter.hpp3
-rw-r--r--src/share/vm/interpreter/bytecodeInterpreter.cpp6
-rw-r--r--src/share/vm/interpreter/bytecodeTracer.cpp4
-rw-r--r--src/share/vm/interpreter/interpreterRuntime.hpp3
-rw-r--r--src/share/vm/interpreter/linkResolver.cpp3
-rw-r--r--src/share/vm/memory/allocation.cpp3
-rw-r--r--src/share/vm/memory/collectorPolicy.cpp3
-rw-r--r--src/share/vm/memory/defNewGeneration.cpp3
-rw-r--r--src/share/vm/memory/gcLocker.hpp4
-rw-r--r--src/share/vm/memory/genMarkSweep.cpp3
-rw-r--r--src/share/vm/memory/oopFactory.cpp9
-rw-r--r--src/share/vm/memory/oopFactory.hpp1
-rw-r--r--src/share/vm/memory/resourceArea.cpp3
-rw-r--r--src/share/vm/memory/resourceArea.hpp3
-rw-r--r--src/share/vm/memory/space.hpp3
-rw-r--r--src/share/vm/memory/threadLocalAllocBuffer.cpp3
-rw-r--r--src/share/vm/memory/universe.cpp3
-rw-r--r--src/share/vm/oops/constantPoolKlass.cpp3
-rw-r--r--src/share/vm/oops/constantPoolOop.cpp2
-rw-r--r--src/share/vm/oops/instanceKlass.cpp3
-rw-r--r--src/share/vm/oops/markOop.cpp3
-rw-r--r--src/share/vm/oops/oop.cpp3
-rw-r--r--src/share/vm/oops/oopsHierarchy.cpp3
-rw-r--r--src/share/vm/oops/typeArrayKlass.cpp8
-rw-r--r--src/share/vm/oops/typeArrayKlass.hpp3
-rw-r--r--src/share/vm/oops/typeArrayOop.hpp6
-rw-r--r--src/share/vm/opto/c2_globals.hpp3
-rw-r--r--src/share/vm/opto/library_call.cpp1
-rw-r--r--src/share/vm/opto/macro.cpp14
-rw-r--r--src/share/vm/opto/memnode.cpp4
-rw-r--r--src/share/vm/opto/memnode.hpp11
-rw-r--r--src/share/vm/opto/phaseX.cpp6
-rw-r--r--src/share/vm/opto/runtime.cpp32
-rw-r--r--src/share/vm/opto/runtime.hpp3
-rw-r--r--src/share/vm/prims/forte.cpp6
-rw-r--r--src/share/vm/prims/jni.cpp4
-rw-r--r--src/share/vm/prims/jvm.cpp3
-rw-r--r--src/share/vm/prims/jvm.h3
-rw-r--r--src/share/vm/prims/jvmtiEnv.cpp3
-rw-r--r--src/share/vm/prims/jvmtiImpl.cpp3
-rw-r--r--src/share/vm/prims/nativeLookup.cpp3
-rw-r--r--src/share/vm/runtime/arguments.cpp3
-rw-r--r--src/share/vm/runtime/atomic.cpp9
-rw-r--r--src/share/vm/runtime/fprofiler.hpp3
-rw-r--r--src/share/vm/runtime/globals.hpp18
-rw-r--r--src/share/vm/runtime/handles.cpp4
-rw-r--r--src/share/vm/runtime/handles.inline.hpp3
-rw-r--r--src/share/vm/runtime/interfaceSupport.hpp6
-rw-r--r--src/share/vm/runtime/java.cpp3
-rw-r--r--src/share/vm/runtime/javaCalls.cpp4
-rw-r--r--src/share/vm/runtime/javaCalls.hpp3
-rw-r--r--src/share/vm/runtime/javaFrameAnchor.hpp7
-rw-r--r--src/share/vm/runtime/jniHandles.cpp3
-rw-r--r--src/share/vm/runtime/memprofiler.cpp3
-rw-r--r--src/share/vm/runtime/mutex.cpp4
-rw-r--r--src/share/vm/runtime/mutexLocker.cpp3
-rw-r--r--src/share/vm/runtime/mutexLocker.hpp3
-rw-r--r--src/share/vm/runtime/objectMonitor.cpp4
-rw-r--r--src/share/vm/runtime/os.cpp15
-rw-r--r--src/share/vm/runtime/os.hpp12
-rw-r--r--src/share/vm/runtime/osThread.hpp3
-rw-r--r--src/share/vm/runtime/safepoint.cpp3
-rw-r--r--src/share/vm/runtime/synchronizer.cpp4
-rw-r--r--src/share/vm/runtime/task.cpp4
-rw-r--r--src/share/vm/runtime/thread.cpp4
-rw-r--r--src/share/vm/runtime/thread.hpp6
-rw-r--r--src/share/vm/runtime/threadLocalStorage.cpp4
-rw-r--r--src/share/vm/runtime/threadLocalStorage.hpp6
-rw-r--r--src/share/vm/runtime/timer.cpp3
-rw-r--r--src/share/vm/runtime/virtualspace.cpp3
-rw-r--r--src/share/vm/runtime/vmStructs.cpp23
-rw-r--r--src/share/vm/runtime/vmThread.cpp3
-rw-r--r--src/share/vm/runtime/vmThread.hpp3
-rw-r--r--src/share/vm/runtime/vm_operations.cpp3
-rw-r--r--src/share/vm/runtime/vm_version.cpp3
-rw-r--r--src/share/vm/utilities/accessFlags.cpp3
-rw-r--r--src/share/vm/utilities/array.cpp3
-rw-r--r--src/share/vm/utilities/bitMap.cpp3
-rw-r--r--src/share/vm/utilities/debug.cpp4
-rw-r--r--src/share/vm/utilities/decoder.cpp3
-rw-r--r--src/share/vm/utilities/decoder.hpp5
-rw-r--r--src/share/vm/utilities/elfFile.cpp2
-rw-r--r--src/share/vm/utilities/elfFile.hpp11
-rw-r--r--src/share/vm/utilities/elfStringTable.cpp3
-rw-r--r--src/share/vm/utilities/elfStringTable.hpp3
-rw-r--r--src/share/vm/utilities/elfSymbolTable.cpp2
-rw-r--r--src/share/vm/utilities/elfSymbolTable.hpp5
-rw-r--r--src/share/vm/utilities/events.cpp3
-rw-r--r--src/share/vm/utilities/exceptions.cpp3
-rw-r--r--src/share/vm/utilities/globalDefinitions.hpp78
-rw-r--r--src/share/vm/utilities/globalDefinitions_gcc.hpp27
-rw-r--r--src/share/vm/utilities/globalDefinitions_sparcWorks.hpp19
-rw-r--r--src/share/vm/utilities/globalDefinitions_visCPP.hpp14
-rw-r--r--src/share/vm/utilities/growableArray.cpp3
-rw-r--r--src/share/vm/utilities/histogram.hpp3
-rw-r--r--src/share/vm/utilities/macros.hpp8
-rw-r--r--src/share/vm/utilities/ostream.cpp5
-rw-r--r--src/share/vm/utilities/preserveException.hpp3
-rw-r--r--src/share/vm/utilities/taskqueue.cpp4
-rw-r--r--src/share/vm/utilities/taskqueue.hpp6
-rw-r--r--src/share/vm/utilities/vmError.cpp9
-rw-r--r--src/share/vm/utilities/workgroup.hpp3
-rw-r--r--test/Makefile16
-rw-r--r--test/jprt.config36
-rw-r--r--test/runtime/6929067/Test6929067.sh2
323 files changed, 26505 insertions, 266 deletions
diff --git a/agent/make/Makefile b/agent/make/Makefile
index fc845ffd0..981d2c862 100644
--- a/agent/make/Makefile
+++ b/agent/make/Makefile
@@ -53,6 +53,9 @@ sun.jvm.hotspot.code \
sun.jvm.hotspot.compiler \
sun.jvm.hotspot.debugger \
sun.jvm.hotspot.debugger.amd64 \
+sun.jvm.hotspot.debugger.bsd \
+sun.jvm.hotspot.debugger.bsd.amd64 \
+sun.jvm.hotspot.debugger.bsd.x86 \
sun.jvm.hotspot.debugger.cdbg \
sun.jvm.hotspot.debugger.cdbg.basic \
sun.jvm.hotspot.debugger.cdbg.basic.amd64 \
@@ -93,6 +96,9 @@ sun.jvm.hotspot.oops \
sun.jvm.hotspot.prims \
sun.jvm.hotspot.runtime \
sun.jvm.hotspot.runtime.amd64 \
+sun.jvm.hotspot.runtime.bsd \
+sun.jvm.hotspot.runtime.bsd_amd64 \
+sun.jvm.hotspot.runtime.bsd_x86 \
sun.jvm.hotspot.runtime.ia64 \
sun.jvm.hotspot.runtime.linux \
sun.jvm.hotspot.runtime.linux_amd64 \
@@ -143,6 +149,9 @@ sun/jvm/hotspot/code/*.java \
sun/jvm/hotspot/compiler/*.java \
sun/jvm/hotspot/debugger/*.java \
sun/jvm/hotspot/debugger/amd64/*.java \
+sun/jvm/hotspot/debugger/bsd/*.java \
+sun/jvm/hotspot/debugger/bsd/amd64/*.java \
+sun/jvm/hotspot/debugger/bsd/x86/*.java \
sun/jvm/hotspot/debugger/cdbg/*.java \
sun/jvm/hotspot/debugger/cdbg/basic/*.java \
sun/jvm/hotspot/debugger/cdbg/basic/amd64/*.java \
@@ -176,6 +185,9 @@ sun/jvm/hotspot/opto/*.java \
sun/jvm/hotspot/prims/*.java \
sun/jvm/hotspot/runtime/*.java \
sun/jvm/hotspot/runtime/amd64/*.java \
+sun/jvm/hotspot/runtime/bsd/*.java \
+sun/jvm/hotspot/runtime/bsd_amd64/*.java \
+sun/jvm/hotspot/runtime/bsd_x86/*.java \
sun/jvm/hotspot/runtime/ia64/*.java \
sun/jvm/hotspot/runtime/linux/*.java \
sun/jvm/hotspot/runtime/linux_amd64/*.java \
diff --git a/agent/src/os/bsd/BsdDebuggerLocal.c b/agent/src/os/bsd/BsdDebuggerLocal.c
new file mode 100644
index 000000000..85b07f764
--- /dev/null
+++ b/agent/src/os/bsd/BsdDebuggerLocal.c
@@ -0,0 +1,413 @@
+/*
+ * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include <stdlib.h>
+#include <jni.h>
+#include "libproc.h"
+
+#if defined(x86_64) && !defined(amd64)
+#define amd64 1
+#endif
+
+#ifdef i386
+#include "sun_jvm_hotspot_debugger_x86_X86ThreadContext.h"
+#endif
+
+#ifdef amd64
+#include "sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext.h"
+#endif
+
+#if defined(sparc) || defined(sparcv9)
+#include "sun_jvm_hotspot_debugger_sparc_SPARCThreadContext.h"
+#endif
+
+static jfieldID p_ps_prochandle_ID = 0;
+static jfieldID threadList_ID = 0;
+static jfieldID loadObjectList_ID = 0;
+
+static jmethodID createClosestSymbol_ID = 0;
+static jmethodID createLoadObject_ID = 0;
+static jmethodID getThreadForThreadId_ID = 0;
+static jmethodID listAdd_ID = 0;
+
+#define CHECK_EXCEPTION_(value) if ((*env)->ExceptionOccurred(env)) { return value; }
+#define CHECK_EXCEPTION if ((*env)->ExceptionOccurred(env)) { return;}
+#define THROW_NEW_DEBUGGER_EXCEPTION_(str, value) { throw_new_debugger_exception(env, str); return value; }
+#define THROW_NEW_DEBUGGER_EXCEPTION(str) { throw_new_debugger_exception(env, str); return;}
+
+static void throw_new_debugger_exception(JNIEnv* env, const char* errMsg) {
+ (*env)->ThrowNew(env, (*env)->FindClass(env, "sun/jvm/hotspot/debugger/DebuggerException"), errMsg);
+}
+
+static struct ps_prochandle* get_proc_handle(JNIEnv* env, jobject this_obj) {
+ jlong ptr = (*env)->GetLongField(env, this_obj, p_ps_prochandle_ID);
+ return (struct ps_prochandle*)(intptr_t)ptr;
+}
+
+/*
+ * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
+ * Method: init0
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0
+ (JNIEnv *env, jclass cls) {
+ jclass listClass;
+
+ if (init_libproc(getenv("LIBSAPROC_DEBUG") != NULL) != true) {
+ THROW_NEW_DEBUGGER_EXCEPTION("can't initialize libproc");
+ }
+
+ // fields we use
+ p_ps_prochandle_ID = (*env)->GetFieldID(env, cls, "p_ps_prochandle", "J");
+ CHECK_EXCEPTION;
+ threadList_ID = (*env)->GetFieldID(env, cls, "threadList", "Ljava/util/List;");
+ CHECK_EXCEPTION;
+ loadObjectList_ID = (*env)->GetFieldID(env, cls, "loadObjectList", "Ljava/util/List;");
+ CHECK_EXCEPTION;
+
+ // methods we use
+ createClosestSymbol_ID = (*env)->GetMethodID(env, cls, "createClosestSymbol",
+ "(Ljava/lang/String;J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;");
+ CHECK_EXCEPTION;
+ createLoadObject_ID = (*env)->GetMethodID(env, cls, "createLoadObject",
+ "(Ljava/lang/String;JJ)Lsun/jvm/hotspot/debugger/cdbg/LoadObject;");
+ CHECK_EXCEPTION;
+ getThreadForThreadId_ID = (*env)->GetMethodID(env, cls, "getThreadForThreadId",
+ "(J)Lsun/jvm/hotspot/debugger/ThreadProxy;");
+ CHECK_EXCEPTION;
+ // java.util.List method we call
+ listClass = (*env)->FindClass(env, "java/util/List");
+ CHECK_EXCEPTION;
+ listAdd_ID = (*env)->GetMethodID(env, listClass, "add", "(Ljava/lang/Object;)Z");
+ CHECK_EXCEPTION;
+}
+
+JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getAddressSize
+ (JNIEnv *env, jclass cls)
+{
+#ifdef _LP64
+ return 8;
+#else
+ return 4;
+#endif
+
+}
+
+
+static void fillThreadsAndLoadObjects(JNIEnv* env, jobject this_obj, struct ps_prochandle* ph) {
+ int n = 0, i = 0;
+
+ // add threads
+ n = get_num_threads(ph);
+ for (i = 0; i < n; i++) {
+ jobject thread;
+ jobject threadList;
+ lwpid_t lwpid;
+
+ lwpid = get_lwp_id(ph, i);
+ thread = (*env)->CallObjectMethod(env, this_obj, getThreadForThreadId_ID,
+ (jlong)lwpid);
+ CHECK_EXCEPTION;
+ threadList = (*env)->GetObjectField(env, this_obj, threadList_ID);
+ CHECK_EXCEPTION;
+ (*env)->CallBooleanMethod(env, threadList, listAdd_ID, thread);
+ CHECK_EXCEPTION;
+ }
+
+ // add load objects
+ n = get_num_libs(ph);
+ for (i = 0; i < n; i++) {
+ uintptr_t base;
+ const char* name;
+ jobject loadObject;
+ jobject loadObjectList;
+
+ base = get_lib_base(ph, i);
+ name = get_lib_name(ph, i);
+ loadObject = (*env)->CallObjectMethod(env, this_obj, createLoadObject_ID,
+ (*env)->NewStringUTF(env, name), (jlong)0, (jlong)base);
+ CHECK_EXCEPTION;
+ loadObjectList = (*env)->GetObjectField(env, this_obj, loadObjectList_ID);
+ CHECK_EXCEPTION;
+ (*env)->CallBooleanMethod(env, loadObjectList, listAdd_ID, loadObject);
+ CHECK_EXCEPTION;
+ }
+}
+
+/*
+ * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
+ * Method: attach0
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__I
+ (JNIEnv *env, jobject this_obj, jint jpid) {
+
+ struct ps_prochandle* ph;
+ if ( (ph = Pgrab(jpid)) == NULL) {
+ THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the process");
+ }
+ (*env)->SetLongField(env, this_obj, p_ps_prochandle_ID, (jlong)(intptr_t)ph);
+ fillThreadsAndLoadObjects(env, this_obj, ph);
+}
+
+/*
+ * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
+ * Method: attach0
+ * Signature: (Ljava/lang/String;Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2
+ (JNIEnv *env, jobject this_obj, jstring execName, jstring coreName) {
+ const char *execName_cstr;
+ const char *coreName_cstr;
+ jboolean isCopy;
+ struct ps_prochandle* ph;
+
+ execName_cstr = (*env)->GetStringUTFChars(env, execName, &isCopy);
+ CHECK_EXCEPTION;
+ coreName_cstr = (*env)->GetStringUTFChars(env, coreName, &isCopy);
+ CHECK_EXCEPTION;
+
+ if ( (ph = Pgrab_core(execName_cstr, coreName_cstr)) == NULL) {
+ (*env)->ReleaseStringUTFChars(env, execName, execName_cstr);
+ (*env)->ReleaseStringUTFChars(env, coreName, coreName_cstr);
+ THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the core file");
+ }
+ (*env)->SetLongField(env, this_obj, p_ps_prochandle_ID, (jlong)(intptr_t)ph);
+ (*env)->ReleaseStringUTFChars(env, execName, execName_cstr);
+ (*env)->ReleaseStringUTFChars(env, coreName, coreName_cstr);
+ fillThreadsAndLoadObjects(env, this_obj, ph);
+}
+
+/*
+ * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
+ * Method: detach0
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0
+ (JNIEnv *env, jobject this_obj) {
+ struct ps_prochandle* ph = get_proc_handle(env, this_obj);
+ if (ph != NULL) {
+ Prelease(ph);
+ }
+}
+
+/*
+ * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
+ * Method: lookupByName0
+ * Signature: (Ljava/lang/String;Ljava/lang/String;)J
+ */
+JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0
+ (JNIEnv *env, jobject this_obj, jstring objectName, jstring symbolName) {
+ const char *objectName_cstr, *symbolName_cstr;
+ jlong addr;
+ jboolean isCopy;
+ struct ps_prochandle* ph = get_proc_handle(env, this_obj);
+
+ objectName_cstr = NULL;
+ if (objectName != NULL) {
+ objectName_cstr = (*env)->GetStringUTFChars(env, objectName, &isCopy);
+ CHECK_EXCEPTION_(0);
+ }
+ symbolName_cstr = (*env)->GetStringUTFChars(env, symbolName, &isCopy);
+ CHECK_EXCEPTION_(0);
+
+ addr = (jlong) lookup_symbol(ph, objectName_cstr, symbolName_cstr);
+
+ if (objectName_cstr != NULL) {
+ (*env)->ReleaseStringUTFChars(env, objectName, objectName_cstr);
+ }
+ (*env)->ReleaseStringUTFChars(env, symbolName, symbolName_cstr);
+ return addr;
+}
+
+/*
+ * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
+ * Method: lookupByAddress0
+ * Signature: (J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;
+ */
+JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByAddress0
+ (JNIEnv *env, jobject this_obj, jlong addr) {
+ uintptr_t offset;
+ const char* sym = NULL;
+
+ struct ps_prochandle* ph = get_proc_handle(env, this_obj);
+ sym = symbol_for_pc(ph, (uintptr_t) addr, &offset);
+ if (sym == NULL) return 0;
+ return (*env)->CallObjectMethod(env, this_obj, createClosestSymbol_ID,
+ (*env)->NewStringUTF(env, sym), (jlong)offset);
+}
+
+/*
+ * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
+ * Method: readBytesFromProcess0
+ * Signature: (JJ)Lsun/jvm/hotspot/debugger/ReadResult;
+ */
+JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0
+ (JNIEnv *env, jobject this_obj, jlong addr, jlong numBytes) {
+
+ jboolean isCopy;
+ jbyteArray array;
+ jbyte *bufPtr;
+ ps_err_e err;
+
+ array = (*env)->NewByteArray(env, numBytes);
+ CHECK_EXCEPTION_(0);
+ bufPtr = (*env)->GetByteArrayElements(env, array, &isCopy);
+ CHECK_EXCEPTION_(0);
+
+ err = ps_pread(get_proc_handle(env, this_obj), (psaddr_t) (uintptr_t)addr, bufPtr, numBytes);
+ (*env)->ReleaseByteArrayElements(env, array, bufPtr, 0);
+ return (err == PS_OK)? array : 0;
+}
+
+JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0
+ (JNIEnv *env, jobject this_obj, jint lwp_id) {
+
+ struct reg gregs;
+ jboolean isCopy;
+ jlongArray array;
+ jlong *regs;
+
+ struct ps_prochandle* ph = get_proc_handle(env, this_obj);
+ if (get_lwp_regs(ph, lwp_id, &gregs) != true) {
+ THROW_NEW_DEBUGGER_EXCEPTION_("get_thread_regs failed for a lwp", 0);
+ }
+
+#undef NPRGREG
+#ifdef i386
+#define NPRGREG sun_jvm_hotspot_debugger_x86_X86ThreadContext_NPRGREG
+#endif
+#ifdef ia64
+#define NPRGREG IA64_REG_COUNT
+#endif
+#ifdef amd64
+#define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG
+#endif
+#if defined(sparc) || defined(sparcv9)
+#define NPRGREG sun_jvm_hotspot_debugger_sparc_SPARCThreadContext_NPRGREG
+#endif
+
+ array = (*env)->NewLongArray(env, NPRGREG);
+ CHECK_EXCEPTION_(0);
+ regs = (*env)->GetLongArrayElements(env, array, &isCopy);
+
+#undef REG_INDEX
+
+#ifdef i386
+#define REG_INDEX(reg) sun_jvm_hotspot_debugger_x86_X86ThreadContext_##reg
+
+ regs[REG_INDEX(GS)] = (uintptr_t) gregs.r_gs;
+ regs[REG_INDEX(FS)] = (uintptr_t) gregs.r_fs;
+ regs[REG_INDEX(ES)] = (uintptr_t) gregs.r_es;
+ regs[REG_INDEX(DS)] = (uintptr_t) gregs.r_ds;
+ regs[REG_INDEX(EDI)] = (uintptr_t) gregs.r_edi;
+ regs[REG_INDEX(ESI)] = (uintptr_t) gregs.r_esi;
+ regs[REG_INDEX(FP)] = (uintptr_t) gregs.r_ebp;
+ regs[REG_INDEX(SP)] = (uintptr_t) gregs.r_isp;
+ regs[REG_INDEX(EBX)] = (uintptr_t) gregs.r_ebx;
+ regs[REG_INDEX(EDX)] = (uintptr_t) gregs.r_edx;
+ regs[REG_INDEX(ECX)] = (uintptr_t) gregs.r_ecx;
+ regs[REG_INDEX(EAX)] = (uintptr_t) gregs.r_eax;
+ regs[REG_INDEX(PC)] = (uintptr_t) gregs.r_eip;
+ regs[REG_INDEX(CS)] = (uintptr_t) gregs.r_cs;
+ regs[REG_INDEX(SS)] = (uintptr_t) gregs.r_ss;
+
+#endif /* i386 */
+
+#if ia64
+ regs = (*env)->GetLongArrayElements(env, array, &isCopy);
+ int i;
+ for (i = 0; i < NPRGREG; i++ ) {
+ regs[i] = 0xDEADDEAD;
+ }
+#endif /* ia64 */
+
+#ifdef amd64
+#define REG_INDEX(reg) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##reg
+
+ regs[REG_INDEX(R15)] = gregs.r_r15;
+ regs[REG_INDEX(R14)] = gregs.r_r14;
+ regs[REG_INDEX(R13)] = gregs.r_r13;
+ regs[REG_INDEX(R12)] = gregs.r_r12;
+ regs[REG_INDEX(RBP)] = gregs.r_rbp;
+ regs[REG_INDEX(RBX)] = gregs.r_rbx;
+ regs[REG_INDEX(R11)] = gregs.r_r11;
+ regs[REG_INDEX(R10)] = gregs.r_r10;
+ regs[REG_INDEX(R9)] = gregs.r_r9;
+ regs[REG_INDEX(R8)] = gregs.r_r8;
+ regs[REG_INDEX(RAX)] = gregs.r_rax;
+ regs[REG_INDEX(RCX)] = gregs.r_rcx;
+ regs[REG_INDEX(RDX)] = gregs.r_rdx;
+ regs[REG_INDEX(RSI)] = gregs.r_rsi;
+ regs[REG_INDEX(RDI)] = gregs.r_rdi;
+ regs[REG_INDEX(RIP)] = gregs.r_rip;
+ regs[REG_INDEX(CS)] = gregs.r_cs;
+ regs[REG_INDEX(RSP)] = gregs.r_rsp;
+ regs[REG_INDEX(SS)] = gregs.r_ss;
+// regs[REG_INDEX(FSBASE)] = gregs.fs_base;
+// regs[REG_INDEX(GSBASE)] = gregs.gs_base;
+// regs[REG_INDEX(DS)] = gregs.ds;
+// regs[REG_INDEX(ES)] = gregs.es;
+// regs[REG_INDEX(FS)] = gregs.fs;
+// regs[REG_INDEX(GS)] = gregs.gs;
+
+#endif /* amd64 */
+
+#if defined(sparc) || defined(sparcv9)
+
+#define REG_INDEX(reg) sun_jvm_hotspot_debugger_sparc_SPARCThreadContext_##reg
+
+#ifdef _LP64
+ regs[REG_INDEX(R_PSR)] = gregs.tstate;
+ regs[REG_INDEX(R_PC)] = gregs.tpc;
+ regs[REG_INDEX(R_nPC)] = gregs.tnpc;
+ regs[REG_INDEX(R_Y)] = gregs.y;
+#else
+ regs[REG_INDEX(R_PSR)] = gregs.psr;
+ regs[REG_INDEX(R_PC)] = gregs.pc;
+ regs[REG_INDEX(R_nPC)] = gregs.npc;
+ regs[REG_INDEX(R_Y)] = gregs.y;
+#endif
+ regs[REG_INDEX(R_G0)] = 0 ;
+ regs[REG_INDEX(R_G1)] = gregs.u_regs[0];
+ regs[REG_INDEX(R_G2)] = gregs.u_regs[1];
+ regs[REG_INDEX(R_G3)] = gregs.u_regs[2];
+ regs[REG_INDEX(R_G4)] = gregs.u_regs[3];
+ regs[REG_INDEX(R_G5)] = gregs.u_regs[4];
+ regs[REG_INDEX(R_G6)] = gregs.u_regs[5];
+ regs[REG_INDEX(R_G7)] = gregs.u_regs[6];
+ regs[REG_INDEX(R_O0)] = gregs.u_regs[7];
+ regs[REG_INDEX(R_O1)] = gregs.u_regs[8];
+ regs[REG_INDEX(R_O2)] = gregs.u_regs[ 9];
+ regs[REG_INDEX(R_O3)] = gregs.u_regs[10];
+ regs[REG_INDEX(R_O4)] = gregs.u_regs[11];
+ regs[REG_INDEX(R_O5)] = gregs.u_regs[12];
+ regs[REG_INDEX(R_O6)] = gregs.u_regs[13];
+ regs[REG_INDEX(R_O7)] = gregs.u_regs[14];
+#endif /* sparc */
+
+
+ (*env)->ReleaseLongArrayElements(env, array, regs, JNI_COMMIT);
+ return array;
+}
diff --git a/agent/src/os/bsd/Makefile b/agent/src/os/bsd/Makefile
new file mode 100644
index 000000000..65909bd5f
--- /dev/null
+++ b/agent/src/os/bsd/Makefile
@@ -0,0 +1,78 @@
+#
+# Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+#
+
+ARCH := $(shell if ([ `uname -m` = "ia64" ]) ; then echo ia64 ; elif ([ `uname -m` = "amd64" ]) ; then echo amd64; elif ([ `uname -m` = "sparc64" ]) ; then echo sparc; else echo i386 ; fi )
+GCC = gcc
+
+JAVAH = ${JAVA_HOME}/bin/javah
+
+SOURCES = salibelf.c \
+ symtab.c \
+ libproc_impl.c \
+ ps_proc.c \
+ ps_core.c \
+ hsearch_r.c \
+ BsdDebuggerLocal.c
+
+INCLUDES = -I${JAVA_HOME}/include -I${JAVA_HOME}/include/$(shell uname -s | tr "[:upper:]" "[:lower:]")
+
+OBJS = $(SOURCES:.c=.o)
+
+LIBS = -lutil -lthread_db
+
+CFLAGS = -c -fPIC -g -Wall -D_ALLBSD_SOURCE -D_GNU_SOURCE -D$(ARCH) $(INCLUDES)
+
+LIBSA = $(ARCH)/libsaproc.so
+
+all: $(LIBSA)
+
+BsdDebuggerLocal.o: BsdDebuggerLocal.c
+ $(JAVAH) -jni -classpath ../../../../../build/bsd-i586/hotspot/outputdir/bsd_i486_compiler2/generated/saclasses \
+ sun.jvm.hotspot.debugger.x86.X86ThreadContext \
+ sun.jvm.hotspot.debugger.amd64.AMD64ThreadContext
+ $(GCC) $(CFLAGS) $<
+
+.c.obj:
+ $(GCC) $(CFLAGS)
+
+ifndef LDNOMAP
+ LFLAGS_LIBSA = -Xlinker --version-script=mapfile
+endif
+
+$(LIBSA): $(OBJS) mapfile
+ if [ ! -d $(ARCH) ] ; then mkdir $(ARCH) ; fi
+ $(GCC) -shared $(LFLAGS_LIBSA) -o $(LIBSA) $(OBJS) $(LIBS)
+
+test.o: $(LIBSA) test.c
+ $(GCC) -c -o test.o -g -D_GNU_SOURCE -D$(ARCH) $(INCLUDES) test.c
+
+test: test.o
+ $(GCC) -o test test.o -L$(ARCH) -lsaproc $(LIBS)
+
+clean:
+ rm -f $(LIBSA)
+ rm -f $(OBJS)
+ rm -f test.o
+ -rmdir $(ARCH)
+
diff --git a/agent/src/os/bsd/StubDebuggerLocal.c b/agent/src/os/bsd/StubDebuggerLocal.c
new file mode 100644
index 000000000..bce0babff
--- /dev/null
+++ b/agent/src/os/bsd/StubDebuggerLocal.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include <stdlib.h>
+#include <jni.h>
+
+#define CHECK_EXCEPTION_(value) if ((*env)->ExceptionOccurred(env)) { return value; }
+#define CHECK_EXCEPTION if ((*env)->ExceptionOccurred(env)) { return;}
+#define THROW_NEW_DEBUGGER_EXCEPTION_(str, value) { throw_new_debugger_exception(env, str); return value; }
+#define THROW_NEW_DEBUGGER_EXCEPTION(str) { throw_new_debugger_exception(env, str); return;}
+
+static void throw_new_debugger_exception(JNIEnv* env, const char* errMsg) {
+ (*env)->ThrowNew(env, (*env)->FindClass(env, "sun/jvm/hotspot/debugger/DebuggerException"), errMsg);
+}
+
+/*
+ * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
+ * Method: init0
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0
+ (JNIEnv *env, jclass cls) {
+}
+
+JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getAddressSize
+ (JNIEnv *env, jclass cls)
+{
+#ifdef _LP64
+ return 8;
+#else
+ return 4;
+#endif
+
+}
+
+/*
+ * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
+ * Method: attach0
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__I
+ (JNIEnv *env, jobject this_obj, jint jpid) {
+
+ THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the process");
+}
+
+/*
+ * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
+ * Method: attach0
+ * Signature: (Ljava/lang/String;Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2
+ (JNIEnv *env, jobject this_obj, jstring execName, jstring coreName) {
+ THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the core file");
+}
+
+/*
+ * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
+ * Method: detach0
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0
+ (JNIEnv *env, jobject this_obj) {
+}
+
+/*
+ * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
+ * Method: lookupByName0
+ * Signature: (Ljava/lang/String;Ljava/lang/String;)J
+ */
+JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0
+ (JNIEnv *env, jobject this_obj, jstring objectName, jstring symbolName) {
+ return 0;
+}
+
+/*
+ * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
+ * Method: lookupByAddress0
+ * Signature: (J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;
+ */
+JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByAddress0
+ (JNIEnv *env, jobject this_obj, jlong addr) {
+ return 0;
+}
+
+/*
+ * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
+ * Method: readBytesFromProcess0
+ * Signature: (JJ)Lsun/jvm/hotspot/debugger/ReadResult;
+ */
+JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0
+ (JNIEnv *env, jobject this_obj, jlong addr, jlong numBytes) {
+ return 0;
+}
+
+JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0
+ (JNIEnv *env, jobject this_obj, jint lwp_id) {
+ return 0;
+}
diff --git a/agent/src/os/bsd/elfmacros.h b/agent/src/os/bsd/elfmacros.h
new file mode 100644
index 000000000..0d089c2ca
--- /dev/null
+++ b/agent/src/os/bsd/elfmacros.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2003, 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.
+ *
+ * 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 _ELFMACROS_H_
+#define _ELFMACROS_H_
+
+#define ELF_NHDR Elf_Note
+
+#if defined(_LP64)
+#define ELF_EHDR Elf64_Ehdr
+#define ELF_SHDR Elf64_Shdr
+#define ELF_PHDR Elf64_Phdr
+#define ELF_SYM Elf64_Sym
+#define ELF_DYN Elf64_Dyn
+#define ELF_ADDR Elf64_Addr
+
+#ifndef ELF_ST_TYPE
+#define ELF_ST_TYPE ELF64_ST_TYPE
+#endif
+
+#else
+
+#define ELF_EHDR Elf32_Ehdr
+#define ELF_SHDR Elf32_Shdr
+#define ELF_PHDR Elf32_Phdr
+#define ELF_SYM Elf32_Sym
+#define ELF_DYN Elf32_Dyn
+#define ELF_ADDR Elf32_Addr
+
+#ifndef ELF_ST_TYPE
+#define ELF_ST_TYPE ELF32_ST_TYPE
+#endif
+
+#endif
+
+
+#endif /* _ELFMACROS_H_ */
diff --git a/agent/src/os/bsd/libproc.h b/agent/src/os/bsd/libproc.h
new file mode 100644
index 000000000..74bb84c17
--- /dev/null
+++ b/agent/src/os/bsd/libproc.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef _LIBPROC_H_
+#define _LIBPROC_H_
+
+#include <unistd.h>
+#include <stdint.h>
+#include <machine/reg.h>
+#include <proc_service.h>
+
+#if defined(sparc) || defined(sparcv9)
+/*
+ If _LP64 is defined ptrace.h should be taken from /usr/include/asm-sparc64
+ otherwise it should be from /usr/include/asm-sparc
+ These two files define pt_regs structure differently
+*/
+#ifdef _LP64
+#include "asm-sparc64/ptrace.h"
+#else
+#include "asm-sparc/ptrace.h"
+#endif
+
+#endif //sparc or sparcv9
+
+/************************************************************************************
+
+0. This is very minimal subset of Solaris libproc just enough for current application.
+Please note that the bulk of the functionality is from proc_service interface. This
+adds Pgrab__ and some missing stuff. We hide the difference b/w live process and core
+file by this interface.
+
+1. pthread_id is unique. We store this in OSThread::_pthread_id in JVM code.
+
+2. All threads see the same pid when they call getpid().
+We used to save the result of ::getpid() call in OSThread::_thread_id.
+Because gettid returns actual pid of thread (lwp id), this is
+unique again. We therefore use OSThread::_thread_id as unique identifier.
+
+3. There is a unique LWP id under both thread libraries. libthread_db maps pthread_id
+to its underlying lwp_id under both the thread libraries. thread_info.lwp_id stores
+lwp_id of the thread. The lwp id is nothing but the actual pid of clone'd processes. But
+unfortunately libthread_db does not work very well for core dumps. So, we get pthread_id
+only for processes. For core dumps, we don't use libthread_db at all (like gdb).
+
+4. ptrace operates on this LWP id under both the thread libraries. When we say 'pid' for
+ptrace call, we refer to lwp_id of the thread.
+
+5. for core file, we parse ELF files and read data from them. For processes we use
+combination of ptrace and /proc calls.
+
+*************************************************************************************/
+
+// This C bool type must be int for compatibility with BSD calls and
+// it would be a mistake to equivalence it to C++ bool on many platforms
+
+typedef int bool;
+#define true 1
+#define false 0
+
+struct ps_prochandle;
+
+// attach to a process
+struct ps_prochandle* Pgrab(pid_t pid);
+
+// attach to a core dump
+struct ps_prochandle* Pgrab_core(const char* execfile, const char* corefile);
+
+// release a process or core
+void Prelease(struct ps_prochandle* ph);
+
+// functions not directly available in Solaris libproc
+
+// initialize libproc (call this only once per app)
+// pass true to make library verbose
+bool init_libproc(bool verbose);
+
+// get number of threads
+int get_num_threads(struct ps_prochandle* ph);
+
+// get lwp_id of n'th thread
+lwpid_t get_lwp_id(struct ps_prochandle* ph, int index);
+
+// get regs for a given lwp
+bool get_lwp_regs(struct ps_prochandle* ph, lwpid_t lid, struct reg* regs);
+
+// get number of shared objects
+int get_num_libs(struct ps_prochandle* ph);
+
+// get name of n'th lib
+const char* get_lib_name(struct ps_prochandle* ph, int index);
+
+// get base of lib
+uintptr_t get_lib_base(struct ps_prochandle* ph, int index);
+
+// returns true if given library is found in lib list
+bool find_lib(struct ps_prochandle* ph, const char *lib_name);
+
+// symbol lookup
+uintptr_t lookup_symbol(struct ps_prochandle* ph, const char* object_name,
+ const char* sym_name);
+
+// address->nearest symbol lookup. return NULL for no symbol
+const char* symbol_for_pc(struct ps_prochandle* ph, uintptr_t addr, uintptr_t* poffset);
+
+#endif //__LIBPROC_H_
diff --git a/agent/src/os/bsd/libproc_impl.c b/agent/src/os/bsd/libproc_impl.c
new file mode 100644
index 000000000..4f2d2822e
--- /dev/null
+++ b/agent/src/os/bsd/libproc_impl.c
@@ -0,0 +1,452 @@
+/*
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <thread_db.h>
+#include "libproc_impl.h"
+
+static const char* alt_root = NULL;
+static int alt_root_len = -1;
+
+#define SA_ALTROOT "SA_ALTROOT"
+
+static void init_alt_root() {
+ if (alt_root_len == -1) {
+ alt_root = getenv(SA_ALTROOT);
+ if (alt_root) {
+ alt_root_len = strlen(alt_root);
+ } else {
+ alt_root_len = 0;
+ }
+ }
+}
+
+int pathmap_open(const char* name) {
+ int fd;
+ char alt_path[PATH_MAX + 1];
+
+ init_alt_root();
+ fd = open(name, O_RDONLY);
+ if (fd >= 0) {
+ return fd;
+ }
+
+ if (alt_root_len > 0) {
+ strcpy(alt_path, alt_root);
+ strcat(alt_path, name);
+ fd = open(alt_path, O_RDONLY);
+ if (fd >= 0) {
+ print_debug("path %s substituted for %s\n", alt_path, name);
+ return fd;
+ }
+
+ if (strrchr(name, '/')) {
+ strcpy(alt_path, alt_root);
+ strcat(alt_path, strrchr(name, '/'));
+ fd = open(alt_path, O_RDONLY);
+ if (fd >= 0) {
+ print_debug("path %s substituted for %s\n", alt_path, name);
+ return fd;
+ }
+ }
+ }
+
+ return -1;
+}
+
+static bool _libsaproc_debug;
+
+void print_debug(const char* format,...) {
+ if (_libsaproc_debug) {
+ va_list alist;
+
+ va_start(alist, format);
+ fputs("libsaproc DEBUG: ", stderr);
+ vfprintf(stderr, format, alist);
+ va_end(alist);
+ }
+}
+
+bool is_debug() {
+ return _libsaproc_debug;
+}
+
+// initialize libproc
+bool init_libproc(bool debug) {
+ // init debug mode
+ _libsaproc_debug = debug;
+
+ // initialize the thread_db library
+ if (td_init() != TD_OK) {
+ print_debug("libthread_db's td_init failed\n");
+ return false;
+ }
+
+ return true;
+}
+
+static void destroy_lib_info(struct ps_prochandle* ph) {
+ lib_info* lib = ph->libs;
+ while (lib) {
+ lib_info *next = lib->next;
+ if (lib->symtab) {
+ destroy_symtab(lib->symtab);
+ }
+ free(lib);
+ lib = next;
+ }
+}
+
+static void destroy_thread_info(struct ps_prochandle* ph) {
+ thread_info* thr = ph->threads;
+ while (thr) {
+ thread_info *next = thr->next;
+ free(thr);
+ thr = next;
+ }
+}
+
+// ps_prochandle cleanup
+
+// ps_prochandle cleanup
+void Prelease(struct ps_prochandle* ph) {
+ // do the "derived class" clean-up first
+ ph->ops->release(ph);
+ destroy_lib_info(ph);
+ destroy_thread_info(ph);
+ free(ph);
+}
+
+lib_info* add_lib_info(struct ps_prochandle* ph, const char* libname, uintptr_t base) {
+ return add_lib_info_fd(ph, libname, -1, base);
+}
+
+lib_info* add_lib_info_fd(struct ps_prochandle* ph, const char* libname, int fd, uintptr_t base) {
+ lib_info* newlib;
+
+ if ( (newlib = (lib_info*) calloc(1, sizeof(struct lib_info))) == NULL) {
+ print_debug("can't allocate memory for lib_info\n");
+ return NULL;
+ }
+
+ strncpy(newlib->name, libname, sizeof(newlib->name));
+ newlib->base = base;
+
+ if (fd == -1) {
+ if ( (newlib->fd = pathmap_open(newlib->name)) < 0) {
+ print_debug("can't open shared object %s\n", newlib->name);
+ free(newlib);
+ return NULL;
+ }
+ } else {
+ newlib->fd = fd;
+ }
+
+ // check whether we have got an ELF file. /proc/<pid>/map
+ // gives out all file mappings and not just shared objects
+ if (is_elf_file(newlib->fd) == false) {
+ close(newlib->fd);
+ free(newlib);
+ return NULL;
+ }
+
+ newlib->symtab = build_symtab(newlib->fd);
+ if (newlib->symtab == NULL) {
+ print_debug("symbol table build failed for %s\n", newlib->name);
+ }
+ else {
+ print_debug("built symbol table for %s\n", newlib->name);
+ }
+
+ // even if symbol table building fails, we add the lib_info.
+ // This is because we may need to read from the ELF file for core file
+ // address read functionality. lookup_symbol checks for NULL symtab.
+ if (ph->libs) {
+ ph->lib_tail->next = newlib;
+ ph->lib_tail = newlib;
+ } else {
+ ph->libs = ph->lib_tail = newlib;
+ }
+ ph->num_libs++;
+
+ return newlib;
+}
+
+// lookup for a specific symbol
+uintptr_t lookup_symbol(struct ps_prochandle* ph, const char* object_name,
+ const char* sym_name) {
+ // ignore object_name. search in all libraries
+ // FIXME: what should we do with object_name?? The library names are obtained
+ // by parsing /proc/<pid>/maps, which may not be the same as object_name.
+ // What we need is a utility to map object_name to real file name, something
+ // dlopen() does by looking at LD_LIBRARY_PATH and /etc/ld.so.cache. For
+ // now, we just ignore object_name and do a global search for the symbol.
+
+ lib_info* lib = ph->libs;
+ while (lib) {
+ if (lib->symtab) {
+ uintptr_t res = search_symbol(lib->symtab, lib->base, sym_name, NULL);
+ if (res) return res;
+ }
+ lib = lib->next;
+ }
+
+ print_debug("lookup failed for symbol '%s' in obj '%s'\n",
+ sym_name, object_name);
+ return (uintptr_t) NULL;
+}
+
+
+const char* symbol_for_pc(struct ps_prochandle* ph, uintptr_t addr, uintptr_t* poffset) {
+ const char* res = NULL;
+ lib_info* lib = ph->libs;
+ while (lib) {
+ if (lib->symtab && addr >= lib->base) {
+ res = nearest_symbol(lib->symtab, addr - lib->base, poffset);
+ if (res) return res;
+ }
+ lib = lib->next;
+ }
+ return NULL;
+}
+
+// add a thread to ps_prochandle
+thread_info* add_thread_info(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id) {
+ thread_info* newthr;
+ if ( (newthr = (thread_info*) calloc(1, sizeof(thread_info))) == NULL) {
+ print_debug("can't allocate memory for thread_info\n");
+ return NULL;
+ }
+
+ // initialize thread info
+ newthr->pthread_id = pthread_id;
+ newthr->lwp_id = lwp_id;
+
+ // add new thread to the list
+ newthr->next = ph->threads;
+ ph->threads = newthr;
+ ph->num_threads++;
+ return newthr;
+}
+
+
+// struct used for client data from thread_db callback
+struct thread_db_client_data {
+ struct ps_prochandle* ph;
+ thread_info_callback callback;
+};
+
+// callback function for libthread_db
+static int thread_db_callback(const td_thrhandle_t *th_p, void *data) {
+ struct thread_db_client_data* ptr = (struct thread_db_client_data*) data;
+ td_thrinfo_t ti;
+ td_err_e err;
+
+ memset(&ti, 0, sizeof(ti));
+ err = td_thr_get_info(th_p, &ti);
+ if (err != TD_OK) {
+ print_debug("libthread_db : td_thr_get_info failed, can't get thread info\n");
+ return err;
+ }
+
+ print_debug("thread_db : pthread %d (lwp %d)\n", ti.ti_tid, ti.ti_lid);
+
+ if (ptr->callback(ptr->ph, (pthread_t)ti.ti_tid, ti.ti_lid) != true)
+ return TD_ERR;
+
+ return TD_OK;
+}
+
+// read thread_info using libthread_db
+bool read_thread_info(struct ps_prochandle* ph, thread_info_callback cb) {
+ struct thread_db_client_data mydata;
+ td_thragent_t* thread_agent = NULL;
+ if (td_ta_new(ph, &thread_agent) != TD_OK) {
+ print_debug("can't create libthread_db agent\n");
+ return false;
+ }
+
+ mydata.ph = ph;
+ mydata.callback = cb;
+
+ // we use libthread_db iterator to iterate thru list of threads.
+ if (td_ta_thr_iter(thread_agent, thread_db_callback, &mydata,
+ TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
+ TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS) != TD_OK) {
+ td_ta_delete(thread_agent);
+ return false;
+ }
+
+ // delete thread agent
+ td_ta_delete(thread_agent);
+ return true;
+}
+
+
+// get number of threads
+int get_num_threads(struct ps_prochandle* ph) {
+ return ph->num_threads;
+}
+
+// get lwp_id of n'th thread
+lwpid_t get_lwp_id(struct ps_prochandle* ph, int index) {
+ int count = 0;
+ thread_info* thr = ph->threads;
+ while (thr) {
+ if (count == index) {
+ return thr->lwp_id;
+ }
+ count++;
+ thr = thr->next;
+ }
+ return -1;
+}
+
+// get regs for a given lwp
+bool get_lwp_regs(struct ps_prochandle* ph, lwpid_t lwp_id, struct reg* regs) {
+ return ph->ops->get_lwp_regs(ph, lwp_id, regs);
+}
+
+// get number of shared objects
+int get_num_libs(struct ps_prochandle* ph) {
+ return ph->num_libs;
+}
+
+// get name of n'th solib
+const char* get_lib_name(struct ps_prochandle* ph, int index) {
+ int count = 0;
+ lib_info* lib = ph->libs;
+ while (lib) {
+ if (count == index) {
+ return lib->name;
+ }
+ count++;
+ lib = lib->next;
+ }
+ return NULL;
+}
+
+// get base address of a lib
+uintptr_t get_lib_base(struct ps_prochandle* ph, int index) {
+ int count = 0;
+ lib_info* lib = ph->libs;
+ while (lib) {
+ if (count == index) {
+ return lib->base;
+ }
+ count++;
+ lib = lib->next;
+ }
+ return (uintptr_t)NULL;
+}
+
+bool find_lib(struct ps_prochandle* ph, const char *lib_name) {
+ lib_info *p = ph->libs;
+ while (p) {
+ if (strcmp(p->name, lib_name) == 0) {
+ return true;
+ }
+ p = p->next;
+ }
+ return false;
+}
+
+//--------------------------------------------------------------------------
+// proc service functions
+
+// ps_pglobal_lookup() looks up the symbol sym_name in the symbol table
+// of the load object object_name in the target process identified by ph.
+// It returns the symbol's value as an address in the target process in
+// *sym_addr.
+
+ps_err_e ps_pglobal_lookup(struct ps_prochandle *ph, const char *object_name,
+ const char *sym_name, psaddr_t *sym_addr) {
+ *sym_addr = (psaddr_t) lookup_symbol(ph, object_name, sym_name);
+ return (*sym_addr ? PS_OK : PS_NOSYM);
+}
+
+// read "size" bytes info "buf" from address "addr"
+ps_err_e ps_pread(struct ps_prochandle *ph, psaddr_t addr,
+ void *buf, size_t size) {
+ return ph->ops->p_pread(ph, (uintptr_t) addr, buf, size)? PS_OK: PS_ERR;
+}
+
+// write "size" bytes of data to debuggee at address "addr"
+ps_err_e ps_pwrite(struct ps_prochandle *ph, psaddr_t addr,
+ const void *buf, size_t size) {
+ return ph->ops->p_pwrite(ph, (uintptr_t)addr, buf, size)? PS_OK: PS_ERR;
+}
+
+// fill in ptrace_lwpinfo for lid
+ps_err_e ps_linfo(struct ps_prochandle *ph, lwpid_t lwp_id, void *linfo) {
+ return ph->ops->get_lwp_info(ph, lwp_id, linfo)? PS_OK: PS_ERR;
+}
+
+// needed for when libthread_db is compiled with TD_DEBUG defined
+void
+ps_plog (const char *format, ...)
+{
+ va_list alist;
+
+ va_start(alist, format);
+ vfprintf(stderr, format, alist);
+ va_end(alist);
+}
+
+// ------------------------------------------------------------------------
+// Functions below this point are not yet implemented. They are here only
+// to make the linker happy.
+
+ps_err_e ps_lsetfpregs(struct ps_prochandle *ph, lwpid_t lid, const prfpregset_t *fpregs) {
+ print_debug("ps_lsetfpregs not implemented\n");
+ return PS_OK;
+}
+
+ps_err_e ps_lsetregs(struct ps_prochandle *ph, lwpid_t lid, const prgregset_t gregset) {
+ print_debug("ps_lsetregs not implemented\n");
+ return PS_OK;
+}
+
+ps_err_e ps_lgetfpregs(struct ps_prochandle *ph, lwpid_t lid, prfpregset_t *fpregs) {
+ print_debug("ps_lgetfpregs not implemented\n");
+ return PS_OK;
+}
+
+ps_err_e ps_lgetregs(struct ps_prochandle *ph, lwpid_t lid, prgregset_t gregset) {
+ print_debug("ps_lgetfpregs not implemented\n");
+ return PS_OK;
+}
+
+ps_err_e ps_lstop(struct ps_prochandle *ph, lwpid_t lid) {
+ print_debug("ps_lstop not implemented\n");
+ return PS_OK;
+}
+
+ps_err_e ps_pcontinue(struct ps_prochandle *ph) {
+ print_debug("ps_pcontinue not implemented\n");
+ return PS_OK;
+}
diff --git a/agent/src/os/bsd/libproc_impl.h b/agent/src/os/bsd/libproc_impl.h
new file mode 100644
index 000000000..8b9d23316
--- /dev/null
+++ b/agent/src/os/bsd/libproc_impl.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2003, 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.
+ *
+ * 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 _LIBPROC_IMPL_H_
+#define _LIBPROC_IMPL_H_
+
+#include <unistd.h>
+#include <limits.h>
+#include "libproc.h"
+#include "symtab.h"
+
+// data structures in this file mimic those of Solaris 8.0 - libproc's Pcontrol.h
+
+#define BUF_SIZE (PATH_MAX + NAME_MAX + 1)
+
+// list of shared objects
+typedef struct lib_info {
+ char name[BUF_SIZE];
+ uintptr_t base;
+ struct symtab* symtab;
+ int fd; // file descriptor for lib
+ struct lib_info* next;
+} lib_info;
+
+// list of threads
+typedef struct thread_info {
+ lwpid_t lwp_id;
+ pthread_t pthread_id; // not used cores, always -1
+ struct reg regs; // not for process, core uses for caching regset
+ struct thread_info* next;
+} thread_info;
+
+// list of virtual memory maps
+typedef struct map_info {
+ int fd; // file descriptor
+ off_t offset; // file offset of this mapping
+ uintptr_t vaddr; // starting virtual address
+ size_t memsz; // size of the mapping
+ struct map_info* next;
+} map_info;
+
+// vtable for ps_prochandle
+typedef struct ps_prochandle_ops {
+ // "derived class" clean-up
+ void (*release)(struct ps_prochandle* ph);
+ // read from debuggee
+ bool (*p_pread)(struct ps_prochandle *ph,
+ uintptr_t addr, char *buf, size_t size);
+ // write into debuggee
+ bool (*p_pwrite)(struct ps_prochandle *ph,
+ uintptr_t addr, const char *buf , size_t size);
+ // get integer regset of a thread
+ bool (*get_lwp_regs)(struct ps_prochandle* ph, lwpid_t lwp_id, struct reg* regs);
+ // get info on thread
+ bool (*get_lwp_info)(struct ps_prochandle *ph, lwpid_t lwp_id, void *linfo);
+} ps_prochandle_ops;
+
+// the ps_prochandle
+
+struct core_data {
+ int core_fd; // file descriptor of core file
+ int exec_fd; // file descriptor of exec file
+ int interp_fd; // file descriptor of interpreter (ld-elf.so.1)
+ // part of the class sharing workaround
+ int classes_jsa_fd; // file descriptor of class share archive
+ uintptr_t dynamic_addr; // address of dynamic section of a.out
+ uintptr_t ld_base_addr; // base address of ld.so
+ size_t num_maps; // number of maps.
+ map_info* maps; // maps in a linked list
+ // part of the class sharing workaround
+ map_info* class_share_maps;// class share maps in a linked list
+ map_info** map_array; // sorted (by vaddr) array of map_info pointers
+};
+
+struct ps_prochandle {
+ ps_prochandle_ops* ops; // vtable ptr
+ pid_t pid;
+ int num_libs;
+ lib_info* libs; // head of lib list
+ lib_info* lib_tail; // tail of lib list - to append at the end
+ int num_threads;
+ thread_info* threads; // head of thread list
+ struct core_data* core; // data only used for core dumps, NULL for process
+};
+
+int pathmap_open(const char* name);
+
+void print_debug(const char* format,...);
+bool is_debug();
+
+typedef bool (*thread_info_callback)(struct ps_prochandle* ph, pthread_t pid, lwpid_t lwpid);
+
+// reads thread info using libthread_db and calls above callback for each thread
+bool read_thread_info(struct ps_prochandle* ph, thread_info_callback cb);
+
+// adds a new shared object to lib list, returns NULL on failure
+lib_info* add_lib_info(struct ps_prochandle* ph, const char* libname, uintptr_t base);
+
+// adds a new shared object to lib list, supply open lib file descriptor as well
+lib_info* add_lib_info_fd(struct ps_prochandle* ph, const char* libname, int fd,
+ uintptr_t base);
+
+// adds a new thread to threads list, returns NULL on failure
+thread_info* add_thread_info(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id);
+
+// a test for ELF signature without using libelf
+bool is_elf_file(int fd);
+
+#endif //_LIBPROC_IMPL_H_
diff --git a/agent/src/os/bsd/mapfile b/agent/src/os/bsd/mapfile
new file mode 100644
index 000000000..36b4334f0
--- /dev/null
+++ b/agent/src/os/bsd/mapfile
@@ -0,0 +1,66 @@
+#
+
+#
+# Copyright (c) 2003, 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.
+#
+# 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.
+#
+#
+
+# Define public interface.
+
+SUNWprivate_1.1 {
+ global:
+
+ # native methods of BsdDebuggerLocal class
+ Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0;
+ Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getAddressSize;
+ Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__I;
+ Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2;
+ Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0;
+ Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0;
+ Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByAddress0;
+ Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0;
+ Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0;
+
+ # proc_service.h functions - to be used by libthread_db
+ ps_getpid;
+ ps_pglobal_lookup;
+ ps_pread;
+ ps_pwrite;
+ ps_lsetfpregs;
+ ps_lsetregs;
+ ps_lgetfpregs;
+ ps_lgetregs;
+ ps_lcontinue;
+ ps_lgetxmmregs;
+ ps_lsetxmmregs;
+ ps_lstop;
+ ps_linfo;
+
+ # used by attach test program
+ init_libproc;
+ Pgrab;
+ Pgrab_core;
+ Prelease;
+
+ local:
+ *;
+};
diff --git a/agent/src/os/bsd/ps_core.c b/agent/src/os/bsd/ps_core.c
new file mode 100644
index 000000000..4e2049b22
--- /dev/null
+++ b/agent/src/os/bsd/ps_core.c
@@ -0,0 +1,1023 @@
+/*
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include <jni.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <elf.h>
+#include <link.h>
+#include "libproc_impl.h"
+#include "salibelf.h"
+
+// This file has the libproc implementation to read core files.
+// For live processes, refer to ps_proc.c. Portions of this is adapted
+// /modelled after Solaris libproc.so (in particular Pcore.c)
+
+//----------------------------------------------------------------------
+// ps_prochandle cleanup helper functions
+
+// close all file descriptors
+static void close_elf_files(struct ps_prochandle* ph) {
+ lib_info* lib = NULL;
+
+ // close core file descriptor
+ if (ph->core->core_fd >= 0)
+ close(ph->core->core_fd);
+
+ // close exec file descriptor
+ if (ph->core->exec_fd >= 0)
+ close(ph->core->exec_fd);
+
+ // close interp file descriptor
+ if (ph->core->interp_fd >= 0)
+ close(ph->core->interp_fd);
+
+ // close class share archive file
+ if (ph->core->classes_jsa_fd >= 0)
+ close(ph->core->classes_jsa_fd);
+
+ // close all library file descriptors
+ lib = ph->libs;
+ while (lib) {
+ int fd = lib->fd;
+ if (fd >= 0 && fd != ph->core->exec_fd) close(fd);
+ lib = lib->next;
+ }
+}
+
+// clean all map_info stuff
+static void destroy_map_info(struct ps_prochandle* ph) {
+ map_info* map = ph->core->maps;
+ while (map) {
+ map_info* next = map->next;
+ free(map);
+ map = next;
+ }
+
+ if (ph->core->map_array) {
+ free(ph->core->map_array);
+ }
+
+ // Part of the class sharing workaround
+ map = ph->core->class_share_maps;
+ while (map) {
+ map_info* next = map->next;
+ free(map);
+ map = next;
+ }
+}
+
+// ps_prochandle operations
+static void core_release(struct ps_prochandle* ph) {
+ if (ph->core) {
+ close_elf_files(ph);
+ destroy_map_info(ph);
+ free(ph->core);
+ }
+}
+
+static map_info* allocate_init_map(int fd, off_t offset, uintptr_t vaddr, size_t memsz) {
+ map_info* map;
+ if ( (map = (map_info*) calloc(1, sizeof(map_info))) == NULL) {
+ print_debug("can't allocate memory for map_info\n");
+ return NULL;
+ }
+
+ // initialize map
+ map->fd = fd;
+ map->offset = offset;
+ map->vaddr = vaddr;
+ map->memsz = memsz;
+ return map;
+}
+
+// add map info with given fd, offset, vaddr and memsz
+static map_info* add_map_info(struct ps_prochandle* ph, int fd, off_t offset,
+ uintptr_t vaddr, size_t memsz) {
+ map_info* map;
+ if ((map = allocate_init_map(fd, offset, vaddr, memsz)) == NULL) {
+ return NULL;
+ }
+
+ // add this to map list
+ map->next = ph->core->maps;
+ ph->core->maps = map;
+ ph->core->num_maps++;
+
+ return map;
+}
+
+// Part of the class sharing workaround
+static map_info* add_class_share_map_info(struct ps_prochandle* ph, off_t offset,
+ uintptr_t vaddr, size_t memsz) {
+ map_info* map;
+ if ((map = allocate_init_map(ph->core->classes_jsa_fd,
+ offset, vaddr, memsz)) == NULL) {
+ return NULL;
+ }
+
+ map->next = ph->core->class_share_maps;
+ ph->core->class_share_maps = map;
+ return map;
+}
+
+// Return the map_info for the given virtual address. We keep a sorted
+// array of pointers in ph->map_array, so we can binary search.
+static map_info* core_lookup(struct ps_prochandle *ph, uintptr_t addr)
+{
+ int mid, lo = 0, hi = ph->core->num_maps - 1;
+ map_info *mp;
+
+ while (hi - lo > 1) {
+ mid = (lo + hi) / 2;
+ if (addr >= ph->core->map_array[mid]->vaddr)
+ lo = mid;
+ else
+ hi = mid;
+ }
+
+ if (addr < ph->core->map_array[hi]->vaddr)
+ mp = ph->core->map_array[lo];
+ else
+ mp = ph->core->map_array[hi];
+
+ if (addr >= mp->vaddr && addr < mp->vaddr + mp->memsz)
+ return (mp);
+
+
+ // Part of the class sharing workaround
+ // Unfortunately, we have no way of detecting -Xshare state.
+ // Check out the share maps atlast, if we don't find anywhere.
+ // This is done this way so to avoid reading share pages
+ // ahead of other normal maps. For eg. with -Xshare:off we don't
+ // want to prefer class sharing data to data from core.
+ mp = ph->core->class_share_maps;
+ if (mp) {
+ print_debug("can't locate map_info at 0x%lx, trying class share maps\n",
+ addr);
+ }
+ while (mp) {
+ if (addr >= mp->vaddr && addr < mp->vaddr + mp->memsz) {
+ print_debug("located map_info at 0x%lx from class share maps\n",
+ addr);
+ return (mp);
+ }
+ mp = mp->next;
+ }
+
+ print_debug("can't locate map_info at 0x%lx\n", addr);
+ return (NULL);
+}
+
+//---------------------------------------------------------------
+// Part of the class sharing workaround:
+//
+// With class sharing, pages are mapped from classes[_g].jsa file.
+// The read-only class sharing pages are mapped as MAP_SHARED,
+// PROT_READ pages. These pages are not dumped into core dump.
+// With this workaround, these pages are read from classes[_g].jsa.
+
+// FIXME: !HACK ALERT!
+// The format of sharing achive file header is needed to read shared heap
+// file mappings. For now, I am hard coding portion of FileMapHeader here.
+// Refer to filemap.hpp.
+
+// FileMapHeader describes the shared space data in the file to be
+// mapped. This structure gets written to a file. It is not a class,
+// so that the compilers don't add any compiler-private data to it.
+
+// Refer to CompactingPermGenGen::n_regions in compactingPermGenGen.hpp
+#define NUM_SHARED_MAPS 4
+
+// Refer to FileMapInfo::_current_version in filemap.hpp
+#define CURRENT_ARCHIVE_VERSION 1
+
+struct FileMapHeader {
+ int _magic; // identify file type.
+ int _version; // (from enum, above.)
+ size_t _alignment; // how shared archive should be aligned
+
+ struct space_info {
+ int _file_offset; // sizeof(this) rounded to vm page size
+ char* _base; // copy-on-write base address
+ size_t _capacity; // for validity checking
+ size_t _used; // for setting space top on read
+
+ // 4991491 NOTICE These are C++ bool's in filemap.hpp and must match up with
+ // the C type matching the C++ bool type on any given platform. For
+ // Hotspot on BSD we assume the corresponding C type is char but
+ // licensees on BSD versions may need to adjust the type of these fields.
+ char _read_only; // read only space?
+ char _allow_exec; // executable code in space?
+
+ } _space[NUM_SHARED_MAPS]; // was _space[CompactingPermGenGen::n_regions];
+
+ // Ignore the rest of the FileMapHeader. We don't need those fields here.
+};
+
+static bool read_jboolean(struct ps_prochandle* ph, uintptr_t addr, jboolean* pvalue) {
+ jboolean i;
+ if (ps_pread(ph, (psaddr_t) addr, &i, sizeof(i)) == PS_OK) {
+ *pvalue = i;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+static bool read_pointer(struct ps_prochandle* ph, uintptr_t addr, uintptr_t* pvalue) {
+ uintptr_t uip;
+ if (ps_pread(ph, (psaddr_t) addr, &uip, sizeof(uip)) == PS_OK) {
+ *pvalue = uip;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+// used to read strings from debuggee
+static bool read_string(struct ps_prochandle* ph, uintptr_t addr, char* buf, size_t size) {
+ size_t i = 0;
+ char c = ' ';
+
+ while (c != '\0') {
+ if (ps_pread(ph, (psaddr_t) addr, &c, sizeof(char)) != PS_OK)
+ return false;
+ if (i < size - 1)
+ buf[i] = c;
+ else // smaller buffer
+ return false;
+ i++; addr++;
+ }
+
+ buf[i] = '\0';
+ return true;
+}
+
+#define USE_SHARED_SPACES_SYM "UseSharedSpaces"
+// mangled name of Arguments::SharedArchivePath
+#define SHARED_ARCHIVE_PATH_SYM "_ZN9Arguments17SharedArchivePathE"
+
+static bool init_classsharing_workaround(struct ps_prochandle* ph) {
+ lib_info* lib = ph->libs;
+ while (lib != NULL) {
+ // we are iterating over shared objects from the core dump. look for
+ // libjvm[_g].so.
+ const char *jvm_name = 0;
+ if ((jvm_name = strstr(lib->name, "/libjvm.so")) != 0 ||
+ (jvm_name = strstr(lib->name, "/libjvm_g.so")) != 0) {
+ char classes_jsa[PATH_MAX];
+ struct FileMapHeader header;
+ size_t n = 0;
+ int fd = -1, m = 0;
+ uintptr_t base = 0, useSharedSpacesAddr = 0;
+ uintptr_t sharedArchivePathAddrAddr = 0, sharedArchivePathAddr = 0;
+ jboolean useSharedSpaces = 0;
+
+ memset(classes_jsa, 0, sizeof(classes_jsa));
+ jvm_name = lib->name;
+ useSharedSpacesAddr = lookup_symbol(ph, jvm_name, USE_SHARED_SPACES_SYM);
+ if (useSharedSpacesAddr == 0) {
+ print_debug("can't lookup 'UseSharedSpaces' flag\n");
+ return false;
+ }
+
+ // Hotspot vm types are not exported to build this library. So
+ // using equivalent type jboolean to read the value of
+ // UseSharedSpaces which is same as hotspot type "bool".
+ if (read_jboolean(ph, useSharedSpacesAddr, &useSharedSpaces) != true) {
+ print_debug("can't read the value of 'UseSharedSpaces' flag\n");
+ return false;
+ }
+
+ if ((int)useSharedSpaces == 0) {
+ print_debug("UseSharedSpaces is false, assuming -Xshare:off!\n");
+ return true;
+ }
+
+ sharedArchivePathAddrAddr = lookup_symbol(ph, jvm_name, SHARED_ARCHIVE_PATH_SYM);
+ if (sharedArchivePathAddrAddr == 0) {
+ print_debug("can't lookup shared archive path symbol\n");
+ return false;
+ }
+
+ if (read_pointer(ph, sharedArchivePathAddrAddr, &sharedArchivePathAddr) != true) {
+ print_debug("can't read shared archive path pointer\n");
+ return false;
+ }
+
+ if (read_string(ph, sharedArchivePathAddr, classes_jsa, sizeof(classes_jsa)) != true) {
+ print_debug("can't read shared archive path value\n");
+ return false;
+ }
+
+ print_debug("looking for %s\n", classes_jsa);
+ // open the class sharing archive file
+ fd = pathmap_open(classes_jsa);
+ if (fd < 0) {
+ print_debug("can't open %s!\n", classes_jsa);
+ ph->core->classes_jsa_fd = -1;
+ return false;
+ } else {
+ print_debug("opened %s\n", classes_jsa);
+ }
+
+ // read FileMapHeader from the file
+ memset(&header, 0, sizeof(struct FileMapHeader));
+ if ((n = read(fd, &header, sizeof(struct FileMapHeader)))
+ != sizeof(struct FileMapHeader)) {
+ print_debug("can't read shared archive file map header from %s\n", classes_jsa);
+ close(fd);
+ return false;
+ }
+
+ // check file magic
+ if (header._magic != 0xf00baba2) {
+ print_debug("%s has bad shared archive file magic number 0x%x, expecing 0xf00baba2\n",
+ classes_jsa, header._magic);
+ close(fd);
+ return false;
+ }
+
+ // check version
+ if (header._version != CURRENT_ARCHIVE_VERSION) {
+ print_debug("%s has wrong shared archive file version %d, expecting %d\n",
+ classes_jsa, header._version, CURRENT_ARCHIVE_VERSION);
+ close(fd);
+ return false;
+ }
+
+ ph->core->classes_jsa_fd = fd;
+ // add read-only maps from classes[_g].jsa to the list of maps
+ for (m = 0; m < NUM_SHARED_MAPS; m++) {
+ if (header._space[m]._read_only) {
+ base = (uintptr_t) header._space[m]._base;
+ // no need to worry about the fractional pages at-the-end.
+ // possible fractional pages are handled by core_read_data.
+ add_class_share_map_info(ph, (off_t) header._space[m]._file_offset,
+ base, (size_t) header._space[m]._used);
+ print_debug("added a share archive map at 0x%lx\n", base);
+ }
+ }
+ return true;
+ }
+ lib = lib->next;
+ }
+ return true;
+}
+
+
+//---------------------------------------------------------------------------
+// functions to handle map_info
+
+// Order mappings based on virtual address. We use this function as the
+// callback for sorting the array of map_info pointers.
+static int core_cmp_mapping(const void *lhsp, const void *rhsp)
+{
+ const map_info *lhs = *((const map_info **)lhsp);
+ const map_info *rhs = *((const map_info **)rhsp);
+
+ if (lhs->vaddr == rhs->vaddr)
+ return (0);
+
+ return (lhs->vaddr < rhs->vaddr ? -1 : 1);
+}
+
+// we sort map_info by starting virtual address so that we can do
+// binary search to read from an address.
+static bool sort_map_array(struct ps_prochandle* ph) {
+ size_t num_maps = ph->core->num_maps;
+ map_info* map = ph->core->maps;
+ int i = 0;
+
+ // allocate map_array
+ map_info** array;
+ if ( (array = (map_info**) malloc(sizeof(map_info*) * num_maps)) == NULL) {
+ print_debug("can't allocate memory for map array\n");
+ return false;
+ }
+
+ // add maps to array
+ while (map) {
+ array[i] = map;
+ i++;
+ map = map->next;
+ }
+
+ // sort is called twice. If this is second time, clear map array
+ if (ph->core->map_array) free(ph->core->map_array);
+ ph->core->map_array = array;
+ // sort the map_info array by base virtual address.
+ qsort(ph->core->map_array, ph->core->num_maps, sizeof (map_info*),
+ core_cmp_mapping);
+
+ // print map
+ if (is_debug()) {
+ int j = 0;
+ print_debug("---- sorted virtual address map ----\n");
+ for (j = 0; j < ph->core->num_maps; j++) {
+ print_debug("base = 0x%lx\tsize = %d\n", ph->core->map_array[j]->vaddr,
+ ph->core->map_array[j]->memsz);
+ }
+ }
+
+ return true;
+}
+
+#ifndef MIN
+#define MIN(x, y) (((x) < (y))? (x): (y))
+#endif
+
+static bool core_read_data(struct ps_prochandle* ph, uintptr_t addr, char *buf, size_t size) {
+ ssize_t resid = size;
+ int page_size=sysconf(_SC_PAGE_SIZE);
+ while (resid != 0) {
+ map_info *mp = core_lookup(ph, addr);
+ uintptr_t mapoff;
+ ssize_t len, rem;
+ off_t off;
+ int fd;
+
+ if (mp == NULL)
+ break; /* No mapping for this address */
+
+ fd = mp->fd;
+ mapoff = addr - mp->vaddr;
+ len = MIN(resid, mp->memsz - mapoff);
+ off = mp->offset + mapoff;
+
+ if ((len = pread(fd, buf, len, off)) <= 0)
+ break;
+
+ resid -= len;
+ addr += len;
+ buf = (char *)buf + len;
+
+ // mappings always start at page boundary. But, may end in fractional
+ // page. fill zeros for possible fractional page at the end of a mapping.
+ rem = mp->memsz % page_size;
+ if (rem > 0) {
+ rem = page_size - rem;
+ len = MIN(resid, rem);
+ resid -= len;
+ addr += len;
+ // we are not assuming 'buf' to be zero initialized.
+ memset(buf, 0, len);
+ buf += len;
+ }
+ }
+
+ if (resid) {
+ print_debug("core read failed for %d byte(s) @ 0x%lx (%d more bytes)\n",
+ size, addr, resid);
+ return false;
+ } else {
+ return true;
+ }
+}
+
+// null implementation for write
+static bool core_write_data(struct ps_prochandle* ph,
+ uintptr_t addr, const char *buf , size_t size) {
+ return false;
+}
+
+static bool core_get_lwp_regs(struct ps_prochandle* ph, lwpid_t lwp_id,
+ struct reg* regs) {
+ // for core we have cached the lwp regs from NOTE section
+ thread_info* thr = ph->threads;
+ while (thr) {
+ if (thr->lwp_id == lwp_id) {
+ memcpy(regs, &thr->regs, sizeof(struct reg));
+ return true;
+ }
+ thr = thr->next;
+ }
+ return false;
+}
+
+static bool core_get_lwp_info(struct ps_prochandle *ph, lwpid_t lwp_id, void *linfo) {
+ print_debug("core_get_lwp_info not implemented\n");
+ return false;
+}
+
+static ps_prochandle_ops core_ops = {
+ .release= core_release,
+ .p_pread= core_read_data,
+ .p_pwrite= core_write_data,
+ .get_lwp_regs= core_get_lwp_regs,
+ .get_lwp_info= core_get_lwp_info
+};
+
+// read regs and create thread from NT_PRSTATUS entries from core file
+static bool core_handle_prstatus(struct ps_prochandle* ph, const char* buf, size_t nbytes) {
+ // we have to read prstatus_t from buf
+ // assert(nbytes == sizeof(prstaus_t), "size mismatch on prstatus_t");
+ prstatus_t* prstat = (prstatus_t*) buf;
+ thread_info* newthr;
+ print_debug("got integer regset for lwp %d\n", prstat->pr_pid);
+ // we set pthread_t to -1 for core dump
+ if((newthr = add_thread_info(ph, (pthread_t) -1, prstat->pr_pid)) == NULL)
+ return false;
+
+ // copy regs
+ memcpy(&newthr->regs, &prstat->pr_reg, sizeof(struct reg));
+
+ if (is_debug()) {
+ print_debug("integer regset\n");
+#ifdef i386
+ // print the regset
+ print_debug("\teax = 0x%x\n", newthr->regs.r_eax);
+ print_debug("\tebx = 0x%x\n", newthr->regs.r_ebx);
+ print_debug("\tecx = 0x%x\n", newthr->regs.r_ecx);
+ print_debug("\tedx = 0x%x\n", newthr->regs.r_edx);
+ print_debug("\tesp = 0x%x\n", newthr->regs.r_esp);
+ print_debug("\tebp = 0x%x\n", newthr->regs.r_ebp);
+ print_debug("\tesi = 0x%x\n", newthr->regs.r_esi);
+ print_debug("\tedi = 0x%x\n", newthr->regs.r_edi);
+ print_debug("\teip = 0x%x\n", newthr->regs.r_eip);
+#endif
+
+#if defined(amd64) || defined(x86_64)
+ // print the regset
+ print_debug("\tr15 = 0x%lx\n", newthr->regs.r_r15);
+ print_debug("\tr14 = 0x%lx\n", newthr->regs.r_r14);
+ print_debug("\tr13 = 0x%lx\n", newthr->regs.r_r13);
+ print_debug("\tr12 = 0x%lx\n", newthr->regs.r_r12);
+ print_debug("\trbp = 0x%lx\n", newthr->regs.r_rbp);
+ print_debug("\trbx = 0x%lx\n", newthr->regs.r_rbx);
+ print_debug("\tr11 = 0x%lx\n", newthr->regs.r_r11);
+ print_debug("\tr10 = 0x%lx\n", newthr->regs.r_r10);
+ print_debug("\tr9 = 0x%lx\n", newthr->regs.r_r9);
+ print_debug("\tr8 = 0x%lx\n", newthr->regs.r_r8);
+ print_debug("\trax = 0x%lx\n", newthr->regs.r_rax);
+ print_debug("\trcx = 0x%lx\n", newthr->regs.r_rcx);
+ print_debug("\trdx = 0x%lx\n", newthr->regs.r_rdx);
+ print_debug("\trsi = 0x%lx\n", newthr->regs.r_rsi);
+ print_debug("\trdi = 0x%lx\n", newthr->regs.r_rdi);
+ //print_debug("\torig_rax = 0x%lx\n", newthr->regs.orig_rax);
+ print_debug("\trip = 0x%lx\n", newthr->regs.r_rip);
+ print_debug("\tcs = 0x%lx\n", newthr->regs.r_cs);
+ //print_debug("\teflags = 0x%lx\n", newthr->regs.eflags);
+ print_debug("\trsp = 0x%lx\n", newthr->regs.r_rsp);
+ print_debug("\tss = 0x%lx\n", newthr->regs.r_ss);
+ //print_debug("\tfs_base = 0x%lx\n", newthr->regs.fs_base);
+ //print_debug("\tgs_base = 0x%lx\n", newthr->regs.gs_base);
+ //print_debug("\tds = 0x%lx\n", newthr->regs.ds);
+ //print_debug("\tes = 0x%lx\n", newthr->regs.es);
+ //print_debug("\tfs = 0x%lx\n", newthr->regs.fs);
+ //print_debug("\tgs = 0x%lx\n", newthr->regs.gs);
+#endif
+ }
+
+ return true;
+}
+
+#define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y))
+
+// read NT_PRSTATUS entries from core NOTE segment
+static bool core_handle_note(struct ps_prochandle* ph, ELF_PHDR* note_phdr) {
+ char* buf = NULL;
+ char* p = NULL;
+ size_t size = note_phdr->p_filesz;
+
+ // we are interested in just prstatus entries. we will ignore the rest.
+ // Advance the seek pointer to the start of the PT_NOTE data
+ if (lseek(ph->core->core_fd, note_phdr->p_offset, SEEK_SET) == (off_t)-1) {
+ print_debug("failed to lseek to PT_NOTE data\n");
+ return false;
+ }
+
+ // Now process the PT_NOTE structures. Each one is preceded by
+ // an Elf{32/64}_Nhdr structure describing its type and size.
+ if ( (buf = (char*) malloc(size)) == NULL) {
+ print_debug("can't allocate memory for reading core notes\n");
+ goto err;
+ }
+
+ // read notes into buffer
+ if (read(ph->core->core_fd, buf, size) != size) {
+ print_debug("failed to read notes, core file must have been truncated\n");
+ goto err;
+ }
+
+ p = buf;
+ while (p < buf + size) {
+ ELF_NHDR* notep = (ELF_NHDR*) p;
+ char* descdata = p + sizeof(ELF_NHDR) + ROUNDUP(notep->n_namesz, 4);
+ print_debug("Note header with n_type = %d and n_descsz = %u\n",
+ notep->n_type, notep->n_descsz);
+
+ if (notep->n_type == NT_PRSTATUS) {
+ if (core_handle_prstatus(ph, descdata, notep->n_descsz) != true)
+ return false;
+ }
+ p = descdata + ROUNDUP(notep->n_descsz, 4);
+ }
+
+ free(buf);
+ return true;
+
+err:
+ if (buf) free(buf);
+ return false;
+}
+
+// read all segments from core file
+static bool read_core_segments(struct ps_prochandle* ph, ELF_EHDR* core_ehdr) {
+ int i = 0;
+ ELF_PHDR* phbuf = NULL;
+ ELF_PHDR* core_php = NULL;
+
+ if ((phbuf = read_program_header_table(ph->core->core_fd, core_ehdr)) == NULL)
+ return false;
+
+ /*
+ * Now iterate through the program headers in the core file.
+ * We're interested in two types of Phdrs: PT_NOTE (which
+ * contains a set of saved /proc structures), and PT_LOAD (which
+ * represents a memory mapping from the process's address space).
+ *
+ * Difference b/w Solaris PT_NOTE and BSD PT_NOTE:
+ *
+ * In Solaris there are two PT_NOTE segments the first PT_NOTE (if present)
+ * contains /proc structs in the pre-2.6 unstructured /proc format. the last
+ * PT_NOTE has data in new /proc format.
+ *
+ * In Solaris, there is only one pstatus (process status). pstatus contains
+ * integer register set among other stuff. For each LWP, we have one lwpstatus
+ * entry that has integer regset for that LWP.
+ *
+ * Linux threads are actually 'clone'd processes. To support core analysis
+ * of "multithreaded" process, Linux creates more than one pstatus (called
+ * "prstatus") entry in PT_NOTE. Each prstatus entry has integer regset for one
+ * "thread". Please refer to Linux kernel src file 'fs/binfmt_elf.c', in particular
+ * function "elf_core_dump".
+ */
+
+ for (core_php = phbuf, i = 0; i < core_ehdr->e_phnum; i++) {
+ switch (core_php->p_type) {
+ case PT_NOTE:
+ if (core_handle_note(ph, core_php) != true) goto err;
+ break;
+
+ case PT_LOAD: {
+ if (core_php->p_filesz != 0) {
+ if (add_map_info(ph, ph->core->core_fd, core_php->p_offset,
+ core_php->p_vaddr, core_php->p_filesz) == NULL) goto err;
+ }
+ break;
+ }
+ }
+
+ core_php++;
+ }
+
+ free(phbuf);
+ return true;
+err:
+ free(phbuf);
+ return false;
+}
+
+// read segments of a shared object
+static bool read_lib_segments(struct ps_prochandle* ph, int lib_fd, ELF_EHDR* lib_ehdr, uintptr_t lib_base) {
+ int i = 0;
+ ELF_PHDR* phbuf;
+ ELF_PHDR* lib_php = NULL;
+
+ if ((phbuf = read_program_header_table(lib_fd, lib_ehdr)) == NULL)
+ return false;
+
+ // we want to process only PT_LOAD segments that are not writable.
+ // i.e., text segments. The read/write/exec (data) segments would
+ // have been already added from core file segments.
+ for (lib_php = phbuf, i = 0; i < lib_ehdr->e_phnum; i++) {
+ if ((lib_php->p_type == PT_LOAD) && !(lib_php->p_flags & PF_W) && (lib_php->p_filesz != 0)) {
+ if (add_map_info(ph, lib_fd, lib_php->p_offset, lib_php->p_vaddr + lib_base, lib_php->p_filesz) == NULL)
+ goto err;
+ }
+ lib_php++;
+ }
+
+ free(phbuf);
+ return true;
+err:
+ free(phbuf);
+ return false;
+}
+
+// process segments from interpreter (ld-elf.so.1)
+static bool read_interp_segments(struct ps_prochandle* ph) {
+ ELF_EHDR interp_ehdr;
+
+ if (read_elf_header(ph->core->interp_fd, &interp_ehdr) != true) {
+ print_debug("interpreter is not a valid ELF file\n");
+ return false;
+ }
+
+ if (read_lib_segments(ph, ph->core->interp_fd, &interp_ehdr, ph->core->ld_base_addr) != true) {
+ print_debug("can't read segments of interpreter\n");
+ return false;
+ }
+
+ return true;
+}
+
+// process segments of a a.out
+static bool read_exec_segments(struct ps_prochandle* ph, ELF_EHDR* exec_ehdr) {
+ int i = 0;
+ ELF_PHDR* phbuf = NULL;
+ ELF_PHDR* exec_php = NULL;
+
+ if ((phbuf = read_program_header_table(ph->core->exec_fd, exec_ehdr)) == NULL)
+ return false;
+
+ for (exec_php = phbuf, i = 0; i < exec_ehdr->e_phnum; i++) {
+ switch (exec_php->p_type) {
+
+ // add mappings for PT_LOAD segments
+ case PT_LOAD: {
+ // add only non-writable segments of non-zero filesz
+ if (!(exec_php->p_flags & PF_W) && exec_php->p_filesz != 0) {
+ if (add_map_info(ph, ph->core->exec_fd, exec_php->p_offset, exec_php->p_vaddr, exec_php->p_filesz) == NULL) goto err;
+ }
+ break;
+ }
+
+ // read the interpreter and it's segments
+ case PT_INTERP: {
+ char interp_name[BUF_SIZE];
+
+ pread(ph->core->exec_fd, interp_name, MIN(exec_php->p_filesz, BUF_SIZE), exec_php->p_offset);
+ print_debug("ELF interpreter %s\n", interp_name);
+ // read interpreter segments as well
+ if ((ph->core->interp_fd = pathmap_open(interp_name)) < 0) {
+ print_debug("can't open runtime loader\n");
+ goto err;
+ }
+ break;
+ }
+
+ // from PT_DYNAMIC we want to read address of first link_map addr
+ case PT_DYNAMIC: {
+ ph->core->dynamic_addr = exec_php->p_vaddr;
+ print_debug("address of _DYNAMIC is 0x%lx\n", ph->core->dynamic_addr);
+ break;
+ }
+
+ } // switch
+ exec_php++;
+ } // for
+
+ free(phbuf);
+ return true;
+err:
+ free(phbuf);
+ return false;
+}
+
+
+#define FIRST_LINK_MAP_OFFSET offsetof(struct r_debug, r_map)
+#define LD_BASE_OFFSET offsetof(struct r_debug, r_ldbase)
+#define LINK_MAP_ADDR_OFFSET offsetof(struct link_map, l_addr)
+#define LINK_MAP_NAME_OFFSET offsetof(struct link_map, l_name)
+#define LINK_MAP_NEXT_OFFSET offsetof(struct link_map, l_next)
+
+// read shared library info from runtime linker's data structures.
+// This work is done by librtlb_db in Solaris
+static bool read_shared_lib_info(struct ps_prochandle* ph) {
+ uintptr_t addr = ph->core->dynamic_addr;
+ uintptr_t debug_base;
+ uintptr_t first_link_map_addr;
+ uintptr_t ld_base_addr;
+ uintptr_t link_map_addr;
+ uintptr_t lib_base_diff;
+ uintptr_t lib_base;
+ uintptr_t lib_name_addr;
+ char lib_name[BUF_SIZE];
+ ELF_DYN dyn;
+ ELF_EHDR elf_ehdr;
+ int lib_fd;
+
+ // _DYNAMIC has information of the form
+ // [tag] [data] [tag] [data] .....
+ // Both tag and data are pointer sized.
+ // We look for dynamic info with DT_DEBUG. This has shared object info.
+ // refer to struct r_debug in link.h
+
+ dyn.d_tag = DT_NULL;
+ while (dyn.d_tag != DT_DEBUG) {
+ if (ps_pread(ph, (psaddr_t) addr, &dyn, sizeof(ELF_DYN)) != PS_OK) {
+ print_debug("can't read debug info from _DYNAMIC\n");
+ return false;
+ }
+ addr += sizeof(ELF_DYN);
+ }
+
+ // we have got Dyn entry with DT_DEBUG
+ debug_base = dyn.d_un.d_ptr;
+ // at debug_base we have struct r_debug. This has first link map in r_map field
+ if (ps_pread(ph, (psaddr_t) debug_base + FIRST_LINK_MAP_OFFSET,
+ &first_link_map_addr, sizeof(uintptr_t)) != PS_OK) {
+ print_debug("can't read first link map address\n");
+ return false;
+ }
+
+ // read ld_base address from struct r_debug
+ // XXX: There is no r_ldbase member on BSD
+/*
+ if (ps_pread(ph, (psaddr_t) debug_base + LD_BASE_OFFSET, &ld_base_addr,
+ sizeof(uintptr_t)) != PS_OK) {
+ print_debug("can't read ld base address\n");
+ return false;
+ }
+ ph->core->ld_base_addr = ld_base_addr;
+*/
+ ph->core->ld_base_addr = 0;
+
+ print_debug("interpreter base address is 0x%lx\n", ld_base_addr);
+
+ // now read segments from interp (i.e ld-elf.so.1)
+ if (read_interp_segments(ph) != true)
+ return false;
+
+ // after adding interpreter (ld.so) mappings sort again
+ if (sort_map_array(ph) != true)
+ return false;
+
+ print_debug("first link map is at 0x%lx\n", first_link_map_addr);
+
+ link_map_addr = first_link_map_addr;
+ while (link_map_addr != 0) {
+ // read library base address of the .so. Note that even though <sys/link.h> calls
+ // link_map->l_addr as "base address", this is * not * really base virtual
+ // address of the shared object. This is actually the difference b/w the virtual
+ // address mentioned in shared object and the actual virtual base where runtime
+ // linker loaded it. We use "base diff" in read_lib_segments call below.
+
+ if (ps_pread(ph, (psaddr_t) link_map_addr + LINK_MAP_ADDR_OFFSET,
+ &lib_base_diff, sizeof(uintptr_t)) != PS_OK) {
+ print_debug("can't read shared object base address diff\n");
+ return false;
+ }
+
+ // read address of the name
+ if (ps_pread(ph, (psaddr_t) link_map_addr + LINK_MAP_NAME_OFFSET,
+ &lib_name_addr, sizeof(uintptr_t)) != PS_OK) {
+ print_debug("can't read address of shared object name\n");
+ return false;
+ }
+
+ // read name of the shared object
+ if (read_string(ph, (uintptr_t) lib_name_addr, lib_name, sizeof(lib_name)) != true) {
+ print_debug("can't read shared object name\n");
+ return false;
+ }
+
+ if (lib_name[0] != '\0') {
+ // ignore empty lib names
+ lib_fd = pathmap_open(lib_name);
+
+ if (lib_fd < 0) {
+ print_debug("can't open shared object %s\n", lib_name);
+ // continue with other libraries...
+ } else {
+ if (read_elf_header(lib_fd, &elf_ehdr)) {
+ lib_base = lib_base_diff + find_base_address(lib_fd, &elf_ehdr);
+ print_debug("reading library %s @ 0x%lx [ 0x%lx ]\n",
+ lib_name, lib_base, lib_base_diff);
+ // while adding library mappings we need to use "base difference".
+ if (! read_lib_segments(ph, lib_fd, &elf_ehdr, lib_base_diff)) {
+ print_debug("can't read shared object's segments\n");
+ close(lib_fd);
+ return false;
+ }
+ add_lib_info_fd(ph, lib_name, lib_fd, lib_base);
+ // Map info is added for the library (lib_name) so
+ // we need to re-sort it before calling the p_pdread.
+ if (sort_map_array(ph) != true)
+ return false;
+ } else {
+ print_debug("can't read ELF header for shared object %s\n", lib_name);
+ close(lib_fd);
+ // continue with other libraries...
+ }
+ }
+ }
+
+ // read next link_map address
+ if (ps_pread(ph, (psaddr_t) link_map_addr + LINK_MAP_NEXT_OFFSET,
+ &link_map_addr, sizeof(uintptr_t)) != PS_OK) {
+ print_debug("can't read next link in link_map\n");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// the one and only one exposed stuff from this file
+struct ps_prochandle* Pgrab_core(const char* exec_file, const char* core_file) {
+ ELF_EHDR core_ehdr;
+ ELF_EHDR exec_ehdr;
+
+ struct ps_prochandle* ph = (struct ps_prochandle*) calloc(1, sizeof(struct ps_prochandle));
+ if (ph == NULL) {
+ print_debug("can't allocate ps_prochandle\n");
+ return NULL;
+ }
+
+ if ((ph->core = (struct core_data*) calloc(1, sizeof(struct core_data))) == NULL) {
+ free(ph);
+ print_debug("can't allocate ps_prochandle\n");
+ return NULL;
+ }
+
+ // initialize ph
+ ph->ops = &core_ops;
+ ph->core->core_fd = -1;
+ ph->core->exec_fd = -1;
+ ph->core->interp_fd = -1;
+
+ // open the core file
+ if ((ph->core->core_fd = open(core_file, O_RDONLY)) < 0) {
+ print_debug("can't open core file\n");
+ goto err;
+ }
+
+ // read core file ELF header
+ if (read_elf_header(ph->core->core_fd, &core_ehdr) != true || core_ehdr.e_type != ET_CORE) {
+ print_debug("core file is not a valid ELF ET_CORE file\n");
+ goto err;
+ }
+
+ if ((ph->core->exec_fd = open(exec_file, O_RDONLY)) < 0) {
+ print_debug("can't open executable file\n");
+ goto err;
+ }
+
+ if (read_elf_header(ph->core->exec_fd, &exec_ehdr) != true || exec_ehdr.e_type != ET_EXEC) {
+ print_debug("executable file is not a valid ELF ET_EXEC file\n");
+ goto err;
+ }
+
+ // process core file segments
+ if (read_core_segments(ph, &core_ehdr) != true)
+ goto err;
+
+ // process exec file segments
+ if (read_exec_segments(ph, &exec_ehdr) != true)
+ goto err;
+
+ // exec file is also treated like a shared object for symbol search
+ if (add_lib_info_fd(ph, exec_file, ph->core->exec_fd,
+ (uintptr_t)0 + find_base_address(ph->core->exec_fd, &exec_ehdr)) == NULL)
+ goto err;
+
+ // allocate and sort maps into map_array, we need to do this
+ // here because read_shared_lib_info needs to read from debuggee
+ // address space
+ if (sort_map_array(ph) != true)
+ goto err;
+
+ if (read_shared_lib_info(ph) != true)
+ goto err;
+
+ // sort again because we have added more mappings from shared objects
+ if (sort_map_array(ph) != true)
+ goto err;
+
+ if (init_classsharing_workaround(ph) != true)
+ goto err;
+
+ return ph;
+
+err:
+ Prelease(ph);
+ return NULL;
+}
diff --git a/agent/src/os/bsd/ps_proc.c b/agent/src/os/bsd/ps_proc.c
new file mode 100644
index 000000000..f8957c099
--- /dev/null
+++ b/agent/src/os/bsd/ps_proc.c
@@ -0,0 +1,444 @@
+/*
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/ptrace.h>
+#include <sys/param.h>
+#include <sys/user.h>
+#include <elf.h>
+#include <sys/elf_common.h>
+#include <sys/link_elf.h>
+#include <libutil.h>
+#include "libproc_impl.h"
+#include "elfmacros.h"
+
+// This file has the libproc implementation specific to live process
+// For core files, refer to ps_core.c
+
+static inline uintptr_t align(uintptr_t ptr, size_t size) {
+ return (ptr & ~(size - 1));
+}
+
+// ---------------------------------------------
+// ptrace functions
+// ---------------------------------------------
+
+// read "size" bytes of data from "addr" within the target process.
+// unlike the standard ptrace() function, process_read_data() can handle
+// unaligned address - alignment check, if required, should be done
+// before calling process_read_data.
+
+static bool process_read_data(struct ps_prochandle* ph, uintptr_t addr, char *buf, size_t size) {
+ int rslt;
+ size_t i, words;
+ uintptr_t end_addr = addr + size;
+ uintptr_t aligned_addr = align(addr, sizeof(int));
+
+ if (aligned_addr != addr) {
+ char *ptr = (char *)&rslt;
+ errno = 0;
+ rslt = ptrace(PT_READ_D, ph->pid, (caddr_t) aligned_addr, 0);
+ if (errno) {
+ print_debug("ptrace(PT_READ_D, ..) failed for %d bytes @ %lx\n", size, addr);
+ return false;
+ }
+ for (; aligned_addr != addr; aligned_addr++, ptr++);
+ for (; ((intptr_t)aligned_addr % sizeof(int)) && aligned_addr < end_addr;
+ aligned_addr++)
+ *(buf++) = *(ptr++);
+ }
+
+ words = (end_addr - aligned_addr) / sizeof(int);
+
+ // assert((intptr_t)aligned_addr % sizeof(int) == 0);
+ for (i = 0; i < words; i++) {
+ errno = 0;
+ rslt = ptrace(PT_READ_D, ph->pid, (caddr_t) aligned_addr, 0);
+ if (errno) {
+ print_debug("ptrace(PT_READ_D, ..) failed for %d bytes @ %lx\n", size, addr);
+ return false;
+ }
+ *(int *)buf = rslt;
+ buf += sizeof(int);
+ aligned_addr += sizeof(int);
+ }
+
+ if (aligned_addr != end_addr) {
+ char *ptr = (char *)&rslt;
+ errno = 0;
+ rslt = ptrace(PT_READ_D, ph->pid, (caddr_t) aligned_addr, 0);
+ if (errno) {
+ print_debug("ptrace(PT_READ_D, ..) failed for %d bytes @ %lx\n", size, addr);
+ return false;
+ }
+ for (; aligned_addr != end_addr; aligned_addr++)
+ *(buf++) = *(ptr++);
+ }
+ return true;
+}
+
+// null implementation for write
+static bool process_write_data(struct ps_prochandle* ph,
+ uintptr_t addr, const char *buf , size_t size) {
+ return false;
+}
+
+// "user" should be a pointer to a reg
+static bool process_get_lwp_regs(struct ps_prochandle* ph, pid_t pid, struct reg *user) {
+ // we have already attached to all thread 'pid's, just use ptrace call
+ // to get regset now. Note that we don't cache regset upfront for processes.
+ if (ptrace(PT_GETREGS, pid, (caddr_t) user, 0) < 0) {
+ print_debug("ptrace(PTRACE_GETREGS, ...) failed for lwp %d\n", pid);
+ return false;
+ }
+ return true;
+}
+
+// fill in ptrace_lwpinfo for lid
+static bool process_get_lwp_info(struct ps_prochandle *ph, lwpid_t lwp_id, void *linfo) {
+ errno = 0;
+ ptrace(PT_LWPINFO, lwp_id, linfo, sizeof(struct ptrace_lwpinfo));
+
+ return (errno == 0)? true: false;
+}
+
+// attach to a process/thread specified by "pid"
+static bool ptrace_attach(pid_t pid) {
+ if (ptrace(PT_ATTACH, pid, NULL, 0) < 0) {
+ print_debug("ptrace(PTRACE_ATTACH, ..) failed for %d\n", pid);
+ return false;
+ } else {
+ int ret;
+ int status;
+ do {
+ // Wait for debuggee to stop.
+ ret = waitpid(pid, &status, 0);
+ if (ret >= 0) {
+ if (WIFSTOPPED(status)) {
+ // Debuggee stopped.
+ return true;
+ } else {
+ print_debug("waitpid(): Child process exited/terminated (status = 0x%x)\n", status);
+ return false;
+ }
+ } else {
+ switch (errno) {
+ case EINTR:
+ continue;
+ break;
+ case ECHILD:
+ print_debug("waitpid() failed. Child process pid (%d) does not exist \n", pid);
+ break;
+ case EINVAL:
+ print_debug("waitpid() failed. Invalid options argument.\n");
+ break;
+ default:
+ print_debug("waitpid() failed. Unexpected error %d\n",errno);
+ }
+ return false;
+ }
+ } while(true);
+ }
+}
+
+// -------------------------------------------------------
+// functions for obtaining library information
+// -------------------------------------------------------
+
+// callback for read_thread_info
+static bool add_new_thread(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id) {
+ return add_thread_info(ph, pthread_id, lwp_id) != NULL;
+}
+
+#if defined(__FreeBSD__) && __FreeBSD_version < 701000
+/*
+ * TEXT_START_ADDR from binutils/ld/emulparams/<arch_spec>.sh
+ * Not the most robust but good enough.
+ */
+
+#if defined(amd64) || defined(x86_64)
+#define TEXT_START_ADDR 0x400000
+#elif defined(i386)
+#define TEXT_START_ADDR 0x8048000
+#else
+#error TEXT_START_ADDR not defined
+#endif
+
+#define BUF_SIZE (PATH_MAX + NAME_MAX + 1)
+
+uintptr_t linkmap_addr(struct ps_prochandle *ph) {
+ uintptr_t ehdr_addr, phdr_addr, dyn_addr, dmap_addr, lmap_addr;
+ ELF_EHDR ehdr;
+ ELF_PHDR *phdrs, *phdr;
+ ELF_DYN *dyns, *dyn;
+ struct r_debug dmap;
+ unsigned long hdrs_size;
+ unsigned int i;
+
+ /* read ELF_EHDR at TEXT_START_ADDR and validate */
+
+ ehdr_addr = (uintptr_t)TEXT_START_ADDR;
+
+ if (process_read_data(ph, ehdr_addr, (char *)&ehdr, sizeof(ehdr)) != true) {
+ print_debug("process_read_data failed for ehdr_addr %p\n", ehdr_addr);
+ return (0);
+ }
+
+ if (!IS_ELF(ehdr) ||
+ ehdr.e_ident[EI_CLASS] != ELF_TARG_CLASS ||
+ ehdr.e_ident[EI_DATA] != ELF_TARG_DATA ||
+ ehdr.e_ident[EI_VERSION] != EV_CURRENT ||
+ ehdr.e_phentsize != sizeof(ELF_PHDR) ||
+ ehdr.e_version != ELF_TARG_VER ||
+ ehdr.e_machine != ELF_TARG_MACH) {
+ print_debug("not an ELF_EHDR at %p\n", ehdr_addr);
+ return (0);
+ }
+
+ /* allocate space for all ELF_PHDR's and read */
+
+ phdr_addr = ehdr_addr + ehdr.e_phoff;
+ hdrs_size = ehdr.e_phnum * sizeof(ELF_PHDR);
+
+ if ((phdrs = malloc(hdrs_size)) == NULL)
+ return (0);
+
+ if (process_read_data(ph, phdr_addr, (char *)phdrs, hdrs_size) != true) {
+ print_debug("process_read_data failed for phdr_addr %p\n", phdr_addr);
+ return (0);
+ }
+
+ /* find PT_DYNAMIC section */
+
+ for (i = 0, phdr = phdrs; i < ehdr.e_phnum; i++, phdr++) {
+ if (phdr->p_type == PT_DYNAMIC)
+ break;
+ }
+
+ if (i >= ehdr.e_phnum) {
+ print_debug("PT_DYNAMIC section not found!\n");
+ free(phdrs);
+ return (0);
+ }
+
+ /* allocate space and read in ELF_DYN headers */
+
+ dyn_addr = phdr->p_vaddr;
+ hdrs_size = phdr->p_memsz;
+ free(phdrs);
+
+ if ((dyns = malloc(hdrs_size)) == NULL)
+ return (0);
+
+ if (process_read_data(ph, dyn_addr, (char *)dyns, hdrs_size) != true) {
+ print_debug("process_read_data failed for dyn_addr %p\n", dyn_addr);
+ free(dyns);
+ return (0);
+ }
+
+ /* find DT_DEBUG */
+
+ dyn = dyns;
+ while (dyn->d_tag != DT_DEBUG && dyn->d_tag != DT_NULL) {
+ dyn++;
+ }
+
+ if (dyn->d_tag != DT_DEBUG) {
+ print_debug("failed to find DT_DEBUG\n");
+ free(dyns);
+ return (0);
+ }
+
+ /* read struct r_debug into dmap */
+
+ dmap_addr = (uintptr_t)dyn->d_un.d_ptr;
+ free(dyns);
+
+ if (process_read_data(ph, dmap_addr, (char *)&dmap, sizeof(dmap)) != true) {
+ print_debug("process_read_data failed for dmap_addr %p\n", dmap_addr);
+ return (0);
+ }
+
+ lmap_addr = (uintptr_t)dmap.r_map;
+
+ return (lmap_addr);
+}
+#endif // __FreeBSD__ && __FreeBSD_version < 701000
+
+static bool read_lib_info(struct ps_prochandle* ph) {
+#if defined(__FreeBSD__) && __FreeBSD_version >= 701000
+ struct kinfo_vmentry *freep, *kve;
+ int i, cnt;
+
+ freep = kinfo_getvmmap(ph->pid, &cnt);
+ if (freep == NULL) {
+ print_debug("can't get vm map for pid\n", ph->pid);
+ return false;
+ }
+
+ for (i = 0; i < cnt; i++) {
+ kve = &freep[i];
+ if ((kve->kve_flags & KVME_FLAG_COW) &&
+ kve->kve_path != NULL &&
+ strlen(kve->kve_path) > 0) {
+
+ if (find_lib(ph, kve->kve_path) == false) {
+ lib_info* lib;
+ if ((lib = add_lib_info(ph, kve->kve_path,
+ (uintptr_t) kve->kve_start)) == NULL)
+ continue; // ignore, add_lib_info prints error
+
+ // we don't need to keep the library open, symtab is already
+ // built. Only for core dump we need to keep the fd open.
+ close(lib->fd);
+ lib->fd = -1;
+ }
+ }
+ }
+
+ free(freep);
+
+ return true;
+#else
+ char *l_name;
+ struct link_map *lmap;
+ uintptr_t lmap_addr;
+
+ if ((l_name = malloc(BUF_SIZE)) == NULL)
+ return false;
+
+ if ((lmap = malloc(sizeof(*lmap))) == NULL) {
+ free(l_name);
+ return false;
+ }
+
+ lmap_addr = linkmap_addr(ph);
+
+ if (lmap_addr == 0) {
+ free(l_name);
+ free(lmap);
+ return false;
+ }
+
+ do {
+ if (process_read_data(ph, lmap_addr, (char *)lmap, sizeof(*lmap)) != true) {
+ print_debug("process_read_data failed for lmap_addr %p\n", lmap_addr);
+ free (l_name);
+ free (lmap);
+ return false;
+ }
+
+ if (process_read_data(ph, (uintptr_t)lmap->l_name, l_name,
+ BUF_SIZE) != true) {
+ print_debug("process_read_data failed for lmap->l_name %p\n",
+ lmap->l_name);
+ free (l_name);
+ free (lmap);
+ return false;
+ }
+
+ if (find_lib(ph, l_name) == false) {
+ lib_info* lib;
+ if ((lib = add_lib_info(ph, l_name,
+ (uintptr_t) lmap->l_addr)) == NULL)
+ continue; // ignore, add_lib_info prints error
+
+ // we don't need to keep the library open, symtab is already
+ // built. Only for core dump we need to keep the fd open.
+ close(lib->fd);
+ lib->fd = -1;
+ }
+ lmap_addr = (uintptr_t)lmap->l_next;
+ } while (lmap->l_next != NULL);
+
+ free (l_name);
+ free (lmap);
+
+ return true;
+#endif
+}
+
+// detach a given pid
+static bool ptrace_detach(pid_t pid) {
+ if (pid && ptrace(PT_DETACH, pid, (caddr_t)1, 0) < 0) {
+ print_debug("ptrace(PTRACE_DETACH, ..) failed for %d\n", pid);
+ return false;
+ } else {
+ return true;
+ }
+}
+
+static void process_cleanup(struct ps_prochandle* ph) {
+ ptrace_detach(ph->pid);
+}
+
+static ps_prochandle_ops process_ops = {
+ .release= process_cleanup,
+ .p_pread= process_read_data,
+ .p_pwrite= process_write_data,
+ .get_lwp_regs= process_get_lwp_regs,
+ .get_lwp_info= process_get_lwp_info
+};
+
+// attach to the process. One and only one exposed stuff
+struct ps_prochandle* Pgrab(pid_t pid) {
+ struct ps_prochandle* ph = NULL;
+ thread_info* thr = NULL;
+
+ if ( (ph = (struct ps_prochandle*) calloc(1, sizeof(struct ps_prochandle))) == NULL) {
+ print_debug("can't allocate memory for ps_prochandle\n");
+ return NULL;
+ }
+
+ if (ptrace_attach(pid) != true) {
+ free(ph);
+ return NULL;
+ }
+
+ // initialize ps_prochandle
+ ph->pid = pid;
+
+ // initialize vtable
+ ph->ops = &process_ops;
+
+ // read library info and symbol tables, must do this before attaching threads,
+ // as the symbols in the pthread library will be used to figure out
+ // the list of threads within the same process.
+ if (read_lib_info(ph) != true) {
+ ptrace_detach(pid);
+ free(ph);
+ return NULL;
+ }
+
+ // read thread info
+ read_thread_info(ph, add_new_thread);
+
+ return ph;
+}
diff --git a/agent/src/os/bsd/salibelf.c b/agent/src/os/bsd/salibelf.c
new file mode 100644
index 000000000..4c860a0fe
--- /dev/null
+++ b/agent/src/os/bsd/salibelf.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2003, 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.
+ *
+ * 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 "salibelf.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+extern void print_debug(const char*,...);
+
+// ELF file parsing helpers. Note that we do *not* use libelf here.
+int read_elf_header(int fd, ELF_EHDR* ehdr) {
+ if (pread(fd, ehdr, sizeof (ELF_EHDR), 0) != sizeof (ELF_EHDR) ||
+ memcmp(&ehdr->e_ident[EI_MAG0], ELFMAG, SELFMAG) != 0 ||
+ ehdr->e_version != EV_CURRENT) {
+ return 0;
+ }
+ return 1;
+}
+
+bool is_elf_file(int fd) {
+ ELF_EHDR ehdr;
+ return read_elf_header(fd, &ehdr);
+}
+
+// read program header table of an ELF file
+ELF_PHDR* read_program_header_table(int fd, ELF_EHDR* hdr) {
+ ELF_PHDR* phbuf = 0;
+ // allocate memory for program header table
+ size_t nbytes = hdr->e_phnum * hdr->e_phentsize;
+
+ if ((phbuf = (ELF_PHDR*) malloc(nbytes)) == NULL) {
+ print_debug("can't allocate memory for reading program header table\n");
+ return NULL;
+ }
+
+ if (pread(fd, phbuf, nbytes, hdr->e_phoff) != nbytes) {
+ print_debug("ELF file is truncated! can't read program header table\n");
+ free(phbuf);
+ return NULL;
+ }
+
+ return phbuf;
+}
+
+// read section header table of an ELF file
+ELF_SHDR* read_section_header_table(int fd, ELF_EHDR* hdr) {
+ ELF_SHDR* shbuf = 0;
+ // allocate memory for section header table
+ size_t nbytes = hdr->e_shnum * hdr->e_shentsize;
+
+ if ((shbuf = (ELF_SHDR*) malloc(nbytes)) == NULL) {
+ print_debug("can't allocate memory for reading section header table\n");
+ return NULL;
+ }
+
+ if (pread(fd, shbuf, nbytes, hdr->e_shoff) != nbytes) {
+ print_debug("ELF file is truncated! can't read section header table\n");
+ free(shbuf);
+ return NULL;
+ }
+
+ return shbuf;
+}
+
+// read a particular section's data
+void* read_section_data(int fd, ELF_EHDR* ehdr, ELF_SHDR* shdr) {
+ void *buf = NULL;
+ if (shdr->sh_type == SHT_NOBITS || shdr->sh_size == 0) {
+ return buf;
+ }
+ if ((buf = calloc(shdr->sh_size, 1)) == NULL) {
+ print_debug("can't allocate memory for reading section data\n");
+ return NULL;
+ }
+ if (pread(fd, buf, shdr->sh_size, shdr->sh_offset) != shdr->sh_size) {
+ free(buf);
+ print_debug("section data read failed\n");
+ return NULL;
+ }
+ return buf;
+}
+
+uintptr_t find_base_address(int fd, ELF_EHDR* ehdr) {
+ uintptr_t baseaddr = (uintptr_t)-1;
+ int cnt;
+ ELF_PHDR *phbuf, *phdr;
+
+ // read program header table
+ if ((phbuf = read_program_header_table(fd, ehdr)) == NULL) {
+ goto quit;
+ }
+
+ // the base address of a shared object is the lowest vaddr of
+ // its loadable segments (PT_LOAD)
+ for (phdr = phbuf, cnt = 0; cnt < ehdr->e_phnum; cnt++, phdr++) {
+ if (phdr->p_type == PT_LOAD && phdr->p_vaddr < baseaddr) {
+ baseaddr = phdr->p_vaddr;
+ }
+ }
+
+quit:
+ if (phbuf) free(phbuf);
+ return baseaddr;
+}
diff --git a/agent/src/os/bsd/salibelf.h b/agent/src/os/bsd/salibelf.h
new file mode 100644
index 000000000..957694b25
--- /dev/null
+++ b/agent/src/os/bsd/salibelf.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2003, 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.
+ *
+ * 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 _SALIBELF_H_
+#define _SALIBELF_H_
+
+#include <elf.h>
+#include "elfmacros.h"
+#include "libproc_impl.h"
+
+// read ELF file header.
+int read_elf_header(int fd, ELF_EHDR* ehdr);
+
+// is given file descriptor corresponds to an ELF file?
+bool is_elf_file(int fd);
+
+// read program header table of an ELF file. caller has to
+// free the result pointer after use. NULL on failure.
+ELF_PHDR* read_program_header_table(int fd, ELF_EHDR* hdr);
+
+// read section header table of an ELF file. caller has to
+// free the result pointer after use. NULL on failure.
+ELF_SHDR* read_section_header_table(int fd, ELF_EHDR* hdr);
+
+// read a particular section's data. caller has to free the
+// result pointer after use. NULL on failure.
+void* read_section_data(int fd, ELF_EHDR* ehdr, ELF_SHDR* shdr);
+
+// find the base address at which the library wants to load itself
+uintptr_t find_base_address(int fd, ELF_EHDR* ehdr);
+#endif /* _SALIBELF_H_ */
diff --git a/agent/src/os/bsd/symtab.c b/agent/src/os/bsd/symtab.c
new file mode 100644
index 000000000..0362cf0d6
--- /dev/null
+++ b/agent/src/os/bsd/symtab.c
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include <unistd.h>
+#include <search.h>
+#include <stdlib.h>
+#include <string.h>
+#include <db.h>
+#include <fcntl.h>
+#include "symtab.h"
+#include "salibelf.h"
+
+
+// ----------------------------------------------------
+// functions for symbol lookups
+// ----------------------------------------------------
+
+struct elf_section {
+ ELF_SHDR *c_shdr;
+ void *c_data;
+};
+
+struct elf_symbol {
+ char *name;
+ uintptr_t offset;
+ uintptr_t size;
+};
+
+typedef struct symtab {
+ char *strs;
+ size_t num_symbols;
+ struct elf_symbol *symbols;
+ DB* hash_table;
+} symtab_t;
+
+// read symbol table from given fd.
+struct symtab* build_symtab(int fd) {
+ ELF_EHDR ehdr;
+ struct symtab* symtab = NULL;
+
+ // Reading of elf header
+ struct elf_section *scn_cache = NULL;
+ int cnt = 0;
+ ELF_SHDR* shbuf = NULL;
+ ELF_SHDR* cursct = NULL;
+ ELF_PHDR* phbuf = NULL;
+ int symtab_found = 0;
+ int dynsym_found = 0;
+ uint32_t symsection = SHT_SYMTAB;
+
+ uintptr_t baseaddr = (uintptr_t)-1;
+
+ lseek(fd, (off_t)0L, SEEK_SET);
+ if (! read_elf_header(fd, &ehdr)) {
+ // not an elf
+ return NULL;
+ }
+
+ // read ELF header
+ if ((shbuf = read_section_header_table(fd, &ehdr)) == NULL) {
+ goto quit;
+ }
+
+ baseaddr = find_base_address(fd, &ehdr);
+
+ scn_cache = calloc(ehdr.e_shnum, sizeof(*scn_cache));
+ if (scn_cache == NULL) {
+ goto quit;
+ }
+
+ for (cursct = shbuf, cnt = 0; cnt < ehdr.e_shnum; cnt++) {
+ scn_cache[cnt].c_shdr = cursct;
+ if (cursct->sh_type == SHT_SYMTAB ||
+ cursct->sh_type == SHT_STRTAB ||
+ cursct->sh_type == SHT_DYNSYM) {
+ if ( (scn_cache[cnt].c_data = read_section_data(fd, &ehdr, cursct)) == NULL) {
+ goto quit;
+ }
+ }
+
+ if (cursct->sh_type == SHT_SYMTAB)
+ symtab_found++;
+
+ if (cursct->sh_type == SHT_DYNSYM)
+ dynsym_found++;
+
+ cursct++;
+ }
+
+ if (!symtab_found && dynsym_found)
+ symsection = SHT_DYNSYM;
+
+ for (cnt = 1; cnt < ehdr.e_shnum; cnt++) {
+ ELF_SHDR *shdr = scn_cache[cnt].c_shdr;
+
+ if (shdr->sh_type == symsection) {
+ ELF_SYM *syms;
+ int j, n, rslt;
+ size_t size;
+
+ // FIXME: there could be multiple data buffers associated with the
+ // same ELF section. Here we can handle only one buffer. See man page
+ // for elf_getdata on Solaris.
+
+ // guarantee(symtab == NULL, "multiple symtab");
+ symtab = calloc(1, sizeof(*symtab));
+ if (symtab == NULL) {
+ goto quit;
+ }
+ // the symbol table
+ syms = (ELF_SYM *)scn_cache[cnt].c_data;
+
+ // number of symbols
+ n = shdr->sh_size / shdr->sh_entsize;
+
+ // create hash table, we use berkeley db to
+ // manipulate the hash table.
+ symtab->hash_table = dbopen(NULL, O_CREAT | O_RDWR, 0600, DB_HASH, NULL);
+ // guarantee(symtab->hash_table, "unexpected failure: dbopen");
+
+ // shdr->sh_link points to the section that contains the actual strings
+ // for symbol names. the st_name field in ELF_SYM is just the
+ // string table index. we make a copy of the string table so the
+ // strings will not be destroyed by elf_end.
+ size = scn_cache[shdr->sh_link].c_shdr->sh_size;
+ symtab->strs = malloc(size);
+ memcpy(symtab->strs, scn_cache[shdr->sh_link].c_data, size);
+
+ // allocate memory for storing symbol offset and size;
+ symtab->num_symbols = n;
+ symtab->symbols = calloc(n , sizeof(*symtab->symbols));
+
+ // copy symbols info our symtab and enter them info the hash table
+ for (j = 0; j < n; j++, syms++) {
+ DBT key, value;
+ char *sym_name = symtab->strs + syms->st_name;
+
+ // skip non-object and non-function symbols
+ int st_type = ELF_ST_TYPE(syms->st_info);
+ if ( st_type != STT_FUNC && st_type != STT_OBJECT)
+ continue;
+ // skip empty strings and undefined symbols
+ if (*sym_name == '\0' || syms->st_shndx == SHN_UNDEF) continue;
+
+ symtab->symbols[j].name = sym_name;
+ symtab->symbols[j].offset = syms->st_value - baseaddr;
+ symtab->symbols[j].size = syms->st_size;
+
+ key.data = sym_name;
+ key.size = strlen(sym_name) + 1;
+ value.data = &(symtab->symbols[j]);
+ value.size = sizeof(void *);
+ (*symtab->hash_table->put)(symtab->hash_table, &key, &value, 0);
+ }
+ }
+ }
+
+quit:
+ if (shbuf) free(shbuf);
+ if (phbuf) free(phbuf);
+ if (scn_cache) {
+ for (cnt = 0; cnt < ehdr.e_shnum; cnt++) {
+ if (scn_cache[cnt].c_data != NULL) {
+ free(scn_cache[cnt].c_data);
+ }
+ }
+ free(scn_cache);
+ }
+ return symtab;
+}
+
+void destroy_symtab(struct symtab* symtab) {
+ if (!symtab) return;
+ if (symtab->strs) free(symtab->strs);
+ if (symtab->symbols) free(symtab->symbols);
+ if (symtab->hash_table) {
+ symtab->hash_table->close(symtab->hash_table);
+ }
+ free(symtab);
+}
+
+uintptr_t search_symbol(struct symtab* symtab, uintptr_t base,
+ const char *sym_name, int *sym_size) {
+ DBT key, value;
+ int ret;
+
+ // library does not have symbol table
+ if (!symtab || !symtab->hash_table)
+ return 0;
+
+ key.data = (char*)(uintptr_t)sym_name;
+ key.size = strlen(sym_name) + 1;
+ ret = (*symtab->hash_table->get)(symtab->hash_table, &key, &value, 0);
+ if (ret == 0) {
+ struct elf_symbol *sym = value.data;
+ uintptr_t rslt = (uintptr_t) ((char*)base + sym->offset);
+ if (sym_size) *sym_size = sym->size;
+ return rslt;
+ }
+
+quit:
+ return 0;
+}
+
+const char* nearest_symbol(struct symtab* symtab, uintptr_t offset,
+ uintptr_t* poffset) {
+ int n = 0;
+ if (!symtab) return NULL;
+ for (; n < symtab->num_symbols; n++) {
+ struct elf_symbol* sym = &(symtab->symbols[n]);
+ if (sym->name != NULL &&
+ offset >= sym->offset && offset < sym->offset + sym->size) {
+ if (poffset) *poffset = (offset - sym->offset);
+ return sym->name;
+ }
+ }
+ return NULL;
+}
diff --git a/agent/src/os/bsd/symtab.h b/agent/src/os/bsd/symtab.h
new file mode 100644
index 000000000..9b7eef77d
--- /dev/null
+++ b/agent/src/os/bsd/symtab.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef _SYMTAB_H_
+#define _SYMTAB_H_
+
+#include <stdint.h>
+
+// interface to manage ELF symbol tables
+
+struct symtab;
+
+// build symbol table for a given ELF file descriptor
+struct symtab* build_symtab(int fd);
+
+// destroy the symbol table
+void destroy_symtab(struct symtab* symtab);
+
+// search for symbol in the given symbol table. Adds offset
+// to the base uintptr_t supplied. Returns NULL if not found.
+uintptr_t search_symbol(struct symtab* symtab, uintptr_t base,
+ const char *sym_name, int *sym_size);
+
+// look for nearest symbol for a given offset (not address - base
+// subtraction done by caller
+const char* nearest_symbol(struct symtab* symtab, uintptr_t offset,
+ uintptr_t* poffset);
+
+#endif /*_SYMTAB_H_*/
diff --git a/agent/src/os/bsd/test.c b/agent/src/os/bsd/test.c
new file mode 100644
index 000000000..3659542d5
--- /dev/null
+++ b/agent/src/os/bsd/test.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "libproc.h"
+
+int main(int argc, char** argv) {
+ struct ps_prochandle* ph;
+
+ init_libproc(true);
+ switch (argc) {
+ case 2: {
+ // process
+ ph = Pgrab(atoi(argv[1]));
+ break;
+ }
+
+ case 3: {
+ // core
+ ph = Pgrab_core(argv[1], argv[2]);
+ break;
+ }
+
+ default: {
+ fprintf(stderr, "usage %s <pid> or %s <exec file> <core file>\n", argv[0], argv[0]);
+ return 1;
+ }
+ }
+
+ if (ph) {
+ Prelease(ph);
+ return 0;
+ } else {
+ printf("can't connect to debuggee\n");
+ return 1;
+ }
+}
diff --git a/agent/src/share/classes/sun/jvm/hotspot/BsdVtblAccess.java b/agent/src/share/classes/sun/jvm/hotspot/BsdVtblAccess.java
new file mode 100644
index 000000000..ed688758d
--- /dev/null
+++ b/agent/src/share/classes/sun/jvm/hotspot/BsdVtblAccess.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot;
+
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.types.*;
+import sun.jvm.hotspot.types.basic.*;
+
+public class BsdVtblAccess extends BasicVtblAccess {
+ private String vt;
+
+ public BsdVtblAccess(SymbolLookup symbolLookup,
+ String[] dllNames) {
+ super(symbolLookup, dllNames);
+
+ if (symbolLookup.lookup("libjvm.so", "__vt_10JavaThread") != null ||
+ symbolLookup.lookup("libjvm_g.so", "__vt_10JavaThread") != null) {
+ // old C++ ABI
+ vt = "__vt_";
+ } else {
+ // new C++ ABI
+ vt = "_ZTV";
+ }
+ }
+
+ protected String vtblSymbolForType(Type type) {
+ return vt + type.getName().length() + type;
+ }
+}
diff --git a/agent/src/share/classes/sun/jvm/hotspot/HotSpotAgent.java b/agent/src/share/classes/sun/jvm/hotspot/HotSpotAgent.java
index 0b655b8b1..233bc173a 100644
--- a/agent/src/share/classes/sun/jvm/hotspot/HotSpotAgent.java
+++ b/agent/src/share/classes/sun/jvm/hotspot/HotSpotAgent.java
@@ -28,6 +28,7 @@ import java.io.PrintStream;
import java.net.*;
import java.rmi.*;
import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.debugger.bsd.*;
import sun.jvm.hotspot.debugger.proc.*;
import sun.jvm.hotspot.debugger.remote.*;
import sun.jvm.hotspot.debugger.windbg.*;
@@ -335,6 +336,8 @@ public class HotSpotAgent {
setupDebuggerWin32();
} else if (os.equals("linux")) {
setupDebuggerLinux();
+ } else if (os.equals("bsd")) {
+ setupDebuggerBsd();
} else {
// Add support for more operating systems here
throw new DebuggerException("Operating system " + os + " not yet supported");
@@ -390,6 +393,10 @@ public class HotSpotAgent {
db = new HotSpotTypeDataBase(machDesc,
new LinuxVtblAccess(debugger, jvmLibNames),
debugger, jvmLibNames);
+ } else if (os.equals("bsd")) {
+ db = new HotSpotTypeDataBase(machDesc,
+ new BsdVtblAccess(debugger, jvmLibNames),
+ debugger, jvmLibNames);
} else {
throw new DebuggerException("OS \"" + os + "\" not yet supported (no VtblAccess yet)");
}
@@ -477,6 +484,8 @@ public class HotSpotAgent {
setupJVMLibNamesWin32();
} else if (os.equals("linux")) {
setupJVMLibNamesLinux();
+ } else if (os.equals("bsd")) {
+ setupJVMLibNamesBsd();
} else {
throw new RuntimeException("Unknown OS type");
}
@@ -554,6 +563,31 @@ public class HotSpotAgent {
jvmLibNames = new String[] { "libjvm.so", "libjvm_g.so" };
}
+ //
+ // BSD
+ //
+
+ private void setupDebuggerBsd() {
+ setupJVMLibNamesBsd();
+
+ if (cpu.equals("x86")) {
+ machDesc = new MachineDescriptionIntelX86();
+ } else if (cpu.equals("amd64")) {
+ machDesc = new MachineDescriptionAMD64();
+ } else {
+ throw new DebuggerException("BSD only supported on x86/amd64");
+ }
+
+ BsdDebuggerLocal dbg = new BsdDebuggerLocal(machDesc, !isServer);
+ debugger = dbg;
+
+ attachDebugger();
+ }
+
+ private void setupJVMLibNamesBsd() {
+ jvmLibNames = new String[] { "libjvm.so", "libjvm_g.so" };
+ }
+
/** Convenience routine which should be called by per-platform
debugger setup. Should not be called when startupMode is
REMOTE_MODE. */
diff --git a/agent/src/share/classes/sun/jvm/hotspot/bugspot/BugSpotAgent.java b/agent/src/share/classes/sun/jvm/hotspot/bugspot/BugSpotAgent.java
index 8a5abc8a9..bb0a44470 100644
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/BugSpotAgent.java
+++ b/agent/src/share/classes/sun/jvm/hotspot/bugspot/BugSpotAgent.java
@@ -29,6 +29,7 @@ import java.net.*;
import java.rmi.*;
import sun.jvm.hotspot.*;
import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.debugger.bsd.*;
import sun.jvm.hotspot.debugger.proc.*;
import sun.jvm.hotspot.debugger.cdbg.*;
import sun.jvm.hotspot.debugger.windbg.*;
@@ -514,6 +515,8 @@ public class BugSpotAgent {
setupDebuggerWin32();
} else if (os.equals("linux")) {
setupDebuggerLinux();
+ } else if (os.equals("bsd")) {
+ setupDebuggerBsd();
} else {
// Add support for more operating systems here
throw new DebuggerException("Operating system " + os + " not yet supported");
@@ -565,6 +568,9 @@ public class BugSpotAgent {
} else if (os.equals("linux")) {
db = new HotSpotTypeDataBase(machDesc, new LinuxVtblAccess(debugger, jvmLibNames),
debugger, jvmLibNames);
+ } else if (os.equals("bsd")) {
+ db = new HotSpotTypeDataBase(machDesc, new BsdVtblAccess(debugger, jvmLibNames),
+ debugger, jvmLibNames);
} else {
throw new DebuggerException("OS \"" + os + "\" not yet supported (no VtblAccess implemented yet)");
}
@@ -666,6 +672,8 @@ public class BugSpotAgent {
setupJVMLibNamesWin32();
} else if (os.equals("linux")) {
setupJVMLibNamesLinux();
+ } else if (os.equals("bsd")) {
+ setupJVMLibNamesBsd();
} else {
throw new RuntimeException("Unknown OS type");
}
@@ -745,6 +753,34 @@ public class BugSpotAgent {
setupJVMLibNamesSolaris();
}
+ //
+ // BSD
+ //
+
+ private void setupDebuggerBsd() {
+ setupJVMLibNamesBsd();
+
+ if (cpu.equals("x86")) {
+ machDesc = new MachineDescriptionIntelX86();
+ } else if (cpu.equals("amd64")) {
+ machDesc = new MachineDescriptionAMD64();
+ } else {
+ throw new DebuggerException("Bsd only supported on x86/amd64");
+ }
+
+ // Note we do not use a cache for the local debugger in server
+ // mode; it will be taken care of on the client side (once remote
+ // debugging is implemented).
+
+ debugger = new BsdDebuggerLocal(machDesc, !isServer);
+ attachDebugger();
+ }
+
+ private void setupJVMLibNamesBsd() {
+ // same as solaris
+ setupJVMLibNamesSolaris();
+ }
+
/** Convenience routine which should be called by per-platform
debugger setup. Should not be called when startupMode is
REMOTE_MODE. */
diff --git a/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdAddress.java b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdAddress.java
new file mode 100644
index 000000000..de707f0e9
--- /dev/null
+++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdAddress.java
@@ -0,0 +1,399 @@
+/*
+ * Copyright (c) 2002, 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot.debugger.bsd;
+
+import sun.jvm.hotspot.debugger.*;
+
+class BsdAddress implements Address {
+ protected BsdDebugger debugger;
+ protected long addr;
+
+ BsdAddress(BsdDebugger debugger, long addr) {
+ this.debugger = debugger;
+ this.addr = addr;
+ }
+
+ //
+ // Basic Java routines
+ //
+
+ public boolean equals(Object arg) {
+ if (arg == null) {
+ return false;
+ }
+
+ if (!(arg instanceof BsdAddress)) {
+ return false;
+ }
+
+ return (addr == ((BsdAddress) arg).addr);
+ }
+
+ public int hashCode() {
+ // FIXME: suggestions on a better hash code?
+ return (int) addr;
+ }
+
+ public String toString() {
+ return debugger.addressValueToString(addr);
+ }
+
+ //
+ // C/C++-related routines
+ //
+
+ public long getCIntegerAt(long offset, long numBytes, boolean isUnsigned)
+ throws UnalignedAddressException, UnmappedAddressException {
+ return debugger.readCInteger(addr + offset, numBytes, isUnsigned);
+ }
+
+ public Address getAddressAt(long offset)
+ throws UnalignedAddressException, UnmappedAddressException {
+ return debugger.readAddress(addr + offset);
+ }
+
+ public Address getCompOopAddressAt(long offset)
+ throws UnalignedAddressException, UnmappedAddressException {
+ return debugger.readCompOopAddress(addr + offset);
+ }
+
+ //
+ // Java-related routines
+ //
+
+ public boolean getJBooleanAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
+ return debugger.readJBoolean(addr + offset);
+ }
+
+ public byte getJByteAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
+ return debugger.readJByte(addr + offset);
+ }
+
+ public char getJCharAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
+ return debugger.readJChar(addr + offset);
+ }
+
+ public double getJDoubleAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
+ return debugger.readJDouble(addr + offset);
+ }
+
+ public float getJFloatAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
+ return debugger.readJFloat(addr + offset);
+ }
+
+ public int getJIntAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
+ return debugger.readJInt(addr + offset);
+ }
+
+ public long getJLongAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
+ return debugger.readJLong(addr + offset);
+ }
+
+ public short getJShortAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
+ return debugger.readJShort(addr + offset);
+ }
+
+ public OopHandle getOopHandleAt(long offset)
+ throws UnalignedAddressException, UnmappedAddressException, NotInHeapException {
+ return debugger.readOopHandle(addr + offset);
+ }
+
+ public OopHandle getCompOopHandleAt(long offset)
+ throws UnalignedAddressException, UnmappedAddressException, NotInHeapException {
+ return debugger.readCompOopHandle(addr + offset);
+ }
+
+ // Mutators -- not implemented for now (FIXME)
+ public void setCIntegerAt(long offset, long numBytes, long value) {
+ throw new DebuggerException("Unimplemented");
+ }
+ public void setAddressAt(long offset, Address value) {
+ throw new DebuggerException("Unimplemented");
+ }
+ public void setJBooleanAt (long offset, boolean value)
+ throws UnmappedAddressException, UnalignedAddressException {
+ throw new DebuggerException("Unimplemented");
+ }
+ public void setJByteAt (long offset, byte value)
+ throws UnmappedAddressException, UnalignedAddressException {
+ throw new DebuggerException("Unimplemented");
+ }
+ public void setJCharAt (long offset, char value)
+ throws UnmappedAddressException, UnalignedAddressException {
+ throw new DebuggerException("Unimplemented");
+ }
+ public void setJDoubleAt (long offset, double value)
+ throws UnmappedAddressException, UnalignedAddressException {
+ throw new DebuggerException("Unimplemented");
+ }
+ public void setJFloatAt (long offset, float value)
+ throws UnmappedAddressException, UnalignedAddressException {
+ throw new DebuggerException("Unimplemented");
+ }
+ public void setJIntAt (long offset, int value)
+ throws UnmappedAddressException, UnalignedAddressException {
+ throw new DebuggerException("Unimplemented");
+ }
+ public void setJLongAt (long offset, long value)
+ throws UnmappedAddressException, UnalignedAddressException {
+ throw new DebuggerException("Unimplemented");
+ }
+ public void setJShortAt (long offset, short value)
+ throws UnmappedAddressException, UnalignedAddressException {
+ throw new DebuggerException("Unimplemented");
+ }
+ public void setOopHandleAt (long offset, OopHandle value)
+ throws UnmappedAddressException, UnalignedAddressException {
+ throw new DebuggerException("Unimplemented");
+ }
+
+ //
+ // Arithmetic operations -- necessary evil.
+ //
+
+ public Address addOffsetTo (long offset) throws UnsupportedOperationException {
+ long value = addr + offset;
+ if (value == 0) {
+ return null;
+ }
+ return new BsdAddress(debugger, value);
+ }
+
+ public OopHandle addOffsetToAsOopHandle(long offset) throws UnsupportedOperationException {
+ long value = addr + offset;
+ if (value == 0) {
+ return null;
+ }
+ return new BsdOopHandle(debugger, value);
+ }
+
+ /** (FIXME: any signed/unsigned issues? Should this work for
+ OopHandles?) */
+ public long minus(Address arg) {
+ if (arg == null) {
+ return addr;
+ }
+ return addr - ((BsdAddress) arg).addr;
+ }
+
+ // Two's complement representation.
+ // All negative numbers are larger than positive numbers.
+ // Numbers with the same sign can be compared normally.
+ // Test harness is below in main().
+
+ public boolean lessThan (Address a) {
+ if (a == null) {
+ return false;
+ }
+ BsdAddress arg = (BsdAddress) a;
+ if ((addr >= 0) && (arg.addr < 0)) {
+ return true;
+ }
+ if ((addr < 0) && (arg.addr >= 0)) {
+ return false;
+ }
+ return (addr < arg.addr);
+ }
+
+ public boolean lessThanOrEqual (Address a) {
+ if (a == null) {
+ return false;
+ }
+ BsdAddress arg = (BsdAddress) a;
+ if ((addr >= 0) && (arg.addr < 0)) {
+ return true;
+ }
+ if ((addr < 0) && (arg.addr >= 0)) {
+ return false;
+ }
+ return (addr <= arg.addr);
+ }
+
+ public boolean greaterThan (Address a) {
+ if (a == null) {
+ return true;
+ }
+ BsdAddress arg = (BsdAddress) a;
+ if ((addr >= 0) && (arg.addr < 0)) {
+ return false;
+ }
+ if ((addr < 0) && (arg.addr >= 0)) {
+ return true;
+ }
+ return (addr > arg.addr);
+ }
+
+ public boolean greaterThanOrEqual(Address a) {
+ if (a == null) {
+ return true;
+ }
+ BsdAddress arg = (BsdAddress) a;
+ if ((addr >= 0) && (arg.addr < 0)) {
+ return false;
+ }
+ if ((addr < 0) && (arg.addr >= 0)) {
+ return true;
+ }
+ return (addr >= arg.addr);
+ }
+
+ public Address andWithMask(long mask) throws UnsupportedOperationException {
+ long value = addr & mask;
+ if (value == 0) {
+ return null;
+ }
+ return new BsdAddress(debugger, value);
+ }
+
+ public Address orWithMask(long mask) throws UnsupportedOperationException {
+ long value = addr | mask;
+ if (value == 0) {
+ return null;
+ }
+ return new BsdAddress(debugger, value);
+ }
+
+ public Address xorWithMask(long mask) throws UnsupportedOperationException {
+ long value = addr ^ mask;
+ if (value == 0) {
+ return null;
+ }
+ return new BsdAddress(debugger, value);
+ }
+
+
+ //--------------------------------------------------------------------------------
+ // Internals only below this point
+ //
+
+ long getValue() {
+ return addr;
+ }
+
+
+ private static void check(boolean arg, String failMessage) {
+ if (!arg) {
+ System.err.println(failMessage + ": FAILED");
+ System.exit(1);
+ }
+ }
+
+ // Test harness
+ public static void main(String[] args) {
+ // p/n indicates whether the interior address is really positive
+ // or negative. In unsigned terms, p1 < p2 < n1 < n2.
+
+ BsdAddress p1 = new BsdAddress(null, 0x7FFFFFFFFFFFFFF0L);
+ BsdAddress p2 = (BsdAddress) p1.addOffsetTo(10);
+ BsdAddress n1 = (BsdAddress) p2.addOffsetTo(10);
+ BsdAddress n2 = (BsdAddress) n1.addOffsetTo(10);
+
+ // lessThan positive tests
+ check(p1.lessThan(p2), "lessThan 1");
+ check(p1.lessThan(n1), "lessThan 2");
+ check(p1.lessThan(n2), "lessThan 3");
+ check(p2.lessThan(n1), "lessThan 4");
+ check(p2.lessThan(n2), "lessThan 5");
+ check(n1.lessThan(n2), "lessThan 6");
+
+ // lessThan negative tests
+ check(!p1.lessThan(p1), "lessThan 7");
+ check(!p2.lessThan(p2), "lessThan 8");
+ check(!n1.lessThan(n1), "lessThan 9");
+ check(!n2.lessThan(n2), "lessThan 10");
+
+ check(!p2.lessThan(p1), "lessThan 11");
+ check(!n1.lessThan(p1), "lessThan 12");
+ check(!n2.lessThan(p1), "lessThan 13");
+ check(!n1.lessThan(p2), "lessThan 14");
+ check(!n2.lessThan(p2), "lessThan 15");
+ check(!n2.lessThan(n1), "lessThan 16");
+
+ // lessThanOrEqual positive tests
+ check(p1.lessThanOrEqual(p1), "lessThanOrEqual 1");
+ check(p2.lessThanOrEqual(p2), "lessThanOrEqual 2");
+ check(n1.lessThanOrEqual(n1), "lessThanOrEqual 3");
+ check(n2.lessThanOrEqual(n2), "lessThanOrEqual 4");
+
+ check(p1.lessThanOrEqual(p2), "lessThanOrEqual 5");
+ check(p1.lessThanOrEqual(n1), "lessThanOrEqual 6");
+ check(p1.lessThanOrEqual(n2), "lessThanOrEqual 7");
+ check(p2.lessThanOrEqual(n1), "lessThanOrEqual 8");
+ check(p2.lessThanOrEqual(n2), "lessThanOrEqual 9");
+ check(n1.lessThanOrEqual(n2), "lessThanOrEqual 10");
+
+ // lessThanOrEqual negative tests
+ check(!p2.lessThanOrEqual(p1), "lessThanOrEqual 11");
+ check(!n1.lessThanOrEqual(p1), "lessThanOrEqual 12");
+ check(!n2.lessThanOrEqual(p1), "lessThanOrEqual 13");
+ check(!n1.lessThanOrEqual(p2), "lessThanOrEqual 14");
+ check(!n2.lessThanOrEqual(p2), "lessThanOrEqual 15");
+ check(!n2.lessThanOrEqual(n1), "lessThanOrEqual 16");
+
+ // greaterThan positive tests
+ check(n2.greaterThan(p1), "greaterThan 1");
+ check(n2.greaterThan(p2), "greaterThan 2");
+ check(n2.greaterThan(n1), "greaterThan 3");
+ check(n1.greaterThan(p1), "greaterThan 4");
+ check(n1.greaterThan(p2), "greaterThan 5");
+ check(p2.greaterThan(p1), "greaterThan 6");
+
+ // greaterThan negative tests
+ check(!p1.greaterThan(p1), "greaterThan 7");
+ check(!p2.greaterThan(p2), "greaterThan 8");
+ check(!n1.greaterThan(n1), "greaterThan 9");
+ check(!n2.greaterThan(n2), "greaterThan 10");
+
+ check(!p1.greaterThan(n2), "greaterThan 11");
+ check(!p2.greaterThan(n2), "greaterThan 12");
+ check(!n1.greaterThan(n2), "greaterThan 13");
+ check(!p1.greaterThan(n1), "greaterThan 14");
+ check(!p2.greaterThan(n1), "greaterThan 15");
+ check(!p1.greaterThan(p2), "greaterThan 16");
+
+ // greaterThanOrEqual positive tests
+ check(p1.greaterThanOrEqual(p1), "greaterThanOrEqual 1");
+ check(p2.greaterThanOrEqual(p2), "greaterThanOrEqual 2");
+ check(n1.greaterThanOrEqual(n1), "greaterThanOrEqual 3");
+ check(n2.greaterThanOrEqual(n2), "greaterThanOrEqual 4");
+
+ check(n2.greaterThanOrEqual(p1), "greaterThanOrEqual 5");
+ check(n2.greaterThanOrEqual(p2), "greaterThanOrEqual 6");
+ check(n2.greaterThanOrEqual(n1), "greaterThanOrEqual 7");
+ check(n1.greaterThanOrEqual(p1), "greaterThanOrEqual 8");
+ check(n1.greaterThanOrEqual(p2), "greaterThanOrEqual 9");
+ check(p2.greaterThanOrEqual(p1), "greaterThanOrEqual 10");
+
+ // greaterThanOrEqual negative tests
+ check(!p1.greaterThanOrEqual(n2), "greaterThanOrEqual 11");
+ check(!p2.greaterThanOrEqual(n2), "greaterThanOrEqual 12");
+ check(!n1.greaterThanOrEqual(n2), "greaterThanOrEqual 13");
+ check(!p1.greaterThanOrEqual(n1), "greaterThanOrEqual 14");
+ check(!p2.greaterThanOrEqual(n1), "greaterThanOrEqual 15");
+ check(!p1.greaterThanOrEqual(p2), "greaterThanOrEqual 16");
+
+ System.err.println("BsdAddress: all tests passed successfully.");
+ }
+}
diff --git a/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdCDebugger.java b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdCDebugger.java
new file mode 100644
index 000000000..92f7bbf3d
--- /dev/null
+++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdCDebugger.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2003, 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot.debugger.bsd;
+
+import java.io.*;
+import java.util.*;
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.debugger.cdbg.*;
+import sun.jvm.hotspot.debugger.x86.*;
+import sun.jvm.hotspot.debugger.amd64.*;
+import sun.jvm.hotspot.debugger.bsd.x86.*;
+import sun.jvm.hotspot.debugger.bsd.amd64.*;
+import sun.jvm.hotspot.utilities.*;
+
+class BsdCDebugger implements CDebugger {
+ private BsdDebugger dbg;
+
+ BsdCDebugger(BsdDebugger dbg) {
+ this.dbg = dbg;
+ }
+
+ public List getThreadList() throws DebuggerException {
+ return dbg.getThreadList();
+ }
+
+ public List/*<LoadObject>*/ getLoadObjectList() throws DebuggerException {
+ return dbg.getLoadObjectList();
+ }
+
+ public LoadObject loadObjectContainingPC(Address pc) throws DebuggerException {
+ if (pc == null) {
+ return null;
+ }
+ List objs = getLoadObjectList();
+ Object[] arr = objs.toArray();
+ // load objects are sorted by base address, do binary search
+ int mid = -1;
+ int low = 0;
+ int high = arr.length - 1;
+
+ while (low <= high) {
+ mid = (low + high) >> 1;
+ LoadObject midVal = (LoadObject) arr[mid];
+ long cmp = pc.minus(midVal.getBase());
+ if (cmp < 0) {
+ high = mid - 1;
+ } else if (cmp > 0) {
+ long size = midVal.getSize();
+ if (cmp >= size) {
+ low = mid + 1;
+ } else {
+ return (LoadObject) arr[mid];
+ }
+ } else { // match found
+ return (LoadObject) arr[mid];
+ }
+ }
+ // no match found.
+ return null;
+ }
+
+ public CFrame topFrameForThread(ThreadProxy thread) throws DebuggerException {
+ String cpu = dbg.getCPU();
+ if (cpu.equals("x86")) {
+ X86ThreadContext context = (X86ThreadContext) thread.getContext();
+ Address ebp = context.getRegisterAsAddress(X86ThreadContext.EBP);
+ if (ebp == null) return null;
+ Address pc = context.getRegisterAsAddress(X86ThreadContext.EIP);
+ if (pc == null) return null;
+ return new BsdX86CFrame(dbg, ebp, pc);
+ } else if (cpu.equals("amd64")) {
+ AMD64ThreadContext context = (AMD64ThreadContext) thread.getContext();
+ Address rbp = context.getRegisterAsAddress(AMD64ThreadContext.RBP);
+ if (rbp == null) return null;
+ Address pc = context.getRegisterAsAddress(AMD64ThreadContext.RIP);
+ if (pc == null) return null;
+ return new BsdAMD64CFrame(dbg, rbp, pc);
+ } else {
+ throw new DebuggerException(cpu + " is not yet supported");
+ }
+ }
+
+ public String getNameOfFile(String fileName) {
+ return new File(fileName).getName();
+ }
+
+ public ProcessControl getProcessControl() throws DebuggerException {
+ // FIXME: after stabs parser
+ return null;
+ }
+
+ public boolean canDemangle() {
+ return false;
+ }
+
+ public String demangle(String sym) {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebugger.java b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebugger.java
new file mode 100644
index 000000000..a708a750c
--- /dev/null
+++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebugger.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2002, 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot.debugger.bsd;
+
+import java.util.List;
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.debugger.cdbg.*;
+
+/** An extension of the JVMDebugger interface with a few additions to
+ support 32-bit vs. 64-bit debugging as well as features required
+ by the architecture-specific subpackages. */
+
+public interface BsdDebugger extends JVMDebugger {
+ public String addressValueToString(long address) throws DebuggerException;
+ public boolean readJBoolean(long address) throws DebuggerException;
+ public byte readJByte(long address) throws DebuggerException;
+ public char readJChar(long address) throws DebuggerException;
+ public double readJDouble(long address) throws DebuggerException;
+ public float readJFloat(long address) throws DebuggerException;
+ public int readJInt(long address) throws DebuggerException;
+ public long readJLong(long address) throws DebuggerException;
+ public short readJShort(long address) throws DebuggerException;
+ public long readCInteger(long address, long numBytes, boolean isUnsigned)
+ throws DebuggerException;
+ public BsdAddress readAddress(long address) throws DebuggerException;
+ public BsdAddress readCompOopAddress(long address) throws DebuggerException;
+ public BsdOopHandle readOopHandle(long address) throws DebuggerException;
+ public BsdOopHandle readCompOopHandle(long address) throws DebuggerException;
+ public long[] getThreadIntegerRegisterSet(int lwp_id) throws DebuggerException;
+ public long getAddressValue(Address addr) throws DebuggerException;
+ public Address newAddress(long value) throws DebuggerException;
+
+ // For BsdCDebugger
+ public List getThreadList();
+ public List getLoadObjectList();
+ public ClosestSymbol lookup(long address);
+
+ // NOTE: this interface implicitly contains the following methods:
+ // From the Debugger interface via JVMDebugger
+ // public void attach(int processID) throws DebuggerException;
+ // public void attach(String executableName, String coreFileName) throws DebuggerException;
+ // public boolean detach();
+ // public Address parseAddress(String addressString) throws NumberFormatException;
+ // public String getOS();
+ // public String getCPU();
+ // From the SymbolLookup interface via Debugger and JVMDebugger
+ // public Address lookup(String objectName, String symbol);
+ // public OopHandle lookupOop(String objectName, String symbol);
+ // From the JVMDebugger interface
+ // public void configureJavaPrimitiveTypeSizes(long jbooleanSize,
+ // long jbyteSize,
+ // long jcharSize,
+ // long jdoubleSize,
+ // long jfloatSize,
+ // long jintSize,
+ // long jlongSize,
+ // long jshortSize);
+ // From the ThreadAccess interface via Debugger and JVMDebugger
+ // public ThreadProxy getThreadForIdentifierAddress(Address addr);
+}
diff --git a/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java
new file mode 100644
index 000000000..ce508e619
--- /dev/null
+++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java
@@ -0,0 +1,595 @@
+/*
+ * Copyright (c) 2002, 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot.debugger.bsd;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.debugger.x86.*;
+import sun.jvm.hotspot.debugger.cdbg.*;
+import sun.jvm.hotspot.utilities.*;
+import java.lang.reflect.*;
+
+/** <P> An implementation of the JVMDebugger interface. The basic debug
+ facilities are implemented through ptrace interface in the JNI code
+ (libsaproc.so). Library maps and symbol table management are done in
+ JNI. </P>
+
+ <P> <B>NOTE</B> that since we have the notion of fetching "Java
+ primitive types" from the remote process (which might have
+ different sizes than we expect) we have a bootstrapping
+ problem. We need to know the sizes of these types before we can
+ fetch them. The current implementation solves this problem by
+ requiring that it be configured with these type sizes before they
+ can be fetched. The readJ(Type) routines here will throw a
+ RuntimeException if they are called before the debugger is
+ configured with the Java primitive type sizes. </P> */
+
+public class BsdDebuggerLocal extends DebuggerBase implements BsdDebugger {
+ private boolean useGCC32ABI;
+ private boolean attached;
+ private long p_ps_prochandle; // native debugger handle
+ private boolean isCore;
+
+ // CDebugger support
+ private BsdCDebugger cdbg;
+
+ // threadList and loadObjectList are filled by attach0 method
+ private List threadList;
+ private List loadObjectList;
+
+ // called by native method lookupByAddress0
+ private ClosestSymbol createClosestSymbol(String name, long offset) {
+ return new ClosestSymbol(name, offset);
+ }
+
+ // called by native method attach0
+ private LoadObject createLoadObject(String fileName, long textsize,
+ long base) {
+ File f = new File(fileName);
+ Address baseAddr = newAddress(base);
+ return new SharedObject(this, fileName, f.length(), baseAddr);
+ }
+
+ // native methods
+
+ private native static void init0()
+ throws DebuggerException;
+ private native void attach0(int pid)
+ throws DebuggerException;
+ private native void attach0(String execName, String coreName)
+ throws DebuggerException;
+ private native void detach0()
+ throws DebuggerException;
+ private native long lookupByName0(String objectName, String symbol)
+ throws DebuggerException;
+ private native ClosestSymbol lookupByAddress0(long address)
+ throws DebuggerException;
+ private native long[] getThreadIntegerRegisterSet0(int lwp_id)
+ throws DebuggerException;
+ private native byte[] readBytesFromProcess0(long address, long numBytes)
+ throws DebuggerException;
+ public native static int getAddressSize() ;
+
+ // Note on Bsd threads are really processes. When target process is
+ // attached by a serviceability agent thread, only that thread can do
+ // ptrace operations on the target. This is because from kernel's point
+ // view, other threads are just separate processes and they are not
+ // attached to the target. When they attempt to make ptrace calls,
+ // an ESRCH error will be returned as kernel believes target is not
+ // being traced by the caller.
+ // To work around the problem, we use a worker thread here to handle
+ // all JNI functions that are making ptrace calls.
+
+ interface WorkerThreadTask {
+ public void doit(BsdDebuggerLocal debugger) throws DebuggerException;
+ }
+
+ class BsdDebuggerLocalWorkerThread extends Thread {
+ BsdDebuggerLocal debugger;
+ WorkerThreadTask task;
+ DebuggerException lastException;
+
+ public BsdDebuggerLocalWorkerThread(BsdDebuggerLocal debugger) {
+ this.debugger = debugger;
+ setDaemon(true);
+ }
+
+ public void run() {
+ synchronized (workerThread) {
+ for (;;) {
+ if (task != null) {
+ lastException = null;
+ try {
+ task.doit(debugger);
+ } catch (DebuggerException exp) {
+ lastException = exp;
+ }
+ task = null;
+ workerThread.notifyAll();
+ }
+
+ try {
+ workerThread.wait();
+ } catch (InterruptedException x) {}
+ }
+ }
+ }
+
+ public WorkerThreadTask execute(WorkerThreadTask task) throws DebuggerException {
+ synchronized (workerThread) {
+ this.task = task;
+ workerThread.notifyAll();
+ while (this.task != null) {
+ try {
+ workerThread.wait();
+ } catch (InterruptedException x) {}
+ }
+ if (lastException != null) {
+ throw new DebuggerException(lastException);
+ } else {
+ return task;
+ }
+ }
+ }
+ }
+
+ private BsdDebuggerLocalWorkerThread workerThread = null;
+
+ //----------------------------------------------------------------------
+ // Implementation of Debugger interface
+ //
+
+ /** <P> machDesc may not be null. </P>
+
+ <P> useCache should be set to true if debugging is being done
+ locally, and to false if the debugger is being created for the
+ purpose of supporting remote debugging. </P> */
+ public BsdDebuggerLocal(MachineDescription machDesc,
+ boolean useCache) throws DebuggerException {
+ this.machDesc = machDesc;
+ utils = new DebuggerUtilities(machDesc.getAddressSize(),
+ machDesc.isBigEndian()) {
+ public void checkAlignment(long address, long alignment) {
+ // Need to override default checkAlignment because we need to
+ // relax alignment constraints on Bsd/x86
+ if ( (address % alignment != 0)
+ &&(alignment != 8 || address % 4 != 0)) {
+ throw new UnalignedAddressException(
+ "Trying to read at address: "
+ + addressValueToString(address)
+ + " with alignment: " + alignment,
+ address);
+ }
+ }
+ };
+
+ if (useCache) {
+ // FIXME: re-test necessity of cache on Bsd, where data
+ // fetching is faster
+ // Cache portion of the remote process's address space.
+ // Fetching data over the socket connection to dbx is slow.
+ // Might be faster if we were using a binary protocol to talk to
+ // dbx, but would have to test. For now, this cache works best
+ // if it covers the entire heap of the remote process. FIXME: at
+ // least should make this tunable from the outside, i.e., via
+ // the UI. This is a cache of 4096 4K pages, or 16 MB. The page
+ // size must be adjusted to be the hardware's page size.
+ // (FIXME: should pick this up from the debugger.)
+ if (getCPU().equals("ia64")) {
+ initCache(16384, parseCacheNumPagesProperty(1024));
+ } else {
+ initCache(4096, parseCacheNumPagesProperty(4096));
+ }
+ }
+
+ workerThread = new BsdDebuggerLocalWorkerThread(this);
+ workerThread.start();
+ }
+
+ /** From the Debugger interface via JVMDebugger */
+ public boolean hasProcessList() throws DebuggerException {
+ return false;
+ }
+
+ /** From the Debugger interface via JVMDebugger */
+ public List getProcessList() throws DebuggerException {
+ throw new DebuggerException("getProcessList not implemented yet");
+ }
+
+ private void checkAttached() throws DebuggerException {
+ if (attached) {
+ if (isCore) {
+ throw new DebuggerException("attached to a core dump already");
+ } else {
+ throw new DebuggerException("attached to a process already");
+ }
+ }
+ }
+
+ private void requireAttach() {
+ if (! attached) {
+ throw new RuntimeException("not attached to a process or a core!");
+ }
+ }
+
+ /* called from attach methods */
+ private void findABIVersion() throws DebuggerException {
+ if (lookupByName0("libjvm.so", "__vt_10JavaThread") != 0 ||
+ lookupByName0("libjvm_g.so", "__vt_10JavaThread") != 0) {
+ // old C++ ABI
+ useGCC32ABI = false;
+ } else {
+ // new C++ ABI
+ useGCC32ABI = true;
+ }
+ }
+
+ /** From the Debugger interface via JVMDebugger */
+ public synchronized void attach(int processID) throws DebuggerException {
+ checkAttached();
+ threadList = new ArrayList();
+ loadObjectList = new ArrayList();
+ class AttachTask implements WorkerThreadTask {
+ int pid;
+ public void doit(BsdDebuggerLocal debugger) {
+ debugger.attach0(pid);
+ debugger.attached = true;
+ debugger.isCore = false;
+ findABIVersion();
+ }
+ }
+
+ AttachTask task = new AttachTask();
+ task.pid = processID;
+ workerThread.execute(task);
+ }
+
+ /** From the Debugger interface via JVMDebugger */
+ public synchronized void attach(String execName, String coreName) {
+ checkAttached();
+ threadList = new ArrayList();
+ loadObjectList = new ArrayList();
+ attach0(execName, coreName);
+ attached = true;
+ isCore = true;
+ findABIVersion();
+ }
+
+ /** From the Debugger interface via JVMDebugger */
+ public synchronized boolean detach() {
+ if (!attached) {
+ return false;
+ }
+
+ threadList = null;
+ loadObjectList = null;
+
+ if (isCore) {
+ detach0();
+ attached = false;
+ return true;
+ } else {
+ class DetachTask implements WorkerThreadTask {
+ boolean result = false;
+
+ public void doit(BsdDebuggerLocal debugger) {
+ debugger.detach0();
+ debugger.attached = false;
+ result = true;
+ }
+ }
+
+ DetachTask task = new DetachTask();
+ workerThread.execute(task);
+ return task.result;
+ }
+ }
+
+ /** From the Debugger interface via JVMDebugger */
+ public Address parseAddress(String addressString)
+ throws NumberFormatException {
+ long addr = utils.scanAddress(addressString);
+ if (addr == 0) {
+ return null;
+ }
+ return new BsdAddress(this, addr);
+ }
+
+ /** From the Debugger interface via JVMDebugger */
+ public String getOS() {
+ return PlatformInfo.getOS();
+ }
+
+ /** From the Debugger interface via JVMDebugger */
+ public String getCPU() {
+ return PlatformInfo.getCPU();
+ }
+
+ public boolean hasConsole() throws DebuggerException {
+ return false;
+ }
+
+ public String consoleExecuteCommand(String cmd) throws DebuggerException {
+ throw new DebuggerException("No debugger console available on Bsd");
+ }
+
+ public String getConsolePrompt() throws DebuggerException {
+ return null;
+ }
+
+ /* called from lookup */
+ private long handleGCC32ABI(long addr, String symbol) throws DebuggerException {
+ if (useGCC32ABI && symbol.startsWith("_ZTV")) {
+ return addr + (2 * machDesc.getAddressSize());
+ } else {
+ return addr;
+ }
+ }
+
+ /** From the SymbolLookup interface via Debugger and JVMDebugger */
+ public synchronized Address lookup(String objectName, String symbol) {
+ requireAttach();
+ if (!attached) {
+ return null;
+ }
+
+ if (isCore) {
+ long addr = lookupByName0(objectName, symbol);
+ return (addr == 0)? null : new BsdAddress(this, handleGCC32ABI(addr, symbol));
+ } else {
+ class LookupByNameTask implements WorkerThreadTask {
+ String objectName, symbol;
+ Address result;
+
+ public void doit(BsdDebuggerLocal debugger) {
+ long addr = debugger.lookupByName0(objectName, symbol);
+ result = (addr == 0 ? null : new BsdAddress(debugger, handleGCC32ABI(addr, symbol)));
+ }
+ }
+
+ LookupByNameTask task = new LookupByNameTask();
+ task.objectName = objectName;
+ task.symbol = symbol;
+ workerThread.execute(task);
+ return task.result;
+ }
+ }
+
+ /** From the SymbolLookup interface via Debugger and JVMDebugger */
+ public synchronized OopHandle lookupOop(String objectName, String symbol) {
+ Address addr = lookup(objectName, symbol);
+ if (addr == null) {
+ return null;
+ }
+ return addr.addOffsetToAsOopHandle(0);
+ }
+
+ /** From the Debugger interface */
+ public MachineDescription getMachineDescription() {
+ return machDesc;
+ }
+
+ //----------------------------------------------------------------------
+ // Implementation of ThreadAccess interface
+ //
+
+ /** From the ThreadAccess interface via Debugger and JVMDebugger */
+ public ThreadProxy getThreadForIdentifierAddress(Address addr) {
+ return new BsdThread(this, addr);
+ }
+
+ /** From the ThreadAccess interface via Debugger and JVMDebugger */
+ public ThreadProxy getThreadForThreadId(long id) {
+ return new BsdThread(this, id);
+ }
+
+ //----------------------------------------------------------------------
+ // Internal routines (for implementation of BsdAddress).
+ // These must not be called until the MachineDescription has been set up.
+ //
+
+ /** From the BsdDebugger interface */
+ public String addressValueToString(long address) {
+ return utils.addressValueToString(address);
+ }
+
+ /** From the BsdDebugger interface */
+ public BsdAddress readAddress(long address)
+ throws UnmappedAddressException, UnalignedAddressException {
+ long value = readAddressValue(address);
+ return (value == 0 ? null : new BsdAddress(this, value));
+ }
+ public BsdAddress readCompOopAddress(long address)
+ throws UnmappedAddressException, UnalignedAddressException {
+ long value = readCompOopAddressValue(address);
+ return (value == 0 ? null : new BsdAddress(this, value));
+ }
+
+ /** From the BsdDebugger interface */
+ public BsdOopHandle readOopHandle(long address)
+ throws UnmappedAddressException, UnalignedAddressException,
+ NotInHeapException {
+ long value = readAddressValue(address);
+ return (value == 0 ? null : new BsdOopHandle(this, value));
+ }
+ public BsdOopHandle readCompOopHandle(long address)
+ throws UnmappedAddressException, UnalignedAddressException,
+ NotInHeapException {
+ long value = readCompOopAddressValue(address);
+ return (value == 0 ? null : new BsdOopHandle(this, value));
+ }
+
+ //----------------------------------------------------------------------
+ // Thread context access
+ //
+
+ public synchronized long[] getThreadIntegerRegisterSet(int lwp_id)
+ throws DebuggerException {
+ requireAttach();
+ if (isCore) {
+ return getThreadIntegerRegisterSet0(lwp_id);
+ } else {
+ class GetThreadIntegerRegisterSetTask implements WorkerThreadTask {
+ int lwp_id;
+ long[] result;
+ public void doit(BsdDebuggerLocal debugger) {
+ result = debugger.getThreadIntegerRegisterSet0(lwp_id);
+ }
+ }
+
+ GetThreadIntegerRegisterSetTask task = new GetThreadIntegerRegisterSetTask();
+ task.lwp_id = lwp_id;
+ workerThread.execute(task);
+ return task.result;
+ }
+ }
+
+ /** Need to override this to relax alignment checks on x86. */
+ public long readCInteger(long address, long numBytes, boolean isUnsigned)
+ throws UnmappedAddressException, UnalignedAddressException {
+ // Only slightly relaxed semantics -- this is a hack, but is
+ // necessary on x86 where it seems the compiler is
+ // putting some global 64-bit data on 32-bit boundaries
+ if (numBytes == 8) {
+ utils.checkAlignment(address, 4);
+ } else {
+ utils.checkAlignment(address, numBytes);
+ }
+ byte[] data = readBytes(address, numBytes);
+ return utils.dataToCInteger(data, isUnsigned);
+ }
+
+ // Overridden from DebuggerBase because we need to relax alignment
+ // constraints on x86
+ public long readJLong(long address)
+ throws UnmappedAddressException, UnalignedAddressException {
+ utils.checkAlignment(address, jintSize);
+ byte[] data = readBytes(address, jlongSize);
+ return utils.dataToJLong(data, jlongSize);
+ }
+
+ //----------------------------------------------------------------------
+ // Address access. Can not be package private, but should only be
+ // accessed by the architecture-specific subpackages.
+
+ /** From the BsdDebugger interface */
+ public long getAddressValue(Address addr) {
+ if (addr == null) return 0;
+ return ((BsdAddress) addr).getValue();
+ }
+
+ /** From the BsdDebugger interface */
+ public Address newAddress(long value) {
+ if (value == 0) return null;
+ return new BsdAddress(this, value);
+ }
+
+ /** From the BsdCDebugger interface */
+ public List/*<ThreadProxy>*/ getThreadList() {
+ requireAttach();
+ return threadList;
+ }
+
+ /** From the BsdCDebugger interface */
+ public List/*<LoadObject>*/ getLoadObjectList() {
+ requireAttach();
+ return loadObjectList;
+ }
+
+ /** From the BsdCDebugger interface */
+ public synchronized ClosestSymbol lookup(long addr) {
+ requireAttach();
+ if (isCore) {
+ return lookupByAddress0(addr);
+ } else {
+ class LookupByAddressTask implements WorkerThreadTask {
+ long addr;
+ ClosestSymbol result;
+
+ public void doit(BsdDebuggerLocal debugger) {
+ result = debugger.lookupByAddress0(addr);
+ }
+ }
+
+ LookupByAddressTask task = new LookupByAddressTask();
+ task.addr = addr;
+ workerThread.execute(task);
+ return task.result;
+ }
+ }
+
+ public CDebugger getCDebugger() {
+ if (cdbg == null) {
+ String cpu = getCPU();
+ if (cpu.equals("ia64") ) {
+ // IA-64 is not supported because of stack-walking issues
+ return null;
+ }
+ cdbg = new BsdCDebugger(this);
+ }
+ return cdbg;
+ }
+
+ /** This reads bytes from the remote process. */
+ public synchronized ReadResult readBytesFromProcess(long address,
+ long numBytes) throws UnmappedAddressException, DebuggerException {
+ requireAttach();
+ if (isCore) {
+ byte[] res = readBytesFromProcess0(address, numBytes);
+ return (res != null)? new ReadResult(res) : new ReadResult(address);
+ } else {
+ class ReadBytesFromProcessTask implements WorkerThreadTask {
+ long address, numBytes;
+ ReadResult result;
+ public void doit(BsdDebuggerLocal debugger) {
+ byte[] res = debugger.readBytesFromProcess0(address, numBytes);
+ if (res != null)
+ result = new ReadResult(res);
+ else
+ result = new ReadResult(address);
+ }
+ }
+
+ ReadBytesFromProcessTask task = new ReadBytesFromProcessTask();
+ task.address = address;
+ task.numBytes = numBytes;
+ workerThread.execute(task);
+ return task.result;
+ }
+ }
+
+ public void writeBytesToProcess(long address, long numBytes, byte[] data)
+ throws UnmappedAddressException, DebuggerException {
+ // FIXME
+ throw new DebuggerException("Unimplemented");
+ }
+
+ static {
+ System.loadLibrary("saproc");
+ init0();
+ }
+}
diff --git a/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdOopHandle.java b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdOopHandle.java
new file mode 100644
index 000000000..9df0e2f5c
--- /dev/null
+++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdOopHandle.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot.debugger.bsd;
+
+import sun.jvm.hotspot.debugger.*;
+
+class BsdOopHandle extends BsdAddress implements OopHandle {
+ BsdOopHandle(BsdDebugger debugger, long addr) {
+ super(debugger, addr);
+ }
+
+ public boolean equals(Object arg) {
+ if (arg == null) {
+ return false;
+ }
+
+ if (!(arg instanceof BsdOopHandle)) {
+ return false;
+ }
+
+ return (addr == ((BsdAddress) arg).addr);
+ }
+
+ public Address addOffsetTo (long offset) throws UnsupportedOperationException {
+ throw new UnsupportedOperationException("addOffsetTo not applicable to OopHandles (interior object pointers not allowed)");
+ }
+
+ public Address andWithMask(long mask) throws UnsupportedOperationException {
+ throw new UnsupportedOperationException("andWithMask not applicable to OopHandles (i.e., anything but C addresses)");
+ }
+
+ public Address orWithMask(long mask) throws UnsupportedOperationException {
+ throw new UnsupportedOperationException("orWithMask not applicable to OopHandles (i.e., anything but C addresses)");
+ }
+
+ public Address xorWithMask(long mask) throws UnsupportedOperationException {
+ throw new UnsupportedOperationException("xorWithMask not applicable to OopHandles (i.e., anything but C addresses)");
+ }
+}
diff --git a/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThread.java b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThread.java
new file mode 100644
index 000000000..b7c507c29
--- /dev/null
+++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThread.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot.debugger.bsd;
+
+import sun.jvm.hotspot.debugger.*;
+
+class BsdThread implements ThreadProxy {
+ private BsdDebugger debugger;
+ private int lwp_id;
+
+ /** The address argument must be the address of the _thread_id in the
+ OSThread. It's value is result ::gettid() call. */
+ BsdThread(BsdDebugger debugger, Address addr) {
+ this.debugger = debugger;
+ // FIXME: size of data fetched here should be configurable.
+ // However, making it so would produce a dependency on the "types"
+ // package from the debugger package, which is not desired.
+ this.lwp_id = (int) addr.getCIntegerAt(0, 4, true);
+ }
+
+ BsdThread(BsdDebugger debugger, long id) {
+ this.debugger = debugger;
+ this.lwp_id = (int) id;
+ }
+
+ public boolean equals(Object obj) {
+ if ((obj == null) || !(obj instanceof BsdThread)) {
+ return false;
+ }
+
+ return (((BsdThread) obj).lwp_id == lwp_id);
+ }
+
+ public int hashCode() {
+ return lwp_id;
+ }
+
+ public String toString() {
+ return Integer.toString(lwp_id);
+ }
+
+ public ThreadContext getContext() throws IllegalThreadStateException {
+ long[] data = debugger.getThreadIntegerRegisterSet(lwp_id);
+ ThreadContext context = BsdThreadContextFactory.createThreadContext(debugger);
+ for (int i = 0; i < data.length; i++) {
+ context.setRegister(i, data[i]);
+ }
+ return context;
+ }
+
+ public boolean canSetContext() throws DebuggerException {
+ return false;
+ }
+
+ public void setContext(ThreadContext context)
+ throws IllegalThreadStateException, DebuggerException {
+ throw new DebuggerException("Unimplemented");
+ }
+}
diff --git a/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThreadContextFactory.java b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThreadContextFactory.java
new file mode 100644
index 000000000..8c13adade
--- /dev/null
+++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThreadContextFactory.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2002, 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot.debugger.bsd;
+
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.debugger.bsd.amd64.*;
+import sun.jvm.hotspot.debugger.bsd.x86.*;
+
+class BsdThreadContextFactory {
+ static ThreadContext createThreadContext(BsdDebugger dbg) {
+ String cpu = dbg.getCPU();
+ if (cpu.equals("x86")) {
+ return new BsdX86ThreadContext(dbg);
+ } else if (cpu.equals("amd64")) {
+ return new BsdAMD64ThreadContext(dbg);
+ } else {
+ throw new RuntimeException("cpu " + cpu + " is not yet supported");
+ }
+ }
+}
diff --git a/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/SharedObject.java b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/SharedObject.java
new file mode 100644
index 000000000..2f72f7d5d
--- /dev/null
+++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/SharedObject.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot.debugger.bsd;
+
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.debugger.cdbg.*;
+import sun.jvm.hotspot.debugger.posix.*;
+
+/** A Object can represent either a .so or an a.out file. */
+
+class SharedObject extends DSO {
+ SharedObject(BsdDebugger dbg, String filename, long size, Address relocation) {
+ super(filename, size, relocation);
+ this.dbg = dbg;
+ }
+
+ protected Address newAddress(long address) {
+ return dbg.newAddress(address);
+ }
+
+ protected long getAddressValue(Address addr) {
+ return dbg.getAddressValue(addr);
+ }
+
+ private BsdDebugger dbg;
+}
diff --git a/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/amd64/BsdAMD64CFrame.java b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/amd64/BsdAMD64CFrame.java
new file mode 100644
index 000000000..b27a53990
--- /dev/null
+++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/amd64/BsdAMD64CFrame.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot.debugger.bsd.amd64;
+
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.debugger.bsd.*;
+import sun.jvm.hotspot.debugger.cdbg.*;
+import sun.jvm.hotspot.debugger.cdbg.basic.*;
+
+final public class BsdAMD64CFrame extends BasicCFrame {
+ public BsdAMD64CFrame(BsdDebugger dbg, Address rbp, Address rip) {
+ super(dbg.getCDebugger());
+ this.rbp = rbp;
+ this.rip = rip;
+ this.dbg = dbg;
+ }
+
+ // override base class impl to avoid ELF parsing
+ public ClosestSymbol closestSymbolToPC() {
+ // try native lookup in debugger.
+ return dbg.lookup(dbg.getAddressValue(pc()));
+ }
+
+ public Address pc() {
+ return rip;
+ }
+
+ public Address localVariableBase() {
+ return rbp;
+ }
+
+ public CFrame sender() {
+ if (rbp == null) {
+ return null;
+ }
+
+ Address nextRBP = rbp.getAddressAt( 0 * ADDRESS_SIZE);
+ if (nextRBP == null) {
+ return null;
+ }
+ Address nextPC = rbp.getAddressAt( 1 * ADDRESS_SIZE);
+ if (nextPC == null) {
+ return null;
+ }
+ return new BsdAMD64CFrame(dbg, nextRBP, nextPC);
+ }
+
+ // package/class internals only
+ private static final int ADDRESS_SIZE = 8;
+ private Address rip;
+ private Address rbp;
+ private BsdDebugger dbg;
+}
diff --git a/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/amd64/BsdAMD64ThreadContext.java b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/amd64/BsdAMD64ThreadContext.java
new file mode 100644
index 000000000..a9ebf8353
--- /dev/null
+++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/amd64/BsdAMD64ThreadContext.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot.debugger.bsd.amd64;
+
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.debugger.amd64.*;
+import sun.jvm.hotspot.debugger.bsd.*;
+
+public class BsdAMD64ThreadContext extends AMD64ThreadContext {
+ private BsdDebugger debugger;
+
+ public BsdAMD64ThreadContext(BsdDebugger debugger) {
+ super();
+ this.debugger = debugger;
+ }
+
+ public void setRegisterAsAddress(int index, Address value) {
+ setRegister(index, debugger.getAddressValue(value));
+ }
+
+ public Address getRegisterAsAddress(int index) {
+ return debugger.newAddress(getRegister(index));
+ }
+}
diff --git a/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/x86/BsdX86CFrame.java b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/x86/BsdX86CFrame.java
new file mode 100644
index 000000000..40292b921
--- /dev/null
+++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/x86/BsdX86CFrame.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot.debugger.bsd.x86;
+
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.debugger.bsd.*;
+import sun.jvm.hotspot.debugger.cdbg.*;
+import sun.jvm.hotspot.debugger.cdbg.basic.*;
+
+final public class BsdX86CFrame extends BasicCFrame {
+ // package/class internals only
+ public BsdX86CFrame(BsdDebugger dbg, Address ebp, Address pc) {
+ super(dbg.getCDebugger());
+ this.ebp = ebp;
+ this.pc = pc;
+ this.dbg = dbg;
+ }
+
+ // override base class impl to avoid ELF parsing
+ public ClosestSymbol closestSymbolToPC() {
+ // try native lookup in debugger.
+ return dbg.lookup(dbg.getAddressValue(pc()));
+ }
+
+ public Address pc() {
+ return pc;
+ }
+
+ public Address localVariableBase() {
+ return ebp;
+ }
+
+ public CFrame sender() {
+ if (ebp == null) {
+ return null;
+ }
+
+ Address nextEBP = ebp.getAddressAt( 0 * ADDRESS_SIZE);
+ if (nextEBP == null) {
+ return null;
+ }
+ Address nextPC = ebp.getAddressAt( 1 * ADDRESS_SIZE);
+ if (nextPC == null) {
+ return null;
+ }
+ return new BsdX86CFrame(dbg, nextEBP, nextPC);
+ }
+
+ private static final int ADDRESS_SIZE = 4;
+ private Address pc;
+ private Address ebp;
+ private BsdDebugger dbg;
+}
diff --git a/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/x86/BsdX86ThreadContext.java b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/x86/BsdX86ThreadContext.java
new file mode 100644
index 000000000..8eaca2b7d
--- /dev/null
+++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/x86/BsdX86ThreadContext.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot.debugger.bsd.x86;
+
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.debugger.x86.*;
+import sun.jvm.hotspot.debugger.bsd.*;
+
+public class BsdX86ThreadContext extends X86ThreadContext {
+ private BsdDebugger debugger;
+
+ public BsdX86ThreadContext(BsdDebugger debugger) {
+ super();
+ this.debugger = debugger;
+ }
+
+ public void setRegisterAsAddress(int index, Address value) {
+ setRegister(index, debugger.getAddressValue(value));
+ }
+
+ public Address getRegisterAsAddress(int index) {
+ return debugger.newAddress(getRegister(index));
+ }
+}
diff --git a/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java b/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java
index 9ff98e2aa..87de9700d 100644
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java
+++ b/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java
@@ -44,14 +44,14 @@ public class InstanceKlass extends Klass {
}
// field offset constants
- public static int ACCESS_FLAGS_OFFSET;
- public static int NAME_INDEX_OFFSET;
- public static int SIGNATURE_INDEX_OFFSET;
- public static int INITVAL_INDEX_OFFSET;
- public static int LOW_OFFSET;
- public static int HIGH_OFFSET;
- public static int GENERIC_SIGNATURE_INDEX_OFFSET;
- public static int FIELD_SLOTS;
+ private static int ACCESS_FLAGS_OFFSET;
+ private static int NAME_INDEX_OFFSET;
+ private static int SIGNATURE_INDEX_OFFSET;
+ private static int INITVAL_INDEX_OFFSET;
+ private static int LOW_OFFSET;
+ private static int HIGH_OFFSET;
+ private static int GENERIC_SIGNATURE_INDEX_OFFSET;
+ private static int FIELD_SLOTS;
public static int IMPLEMENTORS_LIMIT;
// ClassState constants
@@ -122,6 +122,13 @@ public class InstanceKlass extends Klass {
InstanceKlass(OopHandle handle, ObjectHeap heap) {
super(handle, heap);
+ if (getJavaFieldsCount() != getAllFieldsCount()) {
+ // Exercise the injected field logic
+ for (int i = getJavaFieldsCount(); i < getAllFieldsCount(); i++) {
+ getFieldName(i);
+ getFieldSignature(i);
+ }
+ }
}
private static OopField arrayKlasses;
@@ -253,24 +260,51 @@ public class InstanceKlass extends Klass {
return getFields().getShortAt(index * FIELD_SLOTS + ACCESS_FLAGS_OFFSET);
}
+ public short getFieldNameIndex(int index) {
+ if (index >= getJavaFieldsCount()) throw new IndexOutOfBoundsException("not a Java field;");
+ return getFields().getShortAt(index * FIELD_SLOTS + NAME_INDEX_OFFSET);
+ }
+
public Symbol getFieldName(int index) {
int nameIndex = getFields().getShortAt(index * FIELD_SLOTS + NAME_INDEX_OFFSET);
- return getConstants().getSymbolAt(nameIndex);
+ if (index < getJavaFieldsCount()) {
+ return getConstants().getSymbolAt(nameIndex);
+ } else {
+ return vmSymbols.symbolAt(nameIndex);
+ }
+ }
+
+ public short getFieldSignatureIndex(int index) {
+ if (index >= getJavaFieldsCount()) throw new IndexOutOfBoundsException("not a Java field;");
+ return getFields().getShortAt(index * FIELD_SLOTS + SIGNATURE_INDEX_OFFSET);
}
public Symbol getFieldSignature(int index) {
int signatureIndex = getFields().getShortAt(index * FIELD_SLOTS + SIGNATURE_INDEX_OFFSET);
- return getConstants().getSymbolAt(signatureIndex);
+ if (index < getJavaFieldsCount()) {
+ return getConstants().getSymbolAt(signatureIndex);
+ } else {
+ return vmSymbols.symbolAt(signatureIndex);
+ }
+ }
+
+ public short getFieldGenericSignatureIndex(int index) {
+ return getFields().getShortAt(index * FIELD_SLOTS + GENERIC_SIGNATURE_INDEX_OFFSET);
}
public Symbol getFieldGenericSignature(int index) {
- short genericSignatureIndex = getFields().getShortAt(index * FIELD_SLOTS + GENERIC_SIGNATURE_INDEX_OFFSET);
+ short genericSignatureIndex = getFieldGenericSignatureIndex(index);
if (genericSignatureIndex != 0) {
return getConstants().getSymbolAt(genericSignatureIndex);
}
return null;
}
+ public short getFieldInitialValueIndex(int index) {
+ if (index >= getJavaFieldsCount()) throw new IndexOutOfBoundsException("not a Java field;");
+ return getFields().getShortAt(index * FIELD_SLOTS + INITVAL_INDEX_OFFSET);
+ }
+
public int getFieldOffset(int index) {
TypeArray fields = getFields();
return VM.getVM().buildIntFromShorts(fields.getShortAt(index * FIELD_SLOTS + LOW_OFFSET),
@@ -288,7 +322,7 @@ public class InstanceKlass extends Klass {
public Klass getImplementor(int i) { return (Klass) implementors[i].getValue(this); }
public TypeArray getFields() { return (TypeArray) fields.getValue(this); }
public int getJavaFieldsCount() { return (int) javaFieldsCount.getValue(this); }
- public int getAllFieldsCount() { return (int)getFields().getLength(); }
+ public int getAllFieldsCount() { return (int)getFields().getLength() / FIELD_SLOTS; }
public ConstantPool getConstants() { return (ConstantPool) constants.getValue(this); }
public Oop getClassLoader() { return classLoader.getValue(this); }
public Oop getProtectionDomain() { return protectionDomain.getValue(this); }
@@ -511,7 +545,6 @@ public class InstanceKlass extends Klass {
}
void iterateStaticFieldsInternal(OopVisitor visitor) {
- TypeArray fields = getFields();
int length = getJavaFieldsCount();
for (int index = 0; index < length; index++) {
short accessFlags = getFieldAccessFlags(index);
@@ -541,8 +574,6 @@ public class InstanceKlass extends Klass {
if (getSuper() != null) {
((InstanceKlass) getSuper()).iterateNonStaticFields(visitor, obj);
}
- TypeArray fields = getFields();
-
int length = getJavaFieldsCount();
for (int index = 0; index < length; index++) {
short accessFlags = getFieldAccessFlags(index);
@@ -556,9 +587,7 @@ public class InstanceKlass extends Klass {
/** Field access by name. */
public Field findLocalField(Symbol name, Symbol sig) {
- TypeArray fields = getFields();
- int length = (int) fields.getLength();
- ConstantPool cp = getConstants();
+ int length = getJavaFieldsCount();
for (int i = 0; i < length; i++) {
Symbol f_name = getFieldName(i);
Symbol f_sig = getFieldSignature(i);
@@ -648,8 +677,6 @@ public class InstanceKlass extends Klass {
public List getImmediateFields() {
// A list of Fields for each field declared in this class/interface,
// not including inherited fields.
- TypeArray fields = getFields();
-
int length = getJavaFieldsCount();
List immediateFields = new ArrayList(length);
for (int index = 0; index < length; index++) {
@@ -839,7 +866,6 @@ public class InstanceKlass extends Klass {
// Creates new field from index in fields TypeArray
private Field newField(int index) {
- TypeArray fields = getFields();
FieldType type = new FieldType(getFieldSignature(index));
if (type.isOop()) {
if (VM.getVM().isCompressedOopsEnabled()) {
diff --git a/agent/src/share/classes/sun/jvm/hotspot/runtime/Threads.java b/agent/src/share/classes/sun/jvm/hotspot/runtime/Threads.java
index d90d08bd7..44ce89804 100644
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/Threads.java
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/Threads.java
@@ -37,6 +37,8 @@ import sun.jvm.hotspot.runtime.linux_x86.LinuxX86JavaThreadPDAccess;
import sun.jvm.hotspot.runtime.linux_ia64.LinuxIA64JavaThreadPDAccess;
import sun.jvm.hotspot.runtime.linux_amd64.LinuxAMD64JavaThreadPDAccess;
import sun.jvm.hotspot.runtime.linux_sparc.LinuxSPARCJavaThreadPDAccess;
+import sun.jvm.hotspot.runtime.bsd_x86.BsdX86JavaThreadPDAccess;
+import sun.jvm.hotspot.runtime.bsd_amd64.BsdAMD64JavaThreadPDAccess;
import sun.jvm.hotspot.utilities.*;
public class Threads {
@@ -90,7 +92,12 @@ public class Threads {
} else if (cpu.equals("sparc")) {
access = new LinuxSPARCJavaThreadPDAccess();
}
-
+ } else if (os.equals("bsd")) {
+ if (cpu.equals("x86")) {
+ access = new BsdX86JavaThreadPDAccess();
+ } else if (cpu.equals("amd64")) {
+ access = new BsdAMD64JavaThreadPDAccess();
+ }
}
if (access == null) {
diff --git a/agent/src/share/classes/sun/jvm/hotspot/runtime/bsd/BsdSignals.java b/agent/src/share/classes/sun/jvm/hotspot/runtime/bsd/BsdSignals.java
new file mode 100644
index 000000000..6887c4783
--- /dev/null
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/bsd/BsdSignals.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot.runtime.bsd;
+
+public class BsdSignals {
+ private static String[] signalNames = {
+ "", /* No signal 0 */
+ "SIGHUP", /* hangup */
+ "SIGINT", /* interrupt */
+ "SIGQUIT", /* quit */
+ "SIGILL", /* illegal instr. (not reset when caught) */
+ "SIGTRAP", /* trace trap (not reset when caught) */
+ "SIGABRT", /* abort() */
+ "SIGEMT", /* EMT instruction */
+ "SIGFPE", /* floating point exception */
+ "SIGKILL", /* kill (cannot be caught or ignored) */
+ "SIGBUS", /* bus error */
+ "SIGSEGV", /* segmentation violation */
+ "SIGSYS", /* non-existent system call invoked */
+ "SIGPIPE", /* write on a pipe with no one to read it */
+ "SIGALRM", /* alarm clock */
+ "SIGTERM", /* software termination signal from kill */
+ "SIGURG", /* urgent condition on IO channel */
+ "SIGSTOP", /* sendable stop signal not from tty */
+ "SIGTSTP", /* stop signal from tty */
+ "SIGCONT", /* continue a stopped process */
+ "SIGCHLD", /* to parent on child stop or exit */
+ "SIGTTIN", /* to readers pgrp upon background tty read */
+ "SIGTTOU", /* like TTIN if (tp->t_local&LTOSTOP) */
+ "SIGIO", /* input/output possible signal */
+ "SIGXCPU", /* exceeded CPU time limit */
+ "SIGXFSZ", /* exceeded file size limit */
+ "SIGVTALRM", /* virtual time alarm */
+ "SIGPROF", /* profiling time alarm */
+ "SIGWINCH", /* window size changes */
+ "SIGINFO", /* information request */
+ "SIGUSR1", /* user defined signal 1 */
+ "SIGUSR2" /* user defined signal 2 */
+ };
+
+ public static String getSignalName(int sigNum) {
+ if ((sigNum <= 0) || (sigNum >= signalNames.length)) {
+ // Probably best to fail in a non-destructive way
+ return "<Error: Illegal signal number " + sigNum + ">";
+ }
+ return signalNames[sigNum];
+ }
+}
diff --git a/agent/src/share/classes/sun/jvm/hotspot/runtime/bsd_amd64/BsdAMD64JavaThreadPDAccess.java b/agent/src/share/classes/sun/jvm/hotspot/runtime/bsd_amd64/BsdAMD64JavaThreadPDAccess.java
new file mode 100644
index 000000000..c0de1381c
--- /dev/null
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/bsd_amd64/BsdAMD64JavaThreadPDAccess.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot.runtime.bsd_amd64;
+
+import java.io.*;
+import java.util.*;
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.debugger.amd64.*;
+import sun.jvm.hotspot.runtime.*;
+import sun.jvm.hotspot.runtime.amd64.*;
+import sun.jvm.hotspot.runtime.x86.*;
+import sun.jvm.hotspot.types.*;
+import sun.jvm.hotspot.utilities.*;
+
+public class BsdAMD64JavaThreadPDAccess implements JavaThreadPDAccess {
+ private static AddressField lastJavaFPField;
+ private static AddressField osThreadField;
+
+ // Field from OSThread
+ private static CIntegerField osThreadThreadIDField;
+
+ // This is currently unneeded but is being kept in case we change
+ // the currentFrameGuess algorithm
+ private static final long GUESS_SCAN_RANGE = 128 * 1024;
+
+ static {
+ VM.registerVMInitializedObserver(new Observer() {
+ public void update(Observable o, Object data) {
+ initialize(VM.getVM().getTypeDataBase());
+ }
+ });
+ }
+
+ private static synchronized void initialize(TypeDataBase db) {
+ Type type = db.lookupType("JavaThread");
+ osThreadField = type.getAddressField("_osthread");
+
+ Type anchorType = db.lookupType("JavaFrameAnchor");
+ lastJavaFPField = anchorType.getAddressField("_last_Java_fp");
+
+ Type osThreadType = db.lookupType("OSThread");
+ osThreadThreadIDField = osThreadType.getCIntegerField("_thread_id");
+ }
+
+ public Address getLastJavaFP(Address addr) {
+ return lastJavaFPField.getValue(addr.addOffsetTo(sun.jvm.hotspot.runtime.JavaThread.getAnchorField().getOffset()));
+ }
+
+ public Address getLastJavaPC(Address addr) {
+ return null;
+ }
+
+ public Address getBaseOfStackPointer(Address addr) {
+ return null;
+ }
+
+ public Frame getLastFramePD(JavaThread thread, Address addr) {
+ Address fp = thread.getLastJavaFP();
+ if (fp == null) {
+ return null; // no information
+ }
+ return new X86Frame(thread.getLastJavaSP(), fp);
+ }
+
+ public RegisterMap newRegisterMap(JavaThread thread, boolean updateMap) {
+ return new X86RegisterMap(thread, updateMap);
+ }
+
+ public Frame getCurrentFrameGuess(JavaThread thread, Address addr) {
+ ThreadProxy t = getThreadProxy(addr);
+ AMD64ThreadContext context = (AMD64ThreadContext) t.getContext();
+ AMD64CurrentFrameGuess guesser = new AMD64CurrentFrameGuess(context, thread);
+ if (!guesser.run(GUESS_SCAN_RANGE)) {
+ return null;
+ }
+ if (guesser.getPC() == null) {
+ return new X86Frame(guesser.getSP(), guesser.getFP());
+ } else {
+ return new X86Frame(guesser.getSP(), guesser.getFP(), guesser.getPC());
+ }
+ }
+
+ public void printThreadIDOn(Address addr, PrintStream tty) {
+ tty.print(getThreadProxy(addr));
+ }
+
+ public void printInfoOn(Address threadAddr, PrintStream tty) {
+ tty.print("Thread id: ");
+ printThreadIDOn(threadAddr, tty);
+// tty.println("\nPostJavaState: " + getPostJavaState(threadAddr));
+ }
+
+ public Address getLastSP(Address addr) {
+ ThreadProxy t = getThreadProxy(addr);
+ AMD64ThreadContext context = (AMD64ThreadContext) t.getContext();
+ return context.getRegisterAsAddress(AMD64ThreadContext.RSP);
+ }
+
+ public ThreadProxy getThreadProxy(Address addr) {
+ // Addr is the address of the JavaThread.
+ // Fetch the OSThread (for now and for simplicity, not making a
+ // separate "OSThread" class in this package)
+ Address osThreadAddr = osThreadField.getValue(addr);
+ // Get the address of the _thread_id from the OSThread
+ Address threadIdAddr = osThreadAddr.addOffsetTo(osThreadThreadIDField.getOffset());
+
+ JVMDebugger debugger = VM.getVM().getDebugger();
+ return debugger.getThreadForIdentifierAddress(threadIdAddr);
+ }
+}
diff --git a/agent/src/share/classes/sun/jvm/hotspot/runtime/bsd_x86/BsdSignals.java b/agent/src/share/classes/sun/jvm/hotspot/runtime/bsd_x86/BsdSignals.java
new file mode 100644
index 000000000..703a09747
--- /dev/null
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/bsd_x86/BsdSignals.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot.runtime.bsd_x86;
+
+public class BsdSignals {
+ private static String[] signalNames = {
+ "", /* No signal 0 */
+ "SIGHUP", /* hangup */
+ "SIGINT", /* interrupt */
+ "SIGQUIT", /* quit */
+ "SIGILL", /* illegal instr. (not reset when caught) */
+ "SIGTRAP", /* trace trap (not reset when caught) */
+ "SIGABRT", /* abort() */
+ "SIGEMT", /* EMT instruction */
+ "SIGFPE", /* floating point exception */
+ "SIGKILL", /* kill (cannot be caught or ignored) */
+ "SIGBUS", /* bus error */
+ "SIGSEGV", /* segmentation violation */
+ "SIGSYS", /* non-existent system call invoked */
+ "SIGPIPE", /* write on a pipe with no one to read it */
+ "SIGALRM", /* alarm clock */
+ "SIGTERM", /* software termination signal from kill */
+ "SIGURG", /* urgent condition on IO channel */
+ "SIGSTOP", /* sendable stop signal not from tty */
+ "SIGTSTP", /* stop signal from tty */
+ "SIGCONT", /* continue a stopped process */
+ "SIGCHLD", /* to parent on child stop or exit */
+ "SIGTTIN", /* to readers pgrp upon background tty read */
+ "SIGTTOU", /* like TTIN if (tp->t_local&LTOSTOP) */
+ "SIGIO", /* input/output possible signal */
+ "SIGXCPU", /* exceeded CPU time limit */
+ "SIGXFSZ", /* exceeded file size limit */
+ "SIGVTALRM", /* virtual time alarm */
+ "SIGPROF", /* profiling time alarm */
+ "SIGWINCH", /* window size changes */
+ "SIGINFO", /* information request */
+ "SIGUSR1", /* user defined signal 1 */
+ "SIGUSR2" /* user defined signal 2 */
+ };
+
+ public static String getSignalName(int sigNum) {
+ if ((sigNum <= 0) || (sigNum >= signalNames.length)) {
+ // Probably best to fail in a non-destructive way
+ return "<Error: Illegal signal number " + sigNum + ">";
+ }
+ return signalNames[sigNum];
+ }
+}
diff --git a/agent/src/share/classes/sun/jvm/hotspot/runtime/bsd_x86/BsdX86JavaThreadPDAccess.java b/agent/src/share/classes/sun/jvm/hotspot/runtime/bsd_x86/BsdX86JavaThreadPDAccess.java
new file mode 100644
index 000000000..a32f0be64
--- /dev/null
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/bsd_x86/BsdX86JavaThreadPDAccess.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot.runtime.bsd_x86;
+
+import java.io.*;
+import java.util.*;
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.debugger.x86.*;
+import sun.jvm.hotspot.runtime.*;
+import sun.jvm.hotspot.runtime.x86.*;
+import sun.jvm.hotspot.types.*;
+import sun.jvm.hotspot.utilities.*;
+
+public class BsdX86JavaThreadPDAccess implements JavaThreadPDAccess {
+ private static AddressField lastJavaFPField;
+ private static AddressField osThreadField;
+
+ // Field from OSThread
+ private static CIntegerField osThreadThreadIDField;
+
+ // This is currently unneeded but is being kept in case we change
+ // the currentFrameGuess algorithm
+ private static final long GUESS_SCAN_RANGE = 128 * 1024;
+
+ static {
+ VM.registerVMInitializedObserver(new Observer() {
+ public void update(Observable o, Object data) {
+ initialize(VM.getVM().getTypeDataBase());
+ }
+ });
+ }
+
+ private static synchronized void initialize(TypeDataBase db) {
+ Type type = db.lookupType("JavaThread");
+ osThreadField = type.getAddressField("_osthread");
+
+ Type anchorType = db.lookupType("JavaFrameAnchor");
+ lastJavaFPField = anchorType.getAddressField("_last_Java_fp");
+
+ Type osThreadType = db.lookupType("OSThread");
+ osThreadThreadIDField = osThreadType.getCIntegerField("_thread_id");
+ }
+
+ public Address getLastJavaFP(Address addr) {
+ return lastJavaFPField.getValue(addr.addOffsetTo(sun.jvm.hotspot.runtime.JavaThread.getAnchorField().getOffset()));
+ }
+
+ public Address getLastJavaPC(Address addr) {
+ return null;
+ }
+
+ public Address getBaseOfStackPointer(Address addr) {
+ return null;
+ }
+
+ public Frame getLastFramePD(JavaThread thread, Address addr) {
+ Address fp = thread.getLastJavaFP();
+ if (fp == null) {
+ return null; // no information
+ }
+ return new X86Frame(thread.getLastJavaSP(), fp);
+ }
+
+ public RegisterMap newRegisterMap(JavaThread thread, boolean updateMap) {
+ return new X86RegisterMap(thread, updateMap);
+ }
+
+ public Frame getCurrentFrameGuess(JavaThread thread, Address addr) {
+ ThreadProxy t = getThreadProxy(addr);
+ X86ThreadContext context = (X86ThreadContext) t.getContext();
+ X86CurrentFrameGuess guesser = new X86CurrentFrameGuess(context, thread);
+ if (!guesser.run(GUESS_SCAN_RANGE)) {
+ return null;
+ }
+ if (guesser.getPC() == null) {
+ return new X86Frame(guesser.getSP(), guesser.getFP());
+ } else {
+ return new X86Frame(guesser.getSP(), guesser.getFP(), guesser.getPC());
+ }
+ }
+
+ public void printThreadIDOn(Address addr, PrintStream tty) {
+ tty.print(getThreadProxy(addr));
+ }
+
+ public void printInfoOn(Address threadAddr, PrintStream tty) {
+ tty.print("Thread id: ");
+ printThreadIDOn(threadAddr, tty);
+// tty.println("\nPostJavaState: " + getPostJavaState(threadAddr));
+ }
+
+ public Address getLastSP(Address addr) {
+ ThreadProxy t = getThreadProxy(addr);
+ X86ThreadContext context = (X86ThreadContext) t.getContext();
+ return context.getRegisterAsAddress(X86ThreadContext.ESP);
+ }
+
+ public ThreadProxy getThreadProxy(Address addr) {
+ // Addr is the address of the JavaThread.
+ // Fetch the OSThread (for now and for simplicity, not making a
+ // separate "OSThread" class in this package)
+ Address osThreadAddr = osThreadField.getValue(addr);
+ // Get the address of the _thread_id from the OSThread
+ Address threadIdAddr = osThreadAddr.addOffsetTo(osThreadThreadIDField.getOffset());
+
+ JVMDebugger debugger = VM.getVM().getDebugger();
+ return debugger.getThreadForIdentifierAddress(threadIdAddr);
+ }
+}
diff --git a/agent/src/share/classes/sun/jvm/hotspot/runtime/vmSymbols.java b/agent/src/share/classes/sun/jvm/hotspot/runtime/vmSymbols.java
new file mode 100644
index 000000000..650f61242
--- /dev/null
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/vmSymbols.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot.runtime;
+
+import java.io.*;
+import java.util.*;
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.memory.*;
+import sun.jvm.hotspot.oops.*;
+import sun.jvm.hotspot.runtime.*;
+import sun.jvm.hotspot.types.*;
+import sun.jvm.hotspot.utilities.*;
+
+
+public class vmSymbols {
+ static {
+ VM.registerVMInitializedObserver(new Observer() {
+ public void update(Observable o, Object data) {
+ initialize(VM.getVM().getTypeDataBase());
+ }
+ });
+ }
+
+ private static Address symbolsAddress;
+ private static int FIRST_SID;
+ private static int SID_LIMIT;
+
+ private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
+ Type type = db.lookupType("vmSymbols");
+ symbolsAddress = type.getAddressField("_symbols[0]").getStaticFieldAddress();
+ FIRST_SID = db.lookupIntConstant("vmSymbols::FIRST_SID");
+ SID_LIMIT = db.lookupIntConstant("vmSymbols::SID_LIMIT");
+ }
+
+ public static Symbol symbolAt(int id) {
+ if (id < FIRST_SID || id >= SID_LIMIT) throw new IndexOutOfBoundsException("bad SID " + id);
+ return Symbol.create(symbolsAddress.getAddressAt(id * VM.getVM().getAddressSize()));
+ }
+}
diff --git a/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java b/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java
index f5e5837e1..f4e3d7c93 100644
--- a/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java
+++ b/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java
@@ -379,23 +379,21 @@ public class ClassWriter implements /* imports */ ClassConstants
}
protected void writeFields() throws IOException {
- TypeArray fields = klass.getFields();
final int length = klass.getJavaFieldsCount();
// write number of fields
- dos.writeShort((short) (length / InstanceKlass.FIELD_SLOTS) );
+ dos.writeShort((short) length);
- if (DEBUG) debugMessage("number of fields = "
- + length/InstanceKlass.FIELD_SLOTS);
+ if (DEBUG) debugMessage("number of fields = " + length);
- for (int index = 0; index < length; index += InstanceKlass.FIELD_SLOTS) {
- short accessFlags = fields.getShortAt(index + InstanceKlass.ACCESS_FLAGS_OFFSET);
+ for (int index = 0; index < length; index++) {
+ short accessFlags = klass.getFieldAccessFlags(index);
dos.writeShort(accessFlags & (short) JVM_RECOGNIZED_FIELD_MODIFIERS);
- short nameIndex = fields.getShortAt(index + InstanceKlass.NAME_INDEX_OFFSET);
+ short nameIndex = klass.getFieldNameIndex(index);
dos.writeShort(nameIndex);
- short signatureIndex = fields.getShortAt(index + InstanceKlass.SIGNATURE_INDEX_OFFSET);
+ short signatureIndex = klass.getFieldSignatureIndex(index);
dos.writeShort(signatureIndex);
if (DEBUG) debugMessage("\tfield name = " + nameIndex + ", signature = " + signatureIndex);
@@ -404,11 +402,11 @@ public class ClassWriter implements /* imports */ ClassConstants
if (hasSyn)
fieldAttributeCount++;
- short initvalIndex = fields.getShortAt(index + InstanceKlass.INITVAL_INDEX_OFFSET);
+ short initvalIndex = klass.getFieldInitialValueIndex(index);
if (initvalIndex != 0)
fieldAttributeCount++;
- short genSigIndex = fields.getShortAt(index + InstanceKlass.GENERIC_SIGNATURE_INDEX_OFFSET);
+ short genSigIndex = klass.getFieldGenericSignatureIndex(index);
if (genSigIndex != 0)
fieldAttributeCount++;
diff --git a/agent/src/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java b/agent/src/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java
index 5e749b31a..baec86bf7 100644
--- a/agent/src/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java
+++ b/agent/src/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java
@@ -37,6 +37,14 @@ public class PlatformInfo {
return "solaris";
} else if (os.equals("Linux")) {
return "linux";
+ } else if (os.equals("FreeBSD")) {
+ return "bsd";
+ } else if (os.equals("NetBSD")) {
+ return "bsd";
+ } else if (os.equals("OpenBSD")) {
+ return "bsd";
+ } else if (os.equals("Darwin")) {
+ return "bsd";
} else if (os.startsWith("Windows")) {
return "win32";
} else {
diff --git a/make/Makefile b/make/Makefile
index dd20eeee3..325ca89bf 100644
--- a/make/Makefile
+++ b/make/Makefile
@@ -323,28 +323,28 @@ endif
ifneq ($(OSNAME),windows)
ifeq ($(ZERO_BUILD), true)
ifeq ($(SHARK_BUILD), true)
-$(EXPORT_JRE_LIB_ARCH_DIR)/%.so: $(SHARK_DIR)/%.so
+$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(SHARK_DIR)/%.$(LIBRARY_SUFFIX)
$(install-file)
-$(EXPORT_SERVER_DIR)/%.so: $(SHARK_DIR)/%.so
+$(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX): $(SHARK_DIR)/%.$(LIBRARY_SUFFIX)
$(install-file)
else
-$(EXPORT_JRE_LIB_ARCH_DIR)/%.so: $(ZERO_DIR)/%.so
+$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(ZERO_DIR)/%.$(LIBRARY_SUFFIX)
$(install-file)
-$(EXPORT_SERVER_DIR)/%.so: $(ZERO_DIR)/%.so
+$(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX): $(ZERO_DIR)/%.$(LIBRARY_SUFFIX)
$(install-file)
endif
else
-$(EXPORT_JRE_LIB_ARCH_DIR)/%.so: $(C1_DIR)/%.so
+$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(C1_DIR)/%.$(LIBRARY_SUFFIX)
$(install-file)
-$(EXPORT_JRE_LIB_ARCH_DIR)/%.so: $(C2_DIR)/%.so
+$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(C2_DIR)/%.$(LIBRARY_SUFFIX)
$(install-file)
-$(EXPORT_CLIENT_DIR)/%.so: $(C1_DIR)/%.so
+$(EXPORT_CLIENT_DIR)/%.$(LIBRARY_SUFFIX): $(C1_DIR)/%.$(LIBRARY_SUFFIX)
$(install-file)
-$(EXPORT_CLIENT_DIR)/64/%.so: $(C1_DIR)/%.so
+$(EXPORT_CLIENT_DIR)/64/%.$(LIBRARY_SUFFIX): $(C1_DIR)/%.$(LIBRARY_SUFFIX)
$(install-file)
-$(EXPORT_SERVER_DIR)/%.so: $(C2_DIR)/%.so
+$(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX): $(C2_DIR)/%.$(LIBRARY_SUFFIX)
$(install-file)
-$(EXPORT_SERVER_DIR)/64/%.so: $(C2_DIR)/%.so
+$(EXPORT_SERVER_DIR)/64/%.$(LIBRARY_SUFFIX): $(C2_DIR)/%.$(LIBRARY_SUFFIX)
$(install-file)
# Debug info for shared library
diff --git a/make/bsd/Makefile b/make/bsd/Makefile
new file mode 100644
index 000000000..cef9d7c91
--- /dev/null
+++ b/make/bsd/Makefile
@@ -0,0 +1,371 @@
+#
+# Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+#
+
+# This makefile creates a build tree and lights off a build.
+# You can go back into the build tree and perform rebuilds or
+# incremental builds as desired. Be sure to reestablish
+# environment variable settings for LD_LIBRARY_PATH and JAVA_HOME.
+
+# The make process now relies on java and javac. These can be
+# specified either implicitly on the PATH, by setting the
+# (JDK-inherited) ALT_BOOTDIR environment variable to full path to a
+# JDK in which bin/java and bin/javac are present and working (e.g.,
+# /usr/local/java/jdk1.3/solaris), or via the (JDK-inherited)
+# default BOOTDIR path value. Note that one of ALT_BOOTDIR
+# or BOOTDIR has to be set. We do *not* search javac, javah, rmic etc.
+# from the PATH.
+#
+# One can set ALT_BOOTDIR or BOOTDIR to point to a jdk that runs on
+# an architecture that differs from the target architecture, as long
+# as the bootstrap jdk runs under the same flavor of OS as the target
+# (i.e., if the target is linux, point to a jdk that runs on a linux
+# box). In order to use such a bootstrap jdk, set the make variable
+# REMOTE to the desired remote command mechanism, e.g.,
+#
+# make REMOTE="rsh -l me myotherlinuxbox"
+
+# Along with VM, Serviceability Agent (SA) is built for SA/JDI binding.
+# JDI binding on SA produces two binaries:
+# 1. sa-jdi.jar - This is build before building libjvm[_g].so
+# Please refer to ./makefiles/sa.make
+# 2. libsa[_g].so - Native library for SA - This is built after
+# libjsig[_g].so (signal interposition library)
+# Please refer to ./makefiles/vm.make
+# If $(GAMMADIR)/agent dir is not present, SA components are not built.
+
+ifeq ($(GAMMADIR),)
+include ../../make/defs.make
+else
+include $(GAMMADIR)/make/defs.make
+endif
+include $(GAMMADIR)/make/$(OSNAME)/makefiles/rules.make
+
+ifndef CC_INTERP
+ ifndef FORCE_TIERED
+ FORCE_TIERED=1
+ endif
+endif
+
+ifdef LP64
+ ifeq ("$(filter $(LP64_ARCH),$(BUILDARCH))","")
+ _JUNK_ := $(shell echo >&2 \
+ $(OSNAME) $(ARCH) "*** ERROR: this platform does not support 64-bit compilers!")
+ @exit 1
+ endif
+endif
+
+# we need to set up LP64 correctly to satisfy sanity checks in adlc
+ifneq ("$(filter $(LP64_ARCH),$(BUILDARCH))","")
+ MFLAGS += " LP64=1 "
+endif
+
+# pass USE_SUNCC further, through MFLAGS
+ifdef USE_SUNCC
+ MFLAGS += " USE_SUNCC=1 "
+endif
+
+# The following renders pathnames in generated Makefiles valid on
+# machines other than the machine containing the build tree.
+#
+# For example, let's say my build tree lives on /files12 on
+# exact.east.sun.com. This logic will cause GAMMADIR to begin with
+# /net/exact/files12/...
+#
+# We only do this on SunOS variants, for a couple of reasons:
+# * It is extremely rare that source trees exist on other systems
+# * It has been claimed that the Linux automounter is flakey, so
+# changing GAMMADIR in a way that exercises the automounter could
+# prove to be a source of unreliability in the build process.
+# Obviously, this Makefile is only relevant on SunOS boxes to begin
+# with, but the SunOS conditionalization will make it easier to
+# combine Makefiles in the future (assuming we ever do that).
+
+ifeq ($(OSNAME),solaris)
+
+ # prepend current directory to relative pathnames.
+ NEW_GAMMADIR := \
+ $(shell echo $(GAMMADIR) | \
+ sed -e "s=^\([^/].*\)=$(shell pwd)/\1=" \
+ )
+ unexport NEW_GAMMADIR
+
+ # If NEW_GAMMADIR doesn't already start with "/net/":
+ ifeq ($(strip $(filter /net/%,$(NEW_GAMMADIR))),)
+ # prepend /net/$(HOST)
+ # remove /net/$(HOST) if name already began with /home/
+ # remove /net/$(HOST) if name already began with /java/
+ # remove /net/$(HOST) if name already began with /lab/
+ NEW_GAMMADIR := \
+ $(shell echo $(NEW_GAMMADIR) | \
+ sed -e "s=^\(.*\)=/net/$(HOST)\1=" \
+ -e "s=^/net/$(HOST)/home/=/home/=" \
+ -e "s=^/net/$(HOST)/java/=/java/=" \
+ -e "s=^/net/$(HOST)/lab/=/lab/=" \
+ )
+ # Don't use the new value for GAMMADIR unless a file with the new
+ # name actually exists.
+ ifneq ($(wildcard $(NEW_GAMMADIR)),)
+ GAMMADIR := $(NEW_GAMMADIR)
+ endif
+ endif
+
+endif
+
+# BUILDARCH is set to "zero" for Zero builds. VARIANTARCH
+# is used to give the build directories meaningful names.
+VARIANTARCH = $(subst i386,i486,$(ZERO_LIBARCH))
+
+# There is a (semi-) regular correspondence between make targets and actions:
+#
+# Target Tree Type Build Dir
+#
+# debug compiler2 <os>_<arch>_compiler2/debug
+# fastdebug compiler2 <os>_<arch>_compiler2/fastdebug
+# jvmg compiler2 <os>_<arch>_compiler2/jvmg
+# optimized compiler2 <os>_<arch>_compiler2/optimized
+# profiled compiler2 <os>_<arch>_compiler2/profiled
+# product compiler2 <os>_<arch>_compiler2/product
+#
+# debug1 compiler1 <os>_<arch>_compiler1/debug
+# fastdebug1 compiler1 <os>_<arch>_compiler1/fastdebug
+# jvmg1 compiler1 <os>_<arch>_compiler1/jvmg
+# optimized1 compiler1 <os>_<arch>_compiler1/optimized
+# profiled1 compiler1 <os>_<arch>_compiler1/profiled
+# product1 compiler1 <os>_<arch>_compiler1/product
+#
+# debugcore core <os>_<arch>_core/debug
+# fastdebugcore core <os>_<arch>_core/fastdebug
+# jvmgcore core <os>_<arch>_core/jvmg
+# optimizedcore core <os>_<arch>_core/optimized
+# profiledcore core <os>_<arch>_core/profiled
+# productcore core <os>_<arch>_core/product
+#
+# debugzero zero <os>_<arch>_zero/debug
+# fastdebugzero zero <os>_<arch>_zero/fastdebug
+# jvmgzero zero <os>_<arch>_zero/jvmg
+# optimizedzero zero <os>_<arch>_zero/optimized
+# profiledzero zero <os>_<arch>_zero/profiled
+# productzero zero <os>_<arch>_zero/product
+#
+# debugshark shark <os>_<arch>_shark/debug
+# fastdebugshark shark <os>_<arch>_shark/fastdebug
+# jvmgshark shark <os>_<arch>_shark/jvmg
+# optimizedshark shark <os>_<arch>_shark/optimized
+# profiledshark shark <os>_<arch>_shark/profiled
+# productshark shark <os>_<arch>_shark/product
+#
+# What you get with each target:
+#
+# debug* - "thin" libjvm_g - debug info linked into the gamma_g launcher
+# fastdebug* - optimized compile, but with asserts enabled
+# jvmg* - "fat" libjvm_g - debug info linked into libjvm_g.so
+# optimized* - optimized compile, no asserts
+# profiled* - gprof
+# product* - the shippable thing: optimized compile, no asserts, -DPRODUCT
+
+# This target list needs to be coordinated with the usage message
+# in the build.sh script:
+TARGETS = debug jvmg fastdebug optimized profiled product
+
+ifeq ($(ZERO_BUILD), true)
+ SUBDIR_DOCS = $(OSNAME)_$(VARIANTARCH)_docs
+else
+ SUBDIR_DOCS = $(OSNAME)_$(BUILDARCH)_docs
+endif
+SUBDIRS_C1 = $(addprefix $(OSNAME)_$(BUILDARCH)_compiler1/,$(TARGETS))
+SUBDIRS_C2 = $(addprefix $(OSNAME)_$(BUILDARCH)_compiler2/,$(TARGETS))
+SUBDIRS_TIERED = $(addprefix $(OSNAME)_$(BUILDARCH)_tiered/,$(TARGETS))
+SUBDIRS_CORE = $(addprefix $(OSNAME)_$(BUILDARCH)_core/,$(TARGETS))
+SUBDIRS_ZERO = $(addprefix $(OSNAME)_$(VARIANTARCH)_zero/,$(TARGETS))
+SUBDIRS_SHARK = $(addprefix $(OSNAME)_$(VARIANTARCH)_shark/,$(TARGETS))
+
+TARGETS_C2 = $(TARGETS)
+TARGETS_C1 = $(addsuffix 1,$(TARGETS))
+TARGETS_TIERED = $(addsuffix tiered,$(TARGETS))
+TARGETS_CORE = $(addsuffix core,$(TARGETS))
+TARGETS_ZERO = $(addsuffix zero,$(TARGETS))
+TARGETS_SHARK = $(addsuffix shark,$(TARGETS))
+
+BUILDTREE_MAKE = $(GAMMADIR)/make/$(OSNAME)/makefiles/buildtree.make
+BUILDTREE_VARS = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OSNAME) SRCARCH=$(SRCARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH)
+BUILDTREE_VARS += HOTSPOT_RELEASE_VERSION=$(HOTSPOT_RELEASE_VERSION) HOTSPOT_BUILD_VERSION=$(HOTSPOT_BUILD_VERSION) JRE_RELEASE_VERSION=$(JRE_RELEASE_VERSION)
+
+BUILDTREE = $(MAKE) -f $(BUILDTREE_MAKE) $(BUILDTREE_VARS)
+
+#-------------------------------------------------------------------------------
+
+# Could make everything by default, but that would take a while.
+all:
+ @echo "Try '$(MAKE) <target> ...' where <target> is one or more of"
+ @echo " $(TARGETS_C2)"
+ @echo " $(TARGETS_C1)"
+ @echo " $(TARGETS_CORE)"
+ @echo " $(TARGETS_ZERO)"
+ @echo " $(TARGETS_SHARK)"
+
+checks: check_os_version check_j2se_version
+
+# We do not want people accidentally building on old systems (e.g. Linux 2.2.x,
+# Solaris 2.5.1, 2.6).
+# Disable this check by setting DISABLE_HOTSPOT_OS_VERSION_CHECK=ok.
+
+#SUPPORTED_OS_VERSION = 2.4% 2.5% 2.6% 2.7%
+DISABLE_HOTSPOT_OS_VERSION_CHECK = ok
+OS_VERSION := $(shell uname -r)
+EMPTY_IF_NOT_SUPPORTED = $(filter $(SUPPORTED_OS_VERSION),$(OS_VERSION))
+
+check_os_version:
+ifeq ($(DISABLE_HOTSPOT_OS_VERSION_CHECK)$(EMPTY_IF_NOT_SUPPORTED),)
+ $(QUIETLY) >&2 echo "*** This OS is not supported:" `uname -a`; exit 1;
+endif
+
+# jvmti.make requires XSLT (J2SE 1.4.x or newer):
+XSLT_CHECK = $(REMOTE) $(RUN.JAVAP) javax.xml.transform.TransformerFactory
+# If not found then fail fast.
+check_j2se_version:
+ $(QUIETLY) $(XSLT_CHECK) > /dev/null 2>&1; \
+ if [ $$? -ne 0 ]; then \
+ $(REMOTE) $(RUN.JAVA) -version; \
+ echo "*** An XSLT processor (J2SE 1.4.x or newer) is required" \
+ "to bootstrap this build" 1>&2; \
+ exit 1; \
+ fi
+
+$(SUBDIRS_TIERED): $(BUILDTREE_MAKE)
+ $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
+ $(BUILDTREE) VARIANT=tiered
+
+$(SUBDIRS_C2): $(BUILDTREE_MAKE)
+ifeq ($(FORCE_TIERED),1)
+ $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
+ $(BUILDTREE) VARIANT=tiered FORCE_TIERED=1
+else
+ $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
+ $(BUILDTREE) VARIANT=compiler2
+endif
+
+$(SUBDIRS_C1): $(BUILDTREE_MAKE)
+ $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
+ $(BUILDTREE) VARIANT=compiler1
+
+$(SUBDIRS_CORE): $(BUILDTREE_MAKE)
+ $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
+ $(BUILDTREE) VARIANT=core
+
+$(SUBDIRS_ZERO): $(BUILDTREE_MAKE) platform_zero
+ $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
+ $(BUILDTREE) VARIANT=zero VARIANTARCH=$(VARIANTARCH)
+
+$(SUBDIRS_SHARK): $(BUILDTREE_MAKE) platform_zero
+ $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
+ $(BUILDTREE) VARIANT=shark VARIANTARCH=$(VARIANTARCH)
+
+platform_zero: $(GAMMADIR)/make/$(OSNAME)/platform_zero.in
+ $(SED) 's/@ZERO_ARCHDEF@/$(ZERO_ARCHDEF)/g;s/@ZERO_LIBARCH@/$(ZERO_LIBARCH)/g;' < $< > $@
+
+# Define INSTALL=y at command line to automatically copy JVM into JAVA_HOME
+
+$(TARGETS_C2): $(SUBDIRS_C2)
+ cd $(OSNAME)_$(BUILDARCH)_compiler2/$@ && $(MAKE) $(MFLAGS)
+ cd $(OSNAME)_$(BUILDARCH)_compiler2/$@ && ./test_gamma
+ifdef INSTALL
+ cd $(OSNAME)_$(BUILDARCH)_compiler2/$@ && $(MAKE) $(MFLAGS) install
+endif
+
+$(TARGETS_TIERED): $(SUBDIRS_TIERED)
+ cd $(OSNAME)_$(BUILDARCH)_tiered/$(patsubst %tiered,%,$@) && $(MAKE) $(MFLAGS)
+ cd $(OSNAME)_$(BUILDARCH)_tiered/$(patsubst %tiered,%,$@) && ./test_gamma
+ifdef INSTALL
+ cd $(OSNAME)_$(BUILDARCH)_tiered/$(patsubst %tiered,%,$@) && $(MAKE) $(MFLAGS) install
+endif
+
+$(TARGETS_C1): $(SUBDIRS_C1)
+ cd $(OSNAME)_$(BUILDARCH)_compiler1/$(patsubst %1,%,$@) && $(MAKE) $(MFLAGS)
+ cd $(OSNAME)_$(BUILDARCH)_compiler1/$(patsubst %1,%,$@) && ./test_gamma
+ifdef INSTALL
+ cd $(OSNAME)_$(BUILDARCH)_compiler1/$(patsubst %1,%,$@) && $(MAKE) $(MFLAGS) install
+endif
+
+$(TARGETS_CORE): $(SUBDIRS_CORE)
+ cd $(OSNAME)_$(BUILDARCH)_core/$(patsubst %core,%,$@) && $(MAKE) $(MFLAGS)
+ cd $(OSNAME)_$(BUILDARCH)_core/$(patsubst %core,%,$@) && ./test_gamma
+ifdef INSTALL
+ cd $(OSNAME)_$(BUILDARCH)_core/$(patsubst %core,%,$@) && $(MAKE) $(MFLAGS) install
+endif
+
+$(TARGETS_ZERO): $(SUBDIRS_ZERO)
+ cd $(OSNAME)_$(VARIANTARCH)_zero/$(patsubst %zero,%,$@) && $(MAKE) $(MFLAGS)
+ cd $(OSNAME)_$(VARIANTARCH)_zero/$(patsubst %zero,%,$@) && ./test_gamma
+ifdef INSTALL
+ cd $(OSNAME)_$(VARIANTARCH)_zero/$(patsubst %zero,%,$@) && $(MAKE) $(MFLAGS) install
+endif
+
+$(TARGETS_SHARK): $(SUBDIRS_SHARK)
+ cd $(OSNAME)_$(VARIANTARCH)_shark/$(patsubst %shark,%,$@) && $(MAKE) $(MFLAGS)
+ cd $(OSNAME)_$(VARIANTARCH)_shark/$(patsubst %shark,%,$@) && ./test_gamma
+ifdef INSTALL
+ cd $(OSNAME)_$(VARIANTARCH)_shark/$(patsubst %shark,%,$@) && $(MAKE) $(MFLAGS) install
+endif
+
+# Just build the tree, and nothing else:
+tree: $(SUBDIRS_C2)
+tree1: $(SUBDIRS_C1)
+treecore: $(SUBDIRS_CORE)
+treezero: $(SUBDIRS_ZERO)
+treeshark: $(SUBDIRS_SHARK)
+
+# Doc target. This is the same for all build options.
+# Hence create a docs directory beside ...$(ARCH)_[...]
+docs: checks
+ $(QUIETLY) mkdir -p $(SUBDIR_DOCS)
+ $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/makefiles/jvmti.make $(MFLAGS) $(BUILDTREE_VARS) JvmtiOutDir=$(SUBDIR_DOCS) jvmtidocs
+
+# Synonyms for win32-like targets.
+compiler2: jvmg product
+
+compiler1: jvmg1 product1
+
+core: jvmgcore productcore
+
+zero: jvmgzero productzero
+
+shark: jvmgshark productshark
+
+clean_docs:
+ rm -rf $(SUBDIR_DOCS)
+
+clean_compiler1 clean_compiler2 clean_core clean_zero clean_shark:
+ rm -rf $(OSNAME)_$(BUILDARCH)_$(subst clean_,,$@)
+
+clean: clean_compiler2 clean_compiler1 clean_core clean_zero clean_shark clean_docs
+
+include $(GAMMADIR)/make/cscope.make
+
+#-------------------------------------------------------------------------------
+
+.PHONY: $(TARGETS_C2) $(TARGETS_C1) $(TARGETS_CORE) $(TARGETS_ZERO) $(TARGETS_SHARK)
+.PHONY: tree tree1 treecore treezero treeshark
+.PHONY: all compiler1 compiler2 core zero shark
+.PHONY: clean clean_compiler1 clean_compiler2 clean_core clean_zero clean_shark docs clean_docs
+.PHONY: checks check_os_version check_j2se_version
diff --git a/make/bsd/README b/make/bsd/README
new file mode 100644
index 000000000..d3efaf8b6
--- /dev/null
+++ b/make/bsd/README
@@ -0,0 +1,26 @@
+Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+________________________________________________________________________
+
+Please refer to the comments in the Makefile in this directory
+for instructions how to build the Solaris versions.
+
diff --git a/make/bsd/adlc_updater b/make/bsd/adlc_updater
new file mode 100644
index 000000000..6d31b792c
--- /dev/null
+++ b/make/bsd/adlc_updater
@@ -0,0 +1,20 @@
+#! /bin/sh
+#
+# This file is used by adlc.make to selectively update generated
+# adlc files. Because source and target diretories are relative
+# paths, this file is copied to the target build directory before
+# use.
+#
+# adlc-updater <file> <source-dir> <target-dir>
+#
+fix_lines() {
+ # repair bare #line directives in $1 to refer to $2
+ awk < $1 > $1+ '
+ /^#line 999999$/ {print "#line " (NR+1) " \"" F2 "\""; next}
+ {print}
+ ' F2=$2
+ mv $1+ $1
+}
+fix_lines $2/$1 $3/$1
+[ -f $3/$1 ] && cmp -s $2/$1 $3/$1 || \
+( [ -f $3/$1 ] && echo Updating $3/$1 ; touch $2/made-change ; mv $2/$1 $3/$1 )
diff --git a/make/bsd/build.sh b/make/bsd/build.sh
new file mode 100644
index 000000000..ddb07e541
--- /dev/null
+++ b/make/bsd/build.sh
@@ -0,0 +1,95 @@
+#! /bin/sh
+#
+# Copyright (c) 1999, 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.
+#
+# 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.
+#
+#
+
+# Make sure the variable JAVA_HOME is set before running this script.
+
+set -u
+
+
+if [ $# != 2 ]; then
+ echo "Usage : $0 Build_Options Location"
+ echo "Build Options : debug or optimized or basicdebug or basic or clean"
+ echo "Location : specify any workspace which has gamma sources"
+ exit 1
+fi
+
+# Just in case:
+case ${JAVA_HOME} in
+/*) true;;
+?*) JAVA_HOME=`( cd $JAVA_HOME; pwd )`;;
+esac
+
+case `uname -m` in
+ i386|i486|i586|i686)
+ mach=i386
+ ;;
+ *)
+ echo "Unsupported machine: " `uname -m`
+ exit 1
+ ;;
+esac
+
+if [ "${JAVA_HOME}" = "" -o ! -d "${JAVA_HOME}" -o ! -d ${JAVA_HOME}/jre/lib/${mach} ]; then
+ echo "JAVA_HOME needs to be set to a valid JDK path"
+ echo "ksh : export JAVA_HOME=/net/tetrasparc/export/gobi/JDK1.2_fcs_V/bsd"
+ echo "csh : setenv JAVA_HOME /net/tetrasparc/export/gobi/JDK1.2_fcs_V/bsd"
+ exit 1
+fi
+
+
+LD_LIBRARY_PATH=${JAVA_HOME}/jre/lib/`uname -p`:\
+${JAVA_HOME}/jre/lib/`uname -p`/native_threads:${LD_LIBRARY_PATH-.}
+
+# This is necessary as long as we are using the old launcher
+# with the new distribution format:
+CLASSPATH=${JAVA_HOME}/jre/lib/rt.jar:${CLASSPATH-.}
+
+
+for gm in gmake gnumake
+do
+ if [ "${GNUMAKE-}" != "" ]; then break; fi
+ ($gm --version >/dev/null) 2>/dev/null && GNUMAKE=$gm
+done
+: ${GNUMAKE:?'Cannot locate the gnumake program. Stop.'}
+
+
+echo "### ENVIRONMENT SETTINGS:"
+export JAVA_HOME ; echo "JAVA_HOME=$JAVA_HOME"
+export LD_LIBRARY_PATH ; echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH"
+export CLASSPATH ; echo "CLASSPATH=$CLASSPATH"
+export GNUMAKE ; echo "GNUMAKE=$GNUMAKE"
+echo "###"
+
+Build_Options=$1
+Location=$2
+
+case ${Location} in
+/*) true;;
+?*) Location=`(cd ${Location}; pwd)`;;
+esac
+
+echo \
+${GNUMAKE} -f ${Location}/make/bsd/Makefile $Build_Options GAMMADIR=${Location}
+${GNUMAKE} -f ${Location}/make/bsd/Makefile $Build_Options GAMMADIR=${Location}
diff --git a/make/bsd/makefiles/adjust-mflags.sh b/make/bsd/makefiles/adjust-mflags.sh
new file mode 100644
index 000000000..484fa85e8
--- /dev/null
+++ b/make/bsd/makefiles/adjust-mflags.sh
@@ -0,0 +1,87 @@
+#! /bin/sh
+#
+# Copyright (c) 1999, 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.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+#
+
+# This script is used only from top.make.
+# The macro $(MFLAGS-adjusted) calls this script to
+# adjust the "-j" arguments to take into account
+# the HOTSPOT_BUILD_JOBS variable. The default
+# handling of the "-j" argument by gnumake does
+# not meet our needs, so we must adjust it ourselves.
+
+# This argument adjustment applies to two recursive
+# calls to "$(MAKE) $(MFLAGS-adjusted)" in top.make.
+# One invokes adlc.make, and the other invokes vm.make.
+# The adjustment propagates the desired concurrency
+# level down to the sub-make (of the adlc or vm).
+# The default behavior of gnumake is to run all
+# sub-makes without concurrency ("-j1").
+
+# Also, we use a make variable rather than an explicit
+# "-j<N>" argument to control this setting, so that
+# the concurrency setting (which must be tuned separately
+# for each MP system) can be set via an environment variable.
+# The recommended setting is 1.5x to 2x the number of available
+# CPUs on the MP system, which is large enough to keep the CPUs
+# busy (even though some jobs may be I/O bound) but not too large,
+# we may presume, to overflow the system's swap space.
+
+set -eu
+
+default_build_jobs=4
+
+case $# in
+[12]) true;;
+*) >&2 echo "Usage: $0 ${MFLAGS} ${HOTSPOT_BUILD_JOBS}"; exit 2;;
+esac
+
+MFLAGS=$1
+HOTSPOT_BUILD_JOBS=${2-}
+
+# Normalize any -jN argument to the form " -j${HBJ}"
+MFLAGS=`
+ echo "$MFLAGS" \
+ | sed '
+ s/^-/ -/
+ s/ -\([^ ][^ ]*\)j/ -\1 -j/
+ s/ -j[0-9][0-9]*/ -j/
+ s/ -j\([^ ]\)/ -j -\1/
+ s/ -j/ -j'${HOTSPOT_BUILD_JOBS:-${default_build_jobs}}'/
+ ' `
+
+case ${HOTSPOT_BUILD_JOBS} in \
+
+'') case ${MFLAGS} in
+ *\ -j*)
+ >&2 echo "# Note: -jN is ineffective for setting parallelism in this makefile."
+ >&2 echo "# please set HOTSPOT_BUILD_JOBS=${default_build_jobs} in the command line or environment."
+ esac;;
+
+?*) case ${MFLAGS} in
+ *\ -j*) true;;
+ *) MFLAGS="-j${HOTSPOT_BUILD_JOBS} ${MFLAGS}";;
+ esac;;
+esac
+
+echo "${MFLAGS}"
diff --git a/make/bsd/makefiles/adlc.make b/make/bsd/makefiles/adlc.make
new file mode 100644
index 000000000..0c15c1c65
--- /dev/null
+++ b/make/bsd/makefiles/adlc.make
@@ -0,0 +1,226 @@
+#
+# Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+#
+
+# This makefile (adlc.make) is included from the adlc.make in the
+# build directories.
+# It knows how to compile, link, and run the adlc.
+
+include $(GAMMADIR)/make/$(Platform_os_family)/makefiles/rules.make
+
+# #########################################################################
+
+# OUTDIR must be the same as AD_Dir = $(GENERATED)/adfiles in top.make:
+GENERATED = ../generated
+OUTDIR = $(GENERATED)/adfiles
+
+ARCH = $(Platform_arch)
+OS = $(Platform_os_family)
+
+SOURCE.AD = $(OUTDIR)/$(OS)_$(Platform_arch_model).ad
+
+SOURCES.AD = \
+ $(call altsrc-replace,$(HS_COMMON_SRC)/cpu/$(ARCH)/vm/$(Platform_arch_model).ad) \
+ $(call altsrc-replace,$(HS_COMMON_SRC)/os_cpu/$(OS)_$(ARCH)/vm/$(OS)_$(Platform_arch_model).ad)
+
+EXEC = $(OUTDIR)/adlc
+
+# set VPATH so make knows where to look for source files
+Src_Dirs_V += $(GAMMADIR)/src/share/vm/adlc
+VPATH += $(Src_Dirs_V:%=%:)
+
+# set INCLUDES for C preprocessor
+Src_Dirs_I += $(GAMMADIR)/src/share/vm/adlc $(GENERATED)
+INCLUDES += $(Src_Dirs_I:%=-I%)
+
+# set flags for adlc compilation
+CPPFLAGS = $(SYSDEFS) $(INCLUDES)
+
+# Force assertions on.
+CPPFLAGS += -DASSERT
+
+# CFLAGS_WARN holds compiler options to suppress/enable warnings.
+# Compiler warnings are treated as errors
+CFLAGS_WARN = -Werror
+CFLAGS += $(CFLAGS_WARN)
+
+OBJECTNAMES = \
+ adlparse.o \
+ archDesc.o \
+ arena.o \
+ dfa.o \
+ dict2.o \
+ filebuff.o \
+ forms.o \
+ formsopt.o \
+ formssel.o \
+ main.o \
+ adlc-opcodes.o \
+ output_c.o \
+ output_h.o \
+
+OBJECTS = $(OBJECTNAMES:%=$(OUTDIR)/%)
+
+GENERATEDNAMES = \
+ ad_$(Platform_arch_model).cpp \
+ ad_$(Platform_arch_model).hpp \
+ ad_$(Platform_arch_model)_clone.cpp \
+ ad_$(Platform_arch_model)_expand.cpp \
+ ad_$(Platform_arch_model)_format.cpp \
+ ad_$(Platform_arch_model)_gen.cpp \
+ ad_$(Platform_arch_model)_misc.cpp \
+ ad_$(Platform_arch_model)_peephole.cpp \
+ ad_$(Platform_arch_model)_pipeline.cpp \
+ adGlobals_$(Platform_arch_model).hpp \
+ dfa_$(Platform_arch_model).cpp \
+
+GENERATEDFILES = $(GENERATEDNAMES:%=$(OUTDIR)/%)
+
+# #########################################################################
+
+all: $(EXEC)
+
+$(EXEC) : $(OBJECTS)
+ @echo Making adlc
+ $(QUIETLY) $(HOST.LINK_NOPROF.CC) -o $(EXEC) $(OBJECTS)
+
+# Random dependencies:
+$(OBJECTS): opcodes.hpp classes.hpp adlc.hpp adlcVMDeps.hpp adlparse.hpp archDesc.hpp arena.hpp dict2.hpp filebuff.hpp forms.hpp formsopt.hpp formssel.hpp
+
+# The source files refer to ostream.h, which sparcworks calls iostream.h
+$(OBJECTS): ostream.h
+
+ostream.h :
+ @echo >$@ '#include <iostream.h>'
+
+dump:
+ : OUTDIR=$(OUTDIR)
+ : OBJECTS=$(OBJECTS)
+ : products = $(GENERATEDFILES)
+
+all: $(GENERATEDFILES)
+
+$(GENERATEDFILES): refresh_adfiles
+
+# Get a unique temporary directory name, so multiple makes can run in parallel.
+# Note that product files are updated via "mv", which is atomic.
+TEMPDIR := $(OUTDIR)/mktmp$(shell echo $$$$)
+
+# Debuggable by default
+CFLAGS += -g
+
+# Pass -D flags into ADLC.
+ADLCFLAGS += $(SYSDEFS)
+
+# Note "+="; it is a hook so flags.make can add more flags, like -g or -DFOO.
+ADLCFLAGS += -q -T
+
+# Normally, debugging is done directly on the ad_<arch>*.cpp files.
+# But -g will put #line directives in those files pointing back to <arch>.ad.
+# Some builds of gcc 3.2 have a bug that gets tickled by the extra #line directives
+# so skip it for 3.2 and ealier.
+ifneq "$(shell expr \( $(CC_VER_MAJOR) \> 3 \) \| \( \( $(CC_VER_MAJOR) = 3 \) \& \( $(CC_VER_MINOR) \>= 3 \) \))" "0"
+ADLCFLAGS += -g
+endif
+
+ifdef LP64
+ADLCFLAGS += -D_LP64
+else
+ADLCFLAGS += -U_LP64
+endif
+
+#
+# adlc_updater is a simple sh script, under sccs control. It is
+# used to selectively update generated adlc files. This should
+# provide a nice compilation speed improvement.
+#
+ADLC_UPDATER_DIRECTORY = $(GAMMADIR)/make/$(OS)
+ADLC_UPDATER = adlc_updater
+$(ADLC_UPDATER): $(ADLC_UPDATER_DIRECTORY)/$(ADLC_UPDATER)
+ $(QUIETLY) cp $< $@; chmod +x $@
+
+# This action refreshes all generated adlc files simultaneously.
+# The way it works is this:
+# 1) create a scratch directory to work in.
+# 2) if the current working directory does not have $(ADLC_UPDATER), copy it.
+# 3) run the compiled adlc executable. This will create new adlc files in the scratch directory.
+# 4) call $(ADLC_UPDATER) on each generated adlc file. It will selectively update changed or missing files.
+# 5) If we actually updated any files, echo a notice.
+#
+refresh_adfiles: $(EXEC) $(SOURCE.AD) $(ADLC_UPDATER)
+ @rm -rf $(TEMPDIR); mkdir $(TEMPDIR)
+ $(QUIETLY) $(EXEC) $(ADLCFLAGS) $(SOURCE.AD) \
+ -c$(TEMPDIR)/ad_$(Platform_arch_model).cpp -h$(TEMPDIR)/ad_$(Platform_arch_model).hpp -a$(TEMPDIR)/dfa_$(Platform_arch_model).cpp -v$(TEMPDIR)/adGlobals_$(Platform_arch_model).hpp \
+ || { rm -rf $(TEMPDIR); exit 1; }
+ $(QUIETLY) ./$(ADLC_UPDATER) ad_$(Platform_arch_model).cpp $(TEMPDIR) $(OUTDIR)
+ $(QUIETLY) ./$(ADLC_UPDATER) ad_$(Platform_arch_model).hpp $(TEMPDIR) $(OUTDIR)
+ $(QUIETLY) ./$(ADLC_UPDATER) ad_$(Platform_arch_model)_clone.cpp $(TEMPDIR) $(OUTDIR)
+ $(QUIETLY) ./$(ADLC_UPDATER) ad_$(Platform_arch_model)_expand.cpp $(TEMPDIR) $(OUTDIR)
+ $(QUIETLY) ./$(ADLC_UPDATER) ad_$(Platform_arch_model)_format.cpp $(TEMPDIR) $(OUTDIR)
+ $(QUIETLY) ./$(ADLC_UPDATER) ad_$(Platform_arch_model)_gen.cpp $(TEMPDIR) $(OUTDIR)
+ $(QUIETLY) ./$(ADLC_UPDATER) ad_$(Platform_arch_model)_misc.cpp $(TEMPDIR) $(OUTDIR)
+ $(QUIETLY) ./$(ADLC_UPDATER) ad_$(Platform_arch_model)_peephole.cpp $(TEMPDIR) $(OUTDIR)
+ $(QUIETLY) ./$(ADLC_UPDATER) ad_$(Platform_arch_model)_pipeline.cpp $(TEMPDIR) $(OUTDIR)
+ $(QUIETLY) ./$(ADLC_UPDATER) adGlobals_$(Platform_arch_model).hpp $(TEMPDIR) $(OUTDIR)
+ $(QUIETLY) ./$(ADLC_UPDATER) dfa_$(Platform_arch_model).cpp $(TEMPDIR) $(OUTDIR)
+ $(QUIETLY) [ -f $(TEMPDIR)/made-change ] \
+ || echo "Rescanned $(SOURCE.AD) but encountered no changes."
+ $(QUIETLY) rm -rf $(TEMPDIR)
+
+
+# #########################################################################
+
+$(SOURCE.AD): $(SOURCES.AD)
+ $(QUIETLY) $(PROCESS_AD_FILES) $(SOURCES.AD) > $(SOURCE.AD)
+
+#PROCESS_AD_FILES = cat
+# Pass through #line directives, in case user enables -g option above:
+PROCESS_AD_FILES = awk '{ \
+ if (CUR_FN != FILENAME) { CUR_FN=FILENAME; NR_BASE=NR-1; need_lineno=1 } \
+ if (need_lineno && $$0 !~ /\/\//) \
+ { print "\n\n\#line " (NR-NR_BASE) " \"" FILENAME "\""; need_lineno=0 }; \
+ print }'
+
+$(OUTDIR)/%.o: %.cpp
+ @echo Compiling $<
+ $(QUIETLY) $(REMOVE_TARGET)
+ $(QUIETLY) $(HOST.COMPILE.CC) -o $@ $< $(COMPILE_DONE)
+
+# Some object files are given a prefix, to disambiguate
+# them from objects of the same name built for the VM.
+$(OUTDIR)/adlc-%.o: %.cpp
+ @echo Compiling $<
+ $(QUIETLY) $(REMOVE_TARGET)
+ $(QUIETLY) $(HOST.COMPILE.CC) -o $@ $< $(COMPILE_DONE)
+
+# #########################################################################
+
+clean :
+ rm $(OBJECTS)
+
+cleanall :
+ rm $(OBJECTS) $(EXEC)
+
+# #########################################################################
+
+.PHONY: all dump refresh_adfiles clean cleanall
diff --git a/make/bsd/makefiles/amd64.make b/make/bsd/makefiles/amd64.make
new file mode 100644
index 000000000..ecdac17ee
--- /dev/null
+++ b/make/bsd/makefiles/amd64.make
@@ -0,0 +1,39 @@
+#
+# Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+#
+
+# The copied fdlibm routines in sharedRuntimeTrig.o must not be optimized
+OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/NOOPT)
+# The copied fdlibm routines in sharedRuntimeTrans.o must not be optimized
+OPT_CFLAGS/sharedRuntimeTrans.o = $(OPT_CFLAGS/NOOPT)
+# Must also specify if CPU is little endian
+CFLAGS += -DVM_LITTLE_ENDIAN
+
+CFLAGS += -D_LP64=1
+
+# The serviceability agent relies on frame pointer (%rbp) to walk thread stack
+ifndef USE_SUNCC
+ CFLAGS += -fno-omit-frame-pointer
+endif
+
+OPT_CFLAGS/compactingPermGenGen.o = -O1
diff --git a/make/bsd/makefiles/arm.make b/make/bsd/makefiles/arm.make
new file mode 100644
index 000000000..e22d5c375
--- /dev/null
+++ b/make/bsd/makefiles/arm.make
@@ -0,0 +1,29 @@
+#
+# Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+#
+
+Obj_Files += bsd_arm.o
+
+LIBS += $(EXT_LIBS_PATH)/sflt_glibc.a
+
+CFLAGS += -DVM_LITTLE_ENDIAN
diff --git a/make/bsd/makefiles/build_vm_def.sh b/make/bsd/makefiles/build_vm_def.sh
new file mode 100644
index 000000000..fb9a0d57a
--- /dev/null
+++ b/make/bsd/makefiles/build_vm_def.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+# If we're cross compiling use that path for nm
+if [ "$CROSS_COMPILE_ARCH" != "" ]; then
+NM=$ALT_COMPILER_PATH/nm
+else
+NM=nm
+fi
+
+$NM --defined-only $* | awk '
+ { if ($3 ~ /^_ZTV/ || $3 ~ /^gHotSpotVM/) print "\t" $3 ";" }
+ '
diff --git a/make/bsd/makefiles/buildtree.make b/make/bsd/makefiles/buildtree.make
new file mode 100644
index 000000000..a62f69ab4
--- /dev/null
+++ b/make/bsd/makefiles/buildtree.make
@@ -0,0 +1,409 @@
+#
+# Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+#
+
+# Usage:
+#
+# $(MAKE) -f buildtree.make SRCARCH=srcarch BUILDARCH=buildarch LIBARCH=libarch
+# GAMMADIR=dir OS_FAMILY=os VARIANT=variant
+#
+# The macros ARCH, GAMMADIR, OS_FAMILY and VARIANT must be defined in the
+# environment or on the command-line:
+#
+# ARCH - sparc, i486, ... HotSpot cpu and os_cpu source directory
+# BUILDARCH - build directory
+# LIBARCH - the corresponding directory in JDK/JRE
+# GAMMADIR - top of workspace
+# OS_FAMILY - operating system
+# VARIANT - core, compiler1, compiler2, or tiered
+# HOTSPOT_RELEASE_VERSION - <major>.<minor>-b<nn> (11.0-b07)
+# HOTSPOT_BUILD_VERSION - internal, internal-$(USER_RELEASE_SUFFIX) or empty
+# JRE_RELEASE_VERSION - <major>.<minor>.<micro> (1.7.0)
+#
+# Builds the directory trees with makefiles plus some convenience files in
+# each directory:
+#
+# Makefile - for "make foo"
+# flags.make - with macro settings
+# vm.make - to support making "$(MAKE) -v vm.make" in makefiles
+# adlc.make -
+# jvmti.make - generate JVMTI bindings from the spec (JSR-163)
+# sa.make - generate SA jar file and natives
+# env.[ck]sh - environment settings
+# test_gamma - script to run the Queens program
+#
+# The makefiles are split this way so that "make foo" will run faster by not
+# having to read the dependency files for the vm.
+
+include $(GAMMADIR)/make/scm.make
+include $(GAMMADIR)/make/altsrc.make
+
+
+# 'gmake MAKE_VERBOSE=y' or 'gmake QUIETLY=' gives all the gory details.
+QUIETLY$(MAKE_VERBOSE) = @
+
+# For now, until the compiler is less wobbly:
+TESTFLAGS = -Xbatch -showversion
+
+ifeq ($(ZERO_BUILD), true)
+ PLATFORM_FILE = $(shell dirname $(shell dirname $(shell pwd)))/platform_zero
+else
+ ifdef USE_SUNCC
+ PLATFORM_FILE = $(GAMMADIR)/make/$(OS_FAMILY)/platform_$(BUILDARCH).suncc
+ else
+ PLATFORM_FILE = $(GAMMADIR)/make/$(OS_FAMILY)/platform_$(BUILDARCH)
+ endif
+endif
+
+# Allow overriding of the arch part of the directory but default
+# to BUILDARCH if nothing is specified
+ifeq ($(VARIANTARCH),)
+ VARIANTARCH=$(BUILDARCH)
+endif
+
+ifdef FORCE_TIERED
+ifeq ($(VARIANT),tiered)
+PLATFORM_DIR = $(OS_FAMILY)_$(VARIANTARCH)_compiler2
+else
+PLATFORM_DIR = $(OS_FAMILY)_$(VARIANTARCH)_$(VARIANT)
+endif
+else
+PLATFORM_DIR = $(OS_FAMILY)_$(VARIANTARCH)_$(VARIANT)
+endif
+
+#
+# We do two levels of exclusion in the shared directory.
+# TOPLEVEL excludes are pruned, they are not recursively searched,
+# but lower level directories can be named without fear of collision.
+# ALWAYS excludes are excluded at any level in the directory tree.
+#
+
+ALWAYS_EXCLUDE_DIRS = $(SCM_DIRS)
+
+ifeq ($(VARIANT),tiered)
+TOPLEVEL_EXCLUDE_DIRS = $(ALWAYS_EXCLUDE_DIRS) -o -name adlc -o -name agent
+else
+ifeq ($(VARIANT),compiler2)
+TOPLEVEL_EXCLUDE_DIRS = $(ALWAYS_EXCLUDE_DIRS) -o -name adlc -o -name c1 -o -name agent
+else
+# compiler1 and core use the same exclude list
+TOPLEVEL_EXCLUDE_DIRS = $(ALWAYS_EXCLUDE_DIRS) -o -name adlc -o -name opto -o -name libadt -o -name agent
+endif
+endif
+
+# Get things from the platform file.
+COMPILER = $(shell sed -n 's/^compiler[ ]*=[ ]*//p' $(PLATFORM_FILE))
+
+SIMPLE_DIRS = \
+ $(PLATFORM_DIR)/generated/dependencies \
+ $(PLATFORM_DIR)/generated/adfiles \
+ $(PLATFORM_DIR)/generated/jvmtifiles
+
+TARGETS = debug fastdebug jvmg optimized product profiled
+SUBMAKE_DIRS = $(addprefix $(PLATFORM_DIR)/,$(TARGETS))
+
+# For dependencies and recursive makes.
+BUILDTREE_MAKE = $(GAMMADIR)/make/$(OS_FAMILY)/makefiles/buildtree.make
+
+BUILDTREE_TARGETS = Makefile flags.make flags_vm.make vm.make adlc.make jvmti.make sa.make \
+ env.sh env.csh jdkpath.sh .dbxrc test_gamma
+
+BUILDTREE_VARS = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OS_FAMILY) \
+ SRCARCH=$(SRCARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH) VARIANT=$(VARIANT)
+
+# Define variables to be set in flags.make.
+# Default values are set in make/defs.make.
+ifeq ($(HOTSPOT_BUILD_VERSION),)
+ HS_BUILD_VER=$(HOTSPOT_RELEASE_VERSION)
+else
+ HS_BUILD_VER=$(HOTSPOT_RELEASE_VERSION)-$(HOTSPOT_BUILD_VERSION)
+endif
+# Set BUILD_USER from system-dependent hints: $LOGNAME, $(whoami)
+ifndef HOTSPOT_BUILD_USER
+ HOTSPOT_BUILD_USER := $(shell echo $$LOGNAME)
+endif
+ifndef HOTSPOT_BUILD_USER
+ HOTSPOT_BUILD_USER := $(shell whoami)
+endif
+# Define HOTSPOT_VM_DISTRO based on settings in make/openjdk_distro
+# or make/hotspot_distro.
+ifndef HOTSPOT_VM_DISTRO
+ ifeq ($(call if-has-altsrc,$(HS_COMMON_SRC)/,true,false),true)
+ include $(GAMMADIR)/make/hotspot_distro
+ else
+ include $(GAMMADIR)/make/openjdk_distro
+ endif
+endif
+
+BUILDTREE_VARS += HOTSPOT_RELEASE_VERSION=$(HS_BUILD_VER) HOTSPOT_BUILD_VERSION= JRE_RELEASE_VERSION=$(JRE_RELEASE_VERSION)
+
+BUILDTREE = \
+ $(MAKE) -f $(BUILDTREE_MAKE) $(BUILDTREE_TARGETS) $(BUILDTREE_VARS)
+
+BUILDTREE_COMMENT = echo "\# Generated by $(BUILDTREE_MAKE)"
+
+all: $(SUBMAKE_DIRS)
+
+# Run make in each subdirectory recursively.
+$(SUBMAKE_DIRS): $(SIMPLE_DIRS) FORCE
+ $(QUIETLY) [ -d $@ ] || { mkdir -p $@; }
+ $(QUIETLY) cd $@ && $(BUILDTREE) TARGET=$(@F)
+ $(QUIETLY) touch $@
+
+$(SIMPLE_DIRS):
+ $(QUIETLY) mkdir -p $@
+
+# Convenience macro which takes a source relative path, applies $(1) to the
+# absolute path, and then replaces $(GAMMADIR) in the result with a
+# literal "$(GAMMADIR)/" suitable for inclusion in a Makefile.
+gamma-path=$(subst $(GAMMADIR),\$$(GAMMADIR),$(call $(1),$(HS_COMMON_SRC)/$(2)))
+
+flags.make: $(BUILDTREE_MAKE) ../shared_dirs.lst
+ @echo Creating $@ ...
+ $(QUIETLY) ( \
+ $(BUILDTREE_COMMENT); \
+ echo; \
+ echo "Platform_file = $(PLATFORM_FILE)" | sed 's|$(GAMMADIR)|$$(GAMMADIR)|'; \
+ sed -n '/=/s/^ */Platform_/p' < $(PLATFORM_FILE); \
+ echo; \
+ echo "GAMMADIR = $(GAMMADIR)"; \
+ echo "SYSDEFS = \$$(Platform_sysdefs)"; \
+ echo "SRCARCH = $(SRCARCH)"; \
+ echo "BUILDARCH = $(BUILDARCH)"; \
+ echo "LIBARCH = $(LIBARCH)"; \
+ echo "TARGET = $(TARGET)"; \
+ echo "HS_BUILD_VER = $(HS_BUILD_VER)"; \
+ echo "JRE_RELEASE_VER = $(JRE_RELEASE_VERSION)"; \
+ echo "SA_BUILD_VERSION = $(HS_BUILD_VER)"; \
+ echo "HOTSPOT_BUILD_USER = $(HOTSPOT_BUILD_USER)"; \
+ echo "HOTSPOT_VM_DISTRO = $(HOTSPOT_VM_DISTRO)"; \
+ echo; \
+ echo "# Used for platform dispatching"; \
+ echo "TARGET_DEFINES = -DTARGET_OS_FAMILY_\$$(Platform_os_family)"; \
+ echo "TARGET_DEFINES += -DTARGET_ARCH_\$$(Platform_arch)"; \
+ echo "TARGET_DEFINES += -DTARGET_ARCH_MODEL_\$$(Platform_arch_model)"; \
+ echo "TARGET_DEFINES += -DTARGET_OS_ARCH_\$$(Platform_os_arch)"; \
+ echo "TARGET_DEFINES += -DTARGET_OS_ARCH_MODEL_\$$(Platform_os_arch_model)"; \
+ echo "TARGET_DEFINES += -DTARGET_COMPILER_\$$(Platform_compiler)"; \
+ echo "CFLAGS += \$$(TARGET_DEFINES)"; \
+ echo; \
+ echo "Src_Dirs_V = \\"; \
+ sed 's/$$/ \\/;s|$(GAMMADIR)|$$(GAMMADIR)|' ../shared_dirs.lst; \
+ echo "$(call gamma-path,altsrc,cpu/$(SRCARCH)/vm) \\"; \
+ echo "$(call gamma-path,commonsrc,cpu/$(SRCARCH)/vm) \\"; \
+ echo "$(call gamma-path,altsrc,os_cpu/$(OS_FAMILY)_$(SRCARCH)/vm) \\"; \
+ echo "$(call gamma-path,commonsrc,os_cpu/$(OS_FAMILY)_$(SRCARCH)/vm) \\"; \
+ echo "$(call gamma-path,altsrc,os/$(OS_FAMILY)/vm) \\"; \
+ echo "$(call gamma-path,commonsrc,os/$(OS_FAMILY)/vm) \\"; \
+ echo "$(call gamma-path,altsrc,os/posix/vm) \\"; \
+ echo "$(call gamma-path,commonsrc,os/posix/vm)"; \
+ echo; \
+ echo "Src_Dirs_I = \\"; \
+ echo "$(call gamma-path,altsrc,share/vm/prims) \\"; \
+ echo "$(call gamma-path,commonsrc,share/vm/prims) \\"; \
+ echo "$(call gamma-path,altsrc,share/vm) \\"; \
+ echo "$(call gamma-path,commonsrc,share/vm) \\"; \
+ echo "$(call gamma-path,altsrc,cpu/$(SRCARCH)/vm) \\"; \
+ echo "$(call gamma-path,commonsrc,cpu/$(SRCARCH)/vm) \\"; \
+ echo "$(call gamma-path,altsrc,os_cpu/$(OS_FAMILY)_$(SRCARCH)/vm) \\"; \
+ echo "$(call gamma-path,commonsrc,os_cpu/$(OS_FAMILY)_$(SRCARCH)/vm) \\"; \
+ echo "$(call gamma-path,altsrc,os/$(OS_FAMILY)/vm) \\"; \
+ echo "$(call gamma-path,commonsrc,os/$(OS_FAMILY)/vm) \\"; \
+ echo "$(call gamma-path,altsrc,os/posix/vm) \\"; \
+ echo "$(call gamma-path,commonsrc,os/posix/vm)"; \
+ [ -n "$(CFLAGS_BROWSE)" ] && \
+ echo && echo "CFLAGS_BROWSE = $(CFLAGS_BROWSE)"; \
+ [ -n "$(HOTSPOT_EXTRA_SYSDEFS)" ] && \
+ echo && \
+ echo "HOTSPOT_EXTRA_SYSDEFS\$$(HOTSPOT_EXTRA_SYSDEFS) = $(HOTSPOT_EXTRA_SYSDEFS)" && \
+ echo "SYSDEFS += \$$(HOTSPOT_EXTRA_SYSDEFS)"; \
+ echo; \
+ echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(VARIANT).make"; \
+ echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(COMPILER).make"; \
+ ) > $@
+
+flags_vm.make: $(BUILDTREE_MAKE) ../shared_dirs.lst
+ @echo Creating $@ ...
+ $(QUIETLY) ( \
+ $(BUILDTREE_COMMENT); \
+ echo; \
+ [ "$(TARGET)" = profiled ] && \
+ echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/optimized.make"; \
+ echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(TARGET).make"; \
+ ) > $@
+
+../shared_dirs.lst: $(BUILDTREE_MAKE) $(GAMMADIR)/src/share/vm
+ @echo Creating directory list $@
+ $(QUIETLY) if [ -d $(HS_ALT_SRC)/share/vm ]; then \
+ find $(HS_ALT_SRC)/share/vm/* -prune \
+ -type d \! \( $(TOPLEVEL_EXCLUDE_DIRS) \) -exec find {} \
+ \( $(ALWAYS_EXCLUDE_DIRS) \) -prune -o -type d -print \; > $@; \
+ fi;
+ $(QUIETLY) find $(HS_COMMON_SRC)/share/vm/* -prune \
+ -type d \! \( $(TOPLEVEL_EXCLUDE_DIRS) \) -exec find {} \
+ \( $(ALWAYS_EXCLUDE_DIRS) \) -prune -o -type d -print \; >> $@
+
+Makefile: $(BUILDTREE_MAKE)
+ @echo Creating $@ ...
+ $(QUIETLY) ( \
+ $(BUILDTREE_COMMENT); \
+ echo; \
+ echo include flags.make; \
+ echo; \
+ echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/top.make"; \
+ ) > $@
+
+vm.make: $(BUILDTREE_MAKE)
+ @echo Creating $@ ...
+ $(QUIETLY) ( \
+ $(BUILDTREE_COMMENT); \
+ echo; \
+ echo include flags.make; \
+ echo include flags_vm.make; \
+ echo; \
+ echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \
+ ) > $@
+
+adlc.make: $(BUILDTREE_MAKE)
+ @echo Creating $@ ...
+ $(QUIETLY) ( \
+ $(BUILDTREE_COMMENT); \
+ echo; \
+ echo include flags.make; \
+ echo; \
+ echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \
+ ) > $@
+
+jvmti.make: $(BUILDTREE_MAKE)
+ @echo Creating $@ ...
+ $(QUIETLY) ( \
+ $(BUILDTREE_COMMENT); \
+ echo; \
+ echo include flags.make; \
+ echo; \
+ echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \
+ ) > $@
+
+sa.make: $(BUILDTREE_MAKE)
+ @echo Creating $@ ...
+ $(QUIETLY) ( \
+ $(BUILDTREE_COMMENT); \
+ echo; \
+ echo include flags.make; \
+ echo; \
+ echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \
+ ) > $@
+
+env.sh: $(BUILDTREE_MAKE)
+ @echo Creating $@ ...
+ $(QUIETLY) ( \
+ $(BUILDTREE_COMMENT); \
+ [ -n "$$JAVA_HOME" ] && { echo ": \$${JAVA_HOME:=$${JAVA_HOME}}"; }; \
+ { \
+ echo "LD_LIBRARY_PATH=.:$${LD_LIBRARY_PATH:+$$LD_LIBRARY_PATH:}\$${JAVA_HOME}/jre/lib/${LIBARCH}/native_threads:\$${JAVA_HOME}/jre/lib/${LIBARCH}:${GCC_LIB}"; \
+ echo "DYLD_LIBRARY_PATH=.:$${DYLD_LIBRARY_PATH:+$$DYLD_LIBRARY_PATH:}\$${JAVA_HOME}/jre/lib/${LIBARCH}/native_threads:\$${JAVA_HOME}/jre/lib/${LIBARCH}:${GCC_LIB}"; \
+ echo "CLASSPATH=$${CLASSPATH:+$$CLASSPATH:}.:\$${JAVA_HOME}/jre/lib/rt.jar:\$${JAVA_HOME}/jre/lib/i18n.jar"; \
+ } | sed s:$${JAVA_HOME:--------}:\$${JAVA_HOME}:g; \
+ echo "HOTSPOT_BUILD_USER=\"$${LOGNAME:-$$USER} in `basename $(GAMMADIR)`\""; \
+ echo "export JAVA_HOME LD_LIBRARY_PATH DYLD_LIBRARY_PATH CLASSPATH HOTSPOT_BUILD_USER"; \
+ ) > $@
+
+env.csh: env.sh
+ @echo Creating $@ ...
+ $(QUIETLY) ( \
+ $(BUILDTREE_COMMENT); \
+ [ -n "$$JAVA_HOME" ] && \
+ { echo "if (! \$$?JAVA_HOME) setenv JAVA_HOME \"$$JAVA_HOME\""; }; \
+ sed -n 's/^\([A-Za-z_][A-Za-z0-9_]*\)=/setenv \1 /p' $?; \
+ ) > $@
+
+jdkpath.sh: $(BUILDTREE_MAKE)
+ @echo Creating $@ ...
+ $(QUIETLY) ( \
+ $(BUILDTREE_COMMENT); \
+ echo "JDK=${JAVA_HOME}"; \
+ ) > $@
+
+.dbxrc: $(BUILDTREE_MAKE)
+ @echo Creating $@ ...
+ $(QUIETLY) ( \
+ echo "echo '# Loading $(PLATFORM_DIR)/$(TARGET)/.dbxrc'"; \
+ echo "if [ -f \"\$${HOTSPOT_DBXWARE}\" ]"; \
+ echo "then"; \
+ echo " source \"\$${HOTSPOT_DBXWARE}\""; \
+ echo "elif [ -f \"\$$HOME/.dbxrc\" ]"; \
+ echo "then"; \
+ echo " source \"\$$HOME/.dbxrc\""; \
+ echo "fi"; \
+ ) > $@
+
+# Skip the test for product builds (which only work when installed in a JDK), to
+# avoid exiting with an error and causing make to halt.
+NO_TEST_MSG = \
+ echo "$@: skipping the test--this build must be tested in a JDK."
+
+NO_JAVA_HOME_MSG = \
+ echo "JAVA_HOME must be set to run this test."
+
+DATA_MODE = $(DATA_MODE/$(BUILDARCH))
+JAVA_FLAG = $(JAVA_FLAG/$(DATA_MODE))
+
+DATA_MODE/i486 = 32
+DATA_MODE/sparc = 32
+DATA_MODE/sparcv9 = 64
+DATA_MODE/amd64 = 64
+DATA_MODE/ia64 = 64
+DATA_MODE/zero = $(ARCH_DATA_MODEL)
+
+JAVA_FLAG/32 = -d32
+JAVA_FLAG/64 = -d64
+
+WRONG_DATA_MODE_MSG = \
+ echo "JAVA_HOME must point to $(DATA_MODE)bit JDK."
+
+CROSS_COMPILING_MSG = \
+ echo "Cross compiling for ARCH $(CROSS_COMPILE_ARCH), skipping gamma run."
+
+test_gamma: $(BUILDTREE_MAKE) $(GAMMADIR)/make/test/Queens.java
+ @echo Creating $@ ...
+ $(QUIETLY) ( \
+ echo '#!/bin/sh'; \
+ $(BUILDTREE_COMMENT); \
+ echo '. ./env.sh'; \
+ echo "exit 0;"; \
+ echo "if [ \"$(CROSS_COMPILE_ARCH)\" != \"\" ]; then { $(CROSS_COMPILING_MSG); exit 0; }; fi"; \
+ echo "if [ -z \$$JAVA_HOME ]; then { $(NO_JAVA_HOME_MSG); exit 0; }; fi"; \
+ echo "if ! \$${JAVA_HOME}/bin/java $(JAVA_FLAG) -fullversion 2>&1 > /dev/null"; \
+ echo "then"; \
+ echo " $(WRONG_DATA_MODE_MSG); exit 0;"; \
+ echo "fi"; \
+ echo "rm -f Queens.class"; \
+ echo "\$${JAVA_HOME}/bin/javac -d . $(GAMMADIR)/make/test/Queens.java"; \
+ echo '[ -f gamma_g ] && { gamma=gamma_g; }'; \
+ echo './$${gamma:-gamma} $(TESTFLAGS) Queens < /dev/null'; \
+ ) > $@
+ $(QUIETLY) chmod +x $@
+
+FORCE:
+
+.PHONY: all FORCE
diff --git a/make/bsd/makefiles/compiler1.make b/make/bsd/makefiles/compiler1.make
new file mode 100644
index 000000000..0057814a0
--- /dev/null
+++ b/make/bsd/makefiles/compiler1.make
@@ -0,0 +1,31 @@
+#
+# Copyright (c) 1999, 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.
+#
+# 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.
+#
+#
+
+# Sets make macros for making client version of VM
+
+TYPE=COMPILER1
+
+VM_SUBDIR = client
+
+CFLAGS += -DCOMPILER1
diff --git a/make/bsd/makefiles/compiler2.make b/make/bsd/makefiles/compiler2.make
new file mode 100644
index 000000000..c88107988
--- /dev/null
+++ b/make/bsd/makefiles/compiler2.make
@@ -0,0 +1,31 @@
+#
+# Copyright (c) 1999, 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.
+#
+# 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.
+#
+#
+
+# Sets make macros for making server version of VM
+
+TYPE=COMPILER2
+
+VM_SUBDIR = server
+
+CFLAGS += -DCOMPILER2
diff --git a/make/bsd/makefiles/core.make b/make/bsd/makefiles/core.make
new file mode 100644
index 000000000..e032d964f
--- /dev/null
+++ b/make/bsd/makefiles/core.make
@@ -0,0 +1,33 @@
+#
+# 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.
+#
+# 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.
+#
+#
+
+# Sets make macros for making core version of VM
+
+# Select which files to use (in top.make)
+TYPE=CORE
+
+# There is no "core" directory in JDK. Install core build in server directory.
+VM_SUBDIR = server
+
+# Note: macros.hpp defines CORE
diff --git a/make/bsd/makefiles/cscope.make b/make/bsd/makefiles/cscope.make
new file mode 100644
index 000000000..7a12b3bbc
--- /dev/null
+++ b/make/bsd/makefiles/cscope.make
@@ -0,0 +1,160 @@
+#
+# Copyright (c) 2005, 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.
+#
+# 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.
+#
+#
+
+#
+# The cscope.out file is made in the current directory and spans the entire
+# source tree.
+#
+# Things to note:
+# 1. We use relative names for cscope.
+# 2. We *don't* remove the old cscope.out file, because cscope is smart
+# enough to only build what has changed. It can be confused, however,
+# if files are renamed or removed, so it may be necessary to manually
+# remove cscope.out if a lot of reorganization has occurred.
+#
+
+include $(GAMMADIR)/make/scm.make
+
+NAWK = awk
+RM = rm -f
+HG = hg
+CS_TOP = ../..
+
+CSDIRS = $(CS_TOP)/src $(CS_TOP)/build
+CSINCS = $(CSDIRS:%=-I%)
+
+CSCOPE = cscope
+CSCOPE_FLAGS = -b
+
+# Allow .java files to be added from the environment (CSCLASSES=yes).
+ifdef CSCLASSES
+ADDCLASSES= -o -name '*.java'
+endif
+
+# Adding CClassHeaders also pushes the file count of a full workspace up about
+# 200 files (these files also don't exist in a new workspace, and thus will
+# cause the recreation of the database as they get created, which might seem
+# a little confusing). Thus allow these files to be added from the environment
+# (CSHEADERS=yes).
+ifndef CSHEADERS
+RMCCHEADERS= -o -name CClassHeaders
+endif
+
+# Use CS_GENERATED=x to include auto-generated files in the build directories.
+ifdef CS_GENERATED
+CS_ADD_GENERATED = -o -name '*.incl'
+else
+CS_PRUNE_GENERATED = -o -name '${OS}_*_core' -o -name '${OS}_*_compiler?'
+endif
+
+# OS-specific files for other systems are excluded by default. Use CS_OS=yes
+# to include platform-specific files for other platforms.
+ifndef CS_OS
+CS_OS = linux macos solaris win32 bsd
+CS_PRUNE_OS = $(patsubst %,-o -name '*%*',$(filter-out ${OS},${CS_OS}))
+endif
+
+# Processor-specific files for other processors are excluded by default. Use
+# CS_CPU=x to include platform-specific files for other platforms.
+ifndef CS_CPU
+CS_CPU = i486 sparc amd64 ia64
+CS_PRUNE_CPU = $(patsubst %,-o -name '*%*',$(filter-out ${SRCARCH},${CS_CPU}))
+endif
+
+# What files should we include? A simple rule might be just those files under
+# SCCS control, however this would miss files we create like the opcodes and
+# CClassHeaders. The following attempts to find everything that is *useful*.
+# (.del files are created by sccsrm, demo directories contain many .java files
+# that probably aren't useful for development, and the pkgarchive may contain
+# duplicates of files within the source hierarchy).
+
+# Directories to exclude.
+CS_PRUNE_STD = $(SCM_DIRS) \
+ -o -name '.del-*' \
+ -o -name '*demo' \
+ -o -name pkgarchive
+
+CS_PRUNE = $(CS_PRUNE_STD) \
+ $(CS_PRUNE_OS) \
+ $(CS_PRUNE_CPU) \
+ $(CS_PRUNE_GENERATED) \
+ $(RMCCHEADERS)
+
+# File names to include.
+CSFILENAMES = -name '*.[ch]pp' \
+ -o -name '*.[Ccshlxy]' \
+ $(CS_ADD_GENERATED) \
+ -o -name '*.il' \
+ -o -name '*.cc' \
+ -o -name '*[Mm]akefile*' \
+ -o -name '*.gmk' \
+ -o -name '*.make' \
+ -o -name '*.ad' \
+ $(ADDCLASSES)
+
+.PRECIOUS: cscope.out
+
+cscope cscope.out: cscope.files FORCE
+ $(CSCOPE) $(CSCOPE_FLAGS)
+
+# The .raw file is reordered here in an attempt to make cscope display the most
+# relevant files first.
+cscope.files: .cscope.files.raw
+ echo "$(CSINCS)" > $@
+ -egrep -v "\.java|\/make\/" $< >> $@
+ -fgrep ".java" $< >> $@
+ -fgrep "/make/" $< >> $@
+
+.cscope.files.raw: .nametable.files
+ -find $(CSDIRS) -type d \( $(CS_PRUNE) \) -prune -o \
+ -type f \( $(CSFILENAMES) \) -print > $@
+
+cscope.clean: nametable.clean
+ -$(RM) cscope.out cscope.files .cscope.files.raw
+
+TAGS: cscope.files FORCE
+ egrep -v '^-|^$$' $< | etags --members -
+
+TAGS.clean: nametable.clean
+ -$(RM) TAGS
+
+# .nametable.files and .nametable.files.tmp are used to determine if any files
+# were added to/deleted from/renamed in the workspace. If not, then there's
+# normally no need to rebuild the cscope database. To force a rebuild of
+# the cscope database: gmake nametable.clean.
+.nametable.files: .nametable.files.tmp
+ ( cmp -s $@ $< ) || ( cp $< $@ )
+ -$(RM) $<
+
+# `hg status' is slightly faster than `hg fstatus'. Both are
+# quite a bit slower on an NFS mounted file system, so this is
+# really geared towards repos on local file systems.
+.nametable.files.tmp:
+ -$(HG) fstatus -acmn > $@
+nametable.clean:
+ -$(RM) .nametable.files .nametable.files.tmp
+
+FORCE:
+
+.PHONY: cscope cscope.clean TAGS.clean nametable.clean FORCE
diff --git a/make/bsd/makefiles/debug.make b/make/bsd/makefiles/debug.make
new file mode 100644
index 000000000..f0aec1797
--- /dev/null
+++ b/make/bsd/makefiles/debug.make
@@ -0,0 +1,44 @@
+#
+# Copyright (c) 1999, 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.
+#
+# 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.
+#
+#
+
+# Sets make macros for making debug version of VM
+
+# Compiler specific DEBUG_CFLAGS are passed in from gcc.make, sparcWorks.make
+DEBUG_CFLAGS/DEFAULT= $(DEBUG_CFLAGS)
+DEBUG_CFLAGS/BYFILE = $(DEBUG_CFLAGS/$@)$(DEBUG_CFLAGS/DEFAULT$(DEBUG_CFLAGS/$@))
+CFLAGS += $(DEBUG_CFLAGS/BYFILE)
+
+# Linker mapfile
+MAPFILE = $(GAMMADIR)/make/bsd/makefiles/mapfile-vers-debug
+
+_JUNK_ := $(shell echo -e >&2 ""\
+ "----------------------------------------------------------------------\n" \
+ "WARNING: 'make debug' is deprecated. It will be removed in the future.\n" \
+ "Please use 'make jvmg' to build debug JVM. \n" \
+ "----------------------------------------------------------------------\n")
+
+G_SUFFIX = _g
+VERSION = debug
+SYSDEFS += -DASSERT -DDEBUG
+PICFLAGS = DEFAULT
diff --git a/make/bsd/makefiles/defs.make b/make/bsd/makefiles/defs.make
new file mode 100644
index 000000000..7911365ed
--- /dev/null
+++ b/make/bsd/makefiles/defs.make
@@ -0,0 +1,170 @@
+#
+# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+#
+
+# The common definitions for hotspot bsd builds.
+# Include the top level defs.make under make directory instead of this one.
+# This file is included into make/defs.make.
+
+SLASH_JAVA ?= /java
+
+# Need PLATFORM (os-arch combo names) for jdk and hotspot, plus libarch name
+ARCH:=$(shell uname -m)
+PATH_SEP = :
+ifeq ($(LP64), 1)
+ ARCH_DATA_MODEL ?= 64
+else
+ ARCH_DATA_MODEL ?= 32
+endif
+
+# zero
+ifeq ($(ZERO_BUILD), true)
+ ifeq ($(ARCH_DATA_MODEL), 64)
+ MAKE_ARGS += LP64=1
+ endif
+ PLATFORM = bsd-zero
+ VM_PLATFORM = bsd_$(subst i386,i486,$(ZERO_LIBARCH))
+ HS_ARCH = zero
+ ARCH = zero
+endif
+
+# ia64
+ifeq ($(ARCH), ia64)
+ ARCH_DATA_MODEL = 64
+ MAKE_ARGS += LP64=1
+ PLATFORM = bsd-ia64
+ VM_PLATFORM = bsd_ia64
+ HS_ARCH = ia64
+endif
+
+# sparc
+ifeq ($(ARCH), sparc64)
+ ifeq ($(ARCH_DATA_MODEL), 64)
+ ARCH_DATA_MODEL = 64
+ MAKE_ARGS += LP64=1
+ PLATFORM = bsd-sparcv9
+ VM_PLATFORM = bsd_sparcv9
+ else
+ ARCH_DATA_MODEL = 32
+ PLATFORM = bsd-sparc
+ VM_PLATFORM = bsd_sparc
+ endif
+ HS_ARCH = sparc
+endif
+
+# amd64
+ifneq (,$(findstring $(ARCH), amd64 x86_64))
+ ifeq ($(ARCH_DATA_MODEL), 64)
+ ARCH_DATA_MODEL = 64
+ MAKE_ARGS += LP64=1
+ PLATFORM = bsd-amd64
+ VM_PLATFORM = bsd_amd64
+ HS_ARCH = x86
+ else
+ ARCH_DATA_MODEL = 32
+ PLATFORM = bsd-i586
+ VM_PLATFORM = bsd_i486
+ HS_ARCH = x86
+ # We have to reset ARCH to i386 since SRCARCH relies on it
+ ARCH = i386
+ endif
+endif
+
+# i386
+ifeq ($(ARCH), i386)
+ ifeq ($(ARCH_DATA_MODEL), 64)
+ ARCH_DATA_MODEL = 64
+ MAKE_ARGS += LP64=1
+ PLATFORM = bsd-amd64
+ VM_PLATFORM = bsd_amd64
+ HS_ARCH = x86
+ # We have to reset ARCH to amd64 since SRCARCH relies on it
+ ARCH = amd64
+ else
+ ARCH_DATA_MODEL = 32
+ PLATFORM = bsd-i586
+ VM_PLATFORM = bsd_i486
+ HS_ARCH = x86
+ endif
+endif
+
+# ARM
+ifeq ($(ARCH), arm)
+ ARCH_DATA_MODEL = 32
+ PLATFORM = bsd-arm
+ VM_PLATFORM = bsd_arm
+ HS_ARCH = arm
+endif
+
+# PPC
+ifeq ($(ARCH), ppc)
+ ARCH_DATA_MODEL = 32
+ PLATFORM = bsd-ppc
+ VM_PLATFORM = bsd_ppc
+ HS_ARCH = ppc
+endif
+
+JDK_INCLUDE_SUBDIR=bsd
+
+# Library suffix
+OS_VENDOR:=$(shell uname -s)
+ifeq ($(OS_VENDOR),Darwin)
+ LIBRARY_SUFFIX=dylib
+else
+ LIBRARY_SUFFIX=so
+endif
+
+# FIXUP: The subdirectory for a debug build is NOT the same on all platforms
+VM_DEBUG=jvmg
+
+EXPORT_LIST += $(EXPORT_DOCS_DIR)/platform/jvmti/jvmti.html
+
+# client and server subdirectories have symbolic links to ../libjsig.so
+EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libjsig.$(LIBRARY_SUFFIX)
+EXPORT_SERVER_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/server
+
+ifndef BUILD_CLIENT_ONLY
+EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt
+EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.$(LIBRARY_SUFFIX)
+endif
+
+ifneq ($(ZERO_BUILD), true)
+ ifeq ($(ARCH_DATA_MODEL), 32)
+ EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client
+ EXPORT_LIST += $(EXPORT_CLIENT_DIR)/Xusage.txt
+ EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.$(LIBRARY_SUFFIX)
+ endif
+endif
+
+# Serviceability Binaries
+# No SA Support for PPC, IA64, ARM or zero
+ADD_SA_BINARIES/x86 = $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.$(LIBRARY_SUFFIX) \
+ $(EXPORT_LIB_DIR)/sa-jdi.jar
+ADD_SA_BINARIES/sparc = $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.$(LIBRARY_SUFFIX) \
+ $(EXPORT_LIB_DIR)/sa-jdi.jar
+ADD_SA_BINARIES/ppc =
+ADD_SA_BINARIES/ia64 =
+ADD_SA_BINARIES/arm =
+ADD_SA_BINARIES/zero =
+
+EXPORT_LIST += $(ADD_SA_BINARIES/$(HS_ARCH))
diff --git a/make/bsd/makefiles/dtrace.make b/make/bsd/makefiles/dtrace.make
new file mode 100644
index 000000000..6ee23a387
--- /dev/null
+++ b/make/bsd/makefiles/dtrace.make
@@ -0,0 +1,27 @@
+#
+# Copyright (c) 2005, 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.
+#
+# 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.
+#
+#
+
+# Bsd does not build jvm_db
+LIBJVM_DB =
+
diff --git a/make/bsd/makefiles/fastdebug.make b/make/bsd/makefiles/fastdebug.make
new file mode 100644
index 000000000..c550d9bdd
--- /dev/null
+++ b/make/bsd/makefiles/fastdebug.make
@@ -0,0 +1,64 @@
+#
+# Copyright (c) 1999, 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.
+#
+# 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.
+#
+#
+
+# Sets make macros for making debug version of VM
+
+# Compiler specific OPT_CFLAGS are passed in from gcc.make, sparcWorks.make
+OPT_CFLAGS/DEFAULT= $(OPT_CFLAGS)
+OPT_CFLAGS/BYFILE = $(OPT_CFLAGS/$@)$(OPT_CFLAGS/DEFAULT$(OPT_CFLAGS/$@))
+
+# (OPT_CFLAGS/SLOWER is also available, to alter compilation of buggy files)
+
+ifeq ($(BUILDARCH), ia64)
+ # Bug in GCC, causes hang. -O1 will override the -O3 specified earlier
+ OPT_CFLAGS/callGenerator.o += -O1
+ OPT_CFLAGS/ciTypeFlow.o += -O1
+ OPT_CFLAGS/compile.o += -O1
+ OPT_CFLAGS/concurrentMarkSweepGeneration.o += -O1
+ OPT_CFLAGS/doCall.o += -O1
+ OPT_CFLAGS/generateOopMap.o += -O1
+ OPT_CFLAGS/generateOptoStub.o += -O1
+ OPT_CFLAGS/graphKit.o += -O1
+ OPT_CFLAGS/instanceKlass.o += -O1
+ OPT_CFLAGS/interpreterRT_ia64.o += -O1
+ OPT_CFLAGS/output.o += -O1
+ OPT_CFLAGS/parse1.o += -O1
+ OPT_CFLAGS/runtime.o += -O1
+ OPT_CFLAGS/synchronizer.o += -O1
+endif
+
+
+# If you set HOTSPARC_GENERIC=yes, you disable all OPT_CFLAGS settings
+CFLAGS$(HOTSPARC_GENERIC) += $(OPT_CFLAGS/BYFILE)
+
+# Set the environment variable HOTSPARC_GENERIC to "true"
+# to inhibit the effect of the previous line on CFLAGS.
+
+# Linker mapfile
+MAPFILE = $(GAMMADIR)/make/bsd/makefiles/mapfile-vers-debug
+
+G_SUFFIX = _g
+VERSION = optimized
+SYSDEFS += -DASSERT -DFASTDEBUG
+PICFLAGS = DEFAULT
diff --git a/make/bsd/makefiles/gcc.make b/make/bsd/makefiles/gcc.make
new file mode 100644
index 000000000..3b340dc92
--- /dev/null
+++ b/make/bsd/makefiles/gcc.make
@@ -0,0 +1,267 @@
+#
+# Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+#
+
+OS_VENDOR = $(shell uname -s)
+
+#------------------------------------------------------------------------
+# CC, CPP & AS
+
+# When cross-compiling the ALT_COMPILER_PATH points
+# to the cross-compilation toolset
+ifdef CROSS_COMPILE_ARCH
+CXX = $(ALT_COMPILER_PATH)/g++
+CPP = $(ALT_COMPILER_PATH)/g++
+CC = $(ALT_COMPILER_PATH)/gcc
+HOSTCPP = g++
+HOSTCC = gcc
+else
+CXX ?= g++
+CPP = $(CXX)
+CC ?= gcc
+HOSTCPP = $(CPP)
+HOSTCC = $(CPP)
+endif
+
+AS = $(CC) -c -x assembler-with-cpp
+
+# -dumpversion in gcc-2.91 shows "egcs-2.91.66". In later version, it only
+# prints the numbers (e.g. "2.95", "3.2.1")
+CC_VER_MAJOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f1)
+CC_VER_MINOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f2)
+
+# check for precompiled headers support
+ifneq "$(shell expr \( $(CC_VER_MAJOR) \> 3 \) \| \( \( $(CC_VER_MAJOR) = 3 \) \& \( $(CC_VER_MINOR) \>= 4 \) \))" "0"
+# Allow the user to turn off precompiled headers from the command line.
+ifneq ($(USE_PRECOMPILED_HEADER),0)
+USE_PRECOMPILED_HEADER=1
+PRECOMPILED_HEADER_DIR=.
+PRECOMPILED_HEADER_SRC=$(GAMMADIR)/src/share/vm/precompiled.hpp
+PRECOMPILED_HEADER=$(PRECOMPILED_HEADER_DIR)/precompiled.hpp.gch
+endif
+endif
+
+
+#------------------------------------------------------------------------
+# Compiler flags
+
+# position-independent code
+PICFLAG = -fPIC
+
+VM_PICFLAG/LIBJVM = $(PICFLAG)
+VM_PICFLAG/AOUT =
+VM_PICFLAG = $(VM_PICFLAG/$(LINK_INTO))
+
+ifeq ($(ZERO_BUILD), true)
+CFLAGS += $(LIBFFI_CFLAGS)
+endif
+ifeq ($(SHARK_BUILD), true)
+CFLAGS += $(LLVM_CFLAGS)
+endif
+CFLAGS += $(VM_PICFLAG)
+CFLAGS += -fno-rtti
+CFLAGS += -fno-exceptions
+CFLAGS += -pthread
+CFLAGS += -fcheck-new
+# version 4 and above support fvisibility=hidden (matches jni_x86.h file)
+# except 4.1.2 gives pointless warnings that can't be disabled (afaik)
+ifneq "$(shell expr \( $(CC_VER_MAJOR) \> 4 \) \| \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) \>= 3 \) \))" "0"
+CFLAGS += -fvisibility=hidden
+endif
+
+ARCHFLAG = $(ARCHFLAG/$(BUILDARCH))
+ARCHFLAG/i486 = -m32 -march=i586
+ARCHFLAG/amd64 = -m64
+ARCHFLAG/ia64 =
+ARCHFLAG/sparc = -m32 -mcpu=v9
+ARCHFLAG/sparcv9 = -m64 -mcpu=v9
+ARCHFLAG/zero = $(ZERO_ARCHFLAG)
+
+# Darwin-specific build flags
+ifeq ($(OS_VENDOR), Darwin)
+ # Ineffecient 16-byte stack re-alignment on Darwin/IA32
+ ARCHFLAG/i486 += -mstackrealign
+endif
+
+CFLAGS += $(ARCHFLAG)
+AOUT_FLAGS += $(ARCHFLAG)
+LFLAGS += $(ARCHFLAG)
+ASFLAGS += $(ARCHFLAG)
+
+ifdef E500V2
+CFLAGS += -DE500V2
+endif
+
+# Use C++ Interpreter
+ifdef CC_INTERP
+ CFLAGS += -DCC_INTERP
+endif
+
+# Build for embedded targets
+ifdef JAVASE_EMBEDDED
+ CFLAGS += -DJAVASE_EMBEDDED
+endif
+
+# Keep temporary files (.ii, .s)
+ifdef NEED_ASM
+ CFLAGS += -save-temps
+else
+ CFLAGS += -pipe
+endif
+
+# Compiler warnings are treated as errors
+WARNINGS_ARE_ERRORS = -Werror
+
+# Except for a few acceptable ones
+# Since GCC 4.3, -Wconversion has changed its meanings to warn these implicit
+# conversions which might affect the values. To avoid that, we need to turn
+# it off explicitly.
+ifneq "$(shell expr \( $(CC_VER_MAJOR) \> 4 \) \| \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) \>= 3 \) \))" "0"
+ACCEPTABLE_WARNINGS = -Wpointer-arith -Wsign-compare
+else
+ACCEPTABLE_WARNINGS = -Wpointer-arith -Wconversion -Wsign-compare
+endif
+
+CFLAGS_WARN/DEFAULT = $(WARNINGS_ARE_ERRORS) $(ACCEPTABLE_WARNINGS)
+# Special cases
+CFLAGS_WARN/BYFILE = $(CFLAGS_WARN/$@)$(CFLAGS_WARN/DEFAULT$(CFLAGS_WARN/$@))
+# XXXDARWIN: for _dyld_bind_fully_image_containing_address
+ifeq ($(OS_VENDOR), Darwin)
+ CFLAGS_WARN/os_bsd.o = $(CFLAGS_WARN/DEFAULT) -Wno-deprecated-declarations
+endif
+
+
+# The flags to use for an Optimized g++ build
+OPT_CFLAGS += -O3
+
+# Hotspot uses very unstrict aliasing turn this optimization off
+OPT_CFLAGS += -fno-strict-aliasing
+
+# The gcc compiler segv's on ia64 when compiling bytecodeInterpreter.cpp
+# if we use expensive-optimizations
+ifeq ($(BUILDARCH), ia64)
+OPT_CFLAGS += -fno-expensive-optimizations
+endif
+
+OPT_CFLAGS/NOOPT=-O0
+
+# 6835796. Problem in GCC 4.3.0 with mulnode.o optimized compilation.
+ifneq "$(shell expr \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) = 3 \) \))" "0"
+OPT_CFLAGS/mulnode.o += -O0
+endif
+
+# Flags for generating make dependency flags.
+ifneq ("${CC_VER_MAJOR}", "2")
+DEPFLAGS = -MMD -MP -MF $(DEP_DIR)/$(@:%=%.d)
+endif
+
+# -DDONT_USE_PRECOMPILED_HEADER will exclude all includes in precompiled.hpp.
+ifneq ($(USE_PRECOMPILED_HEADER),1)
+CFLAGS += -DDONT_USE_PRECOMPILED_HEADER
+endif
+
+#------------------------------------------------------------------------
+# Linker flags
+
+# statically link libstdc++.so, work with gcc but ignored by g++
+STATIC_STDCXX = -Wl,-Bstatic -lstdc++ -Wl,-Bdynamic
+
+# statically link libgcc and/or libgcc_s, libgcc does not exist before gcc-3.x.
+ifneq ("${CC_VER_MAJOR}", "2")
+STATIC_LIBGCC += -static-libgcc
+endif
+
+ifeq ($(BUILDARCH), ia64)
+LFLAGS += -Wl,-relax
+endif
+
+# Use $(MAPFLAG:FILENAME=real_file_name) to specify a map file.
+MAPFLAG = -Xlinker --version-script=FILENAME
+
+#
+# Shared Library
+#
+ifeq ($(OS_VENDOR), Darwin)
+ # Standard linker flags
+ LFLAGS +=
+
+ # Darwin doesn't use ELF and doesn't support version scripts
+ LDNOMAP = true
+
+ # Use $(SONAMEFLAG:SONAME=soname) to specify the intrinsic name of a shared obj
+ SONAMEFLAG =
+
+ # Build shared library
+ SHARED_FLAG = -dynamiclib $(VM_PICFLAG)
+
+ # Keep symbols even they are not used
+ #AOUT_FLAGS += -Xlinker -export-dynamic
+else
+ # Enable linker optimization
+ LFLAGS += -Xlinker -O1
+
+ # Use $(SONAMEFLAG:SONAME=soname) to specify the intrinsic name of a shared obj
+ SONAMEFLAG = -Xlinker -soname=SONAME
+
+ # Build shared library
+ SHARED_FLAG = -shared $(VM_PICFLAG)
+
+ # Keep symbols even they are not used
+ AOUT_FLAGS += -Xlinker -export-dynamic
+endif
+
+#------------------------------------------------------------------------
+# Debug flags
+
+# Use the stabs format for debugging information (this is the default
+# on gcc-2.91). It's good enough, has all the information about line
+# numbers and local variables, and libjvm_g.so is only about 16M.
+# Change this back to "-g" if you want the most expressive format.
+# (warning: that could easily inflate libjvm_g.so to 150M!)
+# Note: The Itanium gcc compiler crashes when using -gstabs.
+DEBUG_CFLAGS/ia64 = -g
+DEBUG_CFLAGS/amd64 = -g
+DEBUG_CFLAGS/arm = -g
+DEBUG_CFLAGS/ppc = -g
+DEBUG_CFLAGS += $(DEBUG_CFLAGS/$(BUILDARCH))
+ifeq ($(DEBUG_CFLAGS/$(BUILDARCH)),)
+DEBUG_CFLAGS += -gstabs
+endif
+
+# DEBUG_BINARIES overrides everything, use full -g debug information
+ifeq ($(DEBUG_BINARIES), true)
+ DEBUG_CFLAGS = -g
+ CFLAGS += $(DEBUG_CFLAGS)
+endif
+
+# If we are building HEADLESS, pass on to VM
+# so it can set the java.awt.headless property
+ifdef HEADLESS
+CFLAGS += -DHEADLESS
+endif
+
+# We are building Embedded for a small device
+# favor code space over speed
+ifdef MINIMIZE_RAM_USAGE
+CFLAGS += -DMINIMIZE_RAM_USAGE
+endif
diff --git a/make/bsd/makefiles/hp.make b/make/bsd/makefiles/hp.make
new file mode 100644
index 000000000..e0b262a8f
--- /dev/null
+++ b/make/bsd/makefiles/hp.make
@@ -0,0 +1,29 @@
+#
+# Copyright (c) 1999, 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.
+#
+# 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.
+#
+#
+
+# Sets make macros for making premium version of VM
+
+TYPE=HP
+
+CFLAGS += -DCOMPILER2
diff --git a/make/bsd/makefiles/hp1.make b/make/bsd/makefiles/hp1.make
new file mode 100644
index 000000000..2e37a6ead
--- /dev/null
+++ b/make/bsd/makefiles/hp1.make
@@ -0,0 +1,29 @@
+#
+# Copyright (c) 1999, 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.
+#
+# 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.
+#
+#
+
+# Sets make macros for making premium version of VM
+
+TYPE=HP1
+
+CFLAGS += -DCOMPILER1
diff --git a/make/bsd/makefiles/i486.make b/make/bsd/makefiles/i486.make
new file mode 100644
index 000000000..86e825d3e
--- /dev/null
+++ b/make/bsd/makefiles/i486.make
@@ -0,0 +1,34 @@
+#
+# 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.
+#
+# 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.
+#
+#
+
+# TLS helper, assembled from .s file
+
+# The copied fdlibm routines in sharedRuntimeTrig.o must not be optimized
+OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/NOOPT)
+# The copied fdlibm routines in sharedRuntimeTrans.o must not be optimized
+OPT_CFLAGS/sharedRuntimeTrans.o = $(OPT_CFLAGS/NOOPT)
+# Must also specify if CPU is little endian
+CFLAGS += -DVM_LITTLE_ENDIAN
+
+OPT_CFLAGS/compactingPermGenGen.o = -O1
diff --git a/make/bsd/makefiles/ia64.make b/make/bsd/makefiles/ia64.make
new file mode 100644
index 000000000..0fa65f270
--- /dev/null
+++ b/make/bsd/makefiles/ia64.make
@@ -0,0 +1,43 @@
+#
+# Copyright (c) 2005, 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.
+#
+# 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.
+#
+#
+
+#
+# IA64 only uses c++ based interpreter
+CFLAGS += -DCC_INTERP -D_LP64=1 -DVM_LITTLE_ENDIAN
+# Hotspot uses very unstrict aliasing turn this optimization off
+OPT_CFLAGS += -fno-strict-aliasing
+ifeq ($(VERSION),debug)
+ASM_FLAGS= -DDEBUG
+else
+ASM_FLAGS=
+endif
+# workaround gcc bug in compiling varargs
+OPT_CFLAGS/jni.o = -O0
+
+# gcc/ia64 has a bug that internal gcc functions linked with libjvm.so
+# are made public. Hiding those symbols will cause undefined symbol error
+# when VM is dropped into older JDK. We probably will need an IA64
+# mapfile to include those symbols as a workaround. Disable linker mapfile
+# for now.
+LDNOMAP=true
diff --git a/make/bsd/makefiles/jsig.make b/make/bsd/makefiles/jsig.make
new file mode 100644
index 000000000..80be20886
--- /dev/null
+++ b/make/bsd/makefiles/jsig.make
@@ -0,0 +1,67 @@
+#
+# Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+#
+
+# Rules to build signal interposition library, used by vm.make
+
+# libjsig[_g].so: signal interposition library
+JSIG = jsig
+JSIG_G = $(JSIG)$(G_SUFFIX)
+
+ifeq ($(OS_VENDOR), Darwin)
+ LIBJSIG = lib$(JSIG).dylib
+ LIBJSIG_G = lib$(JSIG_G).dylib
+else
+ LIBJSIG = lib$(JSIG).so
+ LIBJSIG_G = lib$(JSIG_G).so
+endif
+
+JSIGSRCDIR = $(GAMMADIR)/src/os/$(Platform_os_family)/vm
+
+DEST_JSIG = $(JDK_LIBDIR)/$(LIBJSIG)
+
+LIBJSIG_MAPFILE = $(MAKEFILES_DIR)/mapfile-vers-jsig
+
+# On Bsd we really dont want a mapfile, as this library is small
+# and preloaded using LD_PRELOAD, making functions private will
+# cause problems with interposing. See CR: 6466665
+# LFLAGS_JSIG += $(MAPFLAG:FILENAME=$(LIBJSIG_MAPFILE))
+
+LFLAGS_JSIG += -D_GNU_SOURCE -pthread $(LDFLAGS_HASH_STYLE)
+
+# DEBUG_BINARIES overrides everything, use full -g debug information
+ifeq ($(DEBUG_BINARIES), true)
+ JSIG_DEBUG_CFLAGS = -g
+endif
+
+$(LIBJSIG): $(JSIGSRCDIR)/jsig.c $(LIBJSIG_MAPFILE)
+ @echo Making signal interposition lib...
+ $(QUIETLY) $(CC) $(SYMFLAG) $(ARCHFLAG) $(SHARED_FLAG) $(PICFLAG) \
+ $(LFLAGS_JSIG) $(JSIG_DEBUG_CFLAGS) -o $@ $<
+ $(QUIETLY) [ -f $(LIBJSIG_G) ] || { ln -s $@ $(LIBJSIG_G); }
+
+install_jsig: $(LIBJSIG)
+ @echo "Copying $(LIBJSIG) to $(DEST_JSIG)"
+ $(QUIETLY) cp -f $(LIBJSIG) $(DEST_JSIG) && echo "Done"
+
+.PHONY: install_jsig
diff --git a/make/bsd/makefiles/jvmg.make b/make/bsd/makefiles/jvmg.make
new file mode 100644
index 000000000..8c56368d4
--- /dev/null
+++ b/make/bsd/makefiles/jvmg.make
@@ -0,0 +1,41 @@
+#
+# Copyright (c) 1999, 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.
+#
+# 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.
+#
+#
+
+# Sets make macros for making debug version of VM
+
+# Compiler specific DEBUG_CFLAGS are passed in from gcc.make, sparcWorks.make
+DEBUG_CFLAGS/DEFAULT= $(DEBUG_CFLAGS)
+DEBUG_CFLAGS/BYFILE = $(DEBUG_CFLAGS/$@)$(DEBUG_CFLAGS/DEFAULT$(DEBUG_CFLAGS/$@))
+CFLAGS += $(DEBUG_CFLAGS/BYFILE)
+
+# Set the environment variable HOTSPARC_GENERIC to "true"
+# to inhibit the effect of the previous line on CFLAGS.
+
+# Linker mapfile
+MAPFILE = $(GAMMADIR)/make/bsd/makefiles/mapfile-vers-debug
+
+G_SUFFIX = _g
+VERSION = debug
+SYSDEFS += -DASSERT -DDEBUG
+PICFLAGS = DEFAULT
diff --git a/make/bsd/makefiles/jvmti.make b/make/bsd/makefiles/jvmti.make
new file mode 100644
index 000000000..ee3cc1e22
--- /dev/null
+++ b/make/bsd/makefiles/jvmti.make
@@ -0,0 +1,117 @@
+#
+# Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+#
+
+# This makefile (jvmti.make) is included from the jvmti.make in the
+# build directories.
+#
+# It knows how to build and run the tools to generate jvmti.
+
+include $(GAMMADIR)/make/bsd/makefiles/rules.make
+
+# #########################################################################
+
+TOPDIR = $(shell echo `pwd`)
+GENERATED = $(TOPDIR)/../generated
+JvmtiOutDir = $(GENERATED)/jvmtifiles
+
+JvmtiSrcDir = $(GAMMADIR)/src/share/vm/prims
+InterpreterSrcDir = $(GAMMADIR)/src/share/vm/interpreter
+
+# set VPATH so make knows where to look for source files
+Src_Dirs_V += $(JvmtiSrcDir)
+VPATH += $(Src_Dirs_V:%=%:)
+
+JvmtiGeneratedNames = \
+ jvmtiEnv.hpp \
+ jvmtiEnter.cpp \
+ jvmtiEnterTrace.cpp \
+ jvmtiEnvRecommended.cpp \
+ bytecodeInterpreterWithChecks.cpp \
+ jvmti.h \
+
+JvmtiEnvFillSource = $(JvmtiSrcDir)/jvmtiEnvFill.java
+JvmtiEnvFillClass = $(JvmtiOutDir)/jvmtiEnvFill.class
+
+JvmtiGenSource = $(JvmtiSrcDir)/jvmtiGen.java
+JvmtiGenClass = $(JvmtiOutDir)/jvmtiGen.class
+
+JvmtiGeneratedFiles = $(JvmtiGeneratedNames:%=$(JvmtiOutDir)/%)
+
+XSLT = $(QUIETLY) $(REMOTE) $(RUN.JAVA) -classpath $(JvmtiOutDir) jvmtiGen
+
+.PHONY: all jvmtidocs clean cleanall
+
+# #########################################################################
+
+all: $(JvmtiGeneratedFiles)
+
+both = $(JvmtiGenClass) $(JvmtiSrcDir)/jvmti.xml $(JvmtiSrcDir)/jvmtiLib.xsl
+
+$(JvmtiGenClass): $(JvmtiGenSource)
+ $(QUIETLY) $(REMOTE) $(COMPILE.JAVAC) -d $(JvmtiOutDir) $(JvmtiGenSource)
+
+$(JvmtiEnvFillClass): $(JvmtiEnvFillSource)
+ $(QUIETLY) $(REMOTE) $(COMPILE.JAVAC) -d $(JvmtiOutDir) $(JvmtiEnvFillSource)
+
+$(JvmtiOutDir)/jvmtiEnter.cpp: $(both) $(JvmtiSrcDir)/jvmtiEnter.xsl
+ @echo Generating $@
+ $(XSLT) -IN $(JvmtiSrcDir)/jvmti.xml -XSL $(JvmtiSrcDir)/jvmtiEnter.xsl -OUT $(JvmtiOutDir)/jvmtiEnter.cpp -PARAM interface jvmti
+
+$(JvmtiOutDir)/bytecodeInterpreterWithChecks.cpp: $(JvmtiGenClass) $(InterpreterSrcDir)/bytecodeInterpreter.cpp $(InterpreterSrcDir)/bytecodeInterpreterWithChecks.xml $(InterpreterSrcDir)/bytecodeInterpreterWithChecks.xsl
+ @echo Generating $@
+ $(XSLT) -IN $(InterpreterSrcDir)/bytecodeInterpreterWithChecks.xml -XSL $(InterpreterSrcDir)/bytecodeInterpreterWithChecks.xsl -OUT $(JvmtiOutDir)/bytecodeInterpreterWithChecks.cpp
+
+$(JvmtiOutDir)/jvmtiEnterTrace.cpp: $(both) $(JvmtiSrcDir)/jvmtiEnter.xsl
+ @echo Generating $@
+ $(XSLT) -IN $(JvmtiSrcDir)/jvmti.xml -XSL $(JvmtiSrcDir)/jvmtiEnter.xsl -OUT $(JvmtiOutDir)/jvmtiEnterTrace.cpp -PARAM interface jvmti -PARAM trace Trace
+
+$(JvmtiOutDir)/jvmtiEnvRecommended.cpp: $(both) $(JvmtiSrcDir)/jvmtiEnv.xsl $(JvmtiSrcDir)/jvmtiEnv.cpp $(JvmtiEnvFillClass)
+ @echo Generating $@
+ $(XSLT) -IN $(JvmtiSrcDir)/jvmti.xml -XSL $(JvmtiSrcDir)/jvmtiEnv.xsl -OUT $(JvmtiOutDir)/jvmtiEnvStub.cpp
+ $(QUIETLY) $(REMOTE) $(RUN.JAVA) -classpath $(JvmtiOutDir) jvmtiEnvFill $(JvmtiSrcDir)/jvmtiEnv.cpp $(JvmtiOutDir)/jvmtiEnvStub.cpp $(JvmtiOutDir)/jvmtiEnvRecommended.cpp
+
+$(JvmtiOutDir)/jvmtiEnv.hpp: $(both) $(JvmtiSrcDir)/jvmtiHpp.xsl
+ @echo Generating $@
+ $(XSLT) -IN $(JvmtiSrcDir)/jvmti.xml -XSL $(JvmtiSrcDir)/jvmtiHpp.xsl -OUT $(JvmtiOutDir)/jvmtiEnv.hpp
+
+$(JvmtiOutDir)/jvmti.h: $(both) $(JvmtiSrcDir)/jvmtiH.xsl
+ @echo Generating $@
+ $(XSLT) -IN $(JvmtiSrcDir)/jvmti.xml -XSL $(JvmtiSrcDir)/jvmtiH.xsl -OUT $(JvmtiOutDir)/jvmti.h
+
+jvmtidocs: $(JvmtiOutDir)/jvmti.html
+
+$(JvmtiOutDir)/jvmti.html: $(both) $(JvmtiSrcDir)/jvmti.xsl
+ @echo Generating $@
+ $(XSLT) -IN $(JvmtiSrcDir)/jvmti.xml -XSL $(JvmtiSrcDir)/jvmti.xsl -OUT $(JvmtiOutDir)/jvmti.html
+
+# #########################################################################
+
+clean :
+ rm $(JvmtiGenClass) $(JvmtiEnvFillClass) $(JvmtiGeneratedFiles)
+
+cleanall :
+ rm $(JvmtiGenClass) $(JvmtiEnvFillClass) $(JvmtiGeneratedFiles)
+
+# #########################################################################
+
diff --git a/make/bsd/makefiles/launcher.make b/make/bsd/makefiles/launcher.make
new file mode 100644
index 000000000..b405fbc7f
--- /dev/null
+++ b/make/bsd/makefiles/launcher.make
@@ -0,0 +1,93 @@
+#
+# Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+#
+
+# Rules to build gamma launcher, used by vm.make
+
+
+LAUNCHER_SCRIPT = hotspot
+LAUNCHER = gamma
+
+LAUNCHERDIR := $(GAMMADIR)/src/os/posix/launcher
+LAUNCHERDIR_SHARE := $(GAMMADIR)/src/share/tools/launcher
+LAUNCHERFLAGS := $(ARCHFLAG) \
+ -I$(LAUNCHERDIR) -I$(GAMMADIR)/src/share/vm/prims \
+ -I$(LAUNCHERDIR_SHARE) \
+ -DFULL_VERSION=\"$(HOTSPOT_RELEASE_VERSION)\" \
+ -DJDK_MAJOR_VERSION=\"$(JDK_MAJOR_VERSION)\" \
+ -DJDK_MINOR_VERSION=\"$(JDK_MINOR_VERSION)\" \
+ -DARCH=\"$(LIBARCH)\" \
+ -DGAMMA \
+ -DLAUNCHER_TYPE=\"gamma\" \
+ -DLINK_INTO_$(LINK_INTO) \
+ $(TARGET_DEFINES)
+
+ifeq ($(LINK_INTO),AOUT)
+ LAUNCHER.o = launcher.o $(JVM_OBJ_FILES)
+ LAUNCHER_MAPFILE = mapfile_reorder
+ LFLAGS_LAUNCHER$(LDNOMAP) += $(MAPFLAG:FILENAME=$(LAUNCHER_MAPFILE))
+ LFLAGS_LAUNCHER += $(SONAMEFLAG:SONAME=$(LIBJVM)) $(STATIC_LIBGCC)
+ LIBS_LAUNCHER += $(STATIC_STDCXX) $(LIBS)
+else
+ LAUNCHER.o = launcher.o
+ LFLAGS_LAUNCHER += -L`pwd`
+ LIBS_LAUNCHER += -l$(JVM) $(LIBS)
+endif
+
+LINK_LAUNCHER = $(LINK.c)
+
+LINK_LAUNCHER/PRE_HOOK = $(LINK_LIB.CC/PRE_HOOK)
+LINK_LAUNCHER/POST_HOOK = $(LINK_LIB.CC/POST_HOOK)
+
+LAUNCHER_OUT = launcher
+
+SUFFIXES += .d
+
+SOURCES := $(shell find $(LAUNCHERDIR) -name "*.c")
+SOURCES_SHARE := $(shell find $(LAUNCHERDIR_SHARE) -name "*.c")
+
+OBJS := $(patsubst $(LAUNCHERDIR)/%.c,$(LAUNCHER_OUT)/%.o,$(SOURCES)) $(patsubst $(LAUNCHERDIR_SHARE)/%.c,$(LAUNCHER_OUT)/%.o,$(SOURCES_SHARE))
+
+DEPFILES := $(patsubst %.o,%.d,$(OBJS))
+-include $(DEPFILES)
+
+$(LAUNCHER_OUT)/%.o: $(LAUNCHERDIR_SHARE)/%.c
+ $(QUIETLY) [ -d $(LAUNCHER_OUT) ] || { mkdir -p $(LAUNCHER_OUT); }
+ $(QUIETLY) $(CC) -g -o $@ -c $< -MMD $(LAUNCHERFLAGS) $(CPPFLAGS)
+
+$(LAUNCHER_OUT)/%.o: $(LAUNCHERDIR)/%.c
+ $(QUIETLY) [ -d $(LAUNCHER_OUT) ] || { mkdir -p $(LAUNCHER_OUT); }
+ $(QUIETLY) $(CC) -g -o $@ -c $< -MMD $(LAUNCHERFLAGS) $(CPPFLAGS)
+
+$(LAUNCHER): $(OBJS) $(LIBJVM) $(LAUNCHER_MAPFILE)
+ $(QUIETLY) echo Linking launcher...
+ $(QUIETLY) $(LINK_LAUNCHER/PRE_HOOK)
+ $(QUIETLY) $(LINK_LAUNCHER) $(LFLAGS_LAUNCHER) -o $@ $(OBJS) $(LIBS_LAUNCHER)
+ $(QUIETLY) $(LINK_LAUNCHER/POST_HOOK)
+
+$(LAUNCHER): $(LAUNCHER_SCRIPT)
+
+$(LAUNCHER_SCRIPT): $(LAUNCHERDIR)/launcher.script
+ $(QUIETLY) sed -e 's/@@LIBARCH@@/$(LIBARCH)/g' $< > $@
+ $(QUIETLY) chmod +x $@
+
diff --git a/make/bsd/makefiles/mapfile-vers-debug b/make/bsd/makefiles/mapfile-vers-debug
new file mode 100644
index 000000000..9a2d42fb6
--- /dev/null
+++ b/make/bsd/makefiles/mapfile-vers-debug
@@ -0,0 +1,291 @@
+#
+# @(#)mapfile-vers-debug 1.18 07/10/25 16:47:35
+#
+
+#
+# Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+#
+
+# Define public interface.
+
+SUNWprivate_1.1 {
+ global:
+ # JNI
+ JNI_CreateJavaVM;
+ JNI_GetCreatedJavaVMs;
+ JNI_GetDefaultJavaVMInitArgs;
+
+ # JVM
+ JVM_Accept;
+ JVM_ActiveProcessorCount;
+ JVM_AllocateNewArray;
+ JVM_AllocateNewObject;
+ JVM_ArrayCopy;
+ JVM_AssertionStatusDirectives;
+ JVM_Available;
+ JVM_Bind;
+ JVM_ClassDepth;
+ JVM_ClassLoaderDepth;
+ JVM_Clone;
+ JVM_Close;
+ JVM_CX8Field;
+ JVM_CompileClass;
+ JVM_CompileClasses;
+ JVM_CompilerCommand;
+ JVM_Connect;
+ JVM_ConstantPoolGetClassAt;
+ JVM_ConstantPoolGetClassAtIfLoaded;
+ JVM_ConstantPoolGetDoubleAt;
+ JVM_ConstantPoolGetFieldAt;
+ JVM_ConstantPoolGetFieldAtIfLoaded;
+ JVM_ConstantPoolGetFloatAt;
+ JVM_ConstantPoolGetIntAt;
+ JVM_ConstantPoolGetLongAt;
+ JVM_ConstantPoolGetMethodAt;
+ JVM_ConstantPoolGetMethodAtIfLoaded;
+ JVM_ConstantPoolGetMemberRefInfoAt;
+ JVM_ConstantPoolGetSize;
+ JVM_ConstantPoolGetStringAt;
+ JVM_ConstantPoolGetUTF8At;
+ JVM_CountStackFrames;
+ JVM_CurrentClassLoader;
+ JVM_CurrentLoadedClass;
+ JVM_CurrentThread;
+ JVM_CurrentTimeMillis;
+ JVM_DefineClass;
+ JVM_DefineClassWithSource;
+ JVM_DefineClassWithSourceCond;
+ JVM_DesiredAssertionStatus;
+ JVM_DisableCompiler;
+ JVM_DoPrivileged;
+ JVM_DTraceGetVersion;
+ JVM_DTraceActivate;
+ JVM_DTraceIsProbeEnabled;
+ JVM_DTraceIsSupported;
+ JVM_DTraceDispose;
+ JVM_DumpAllStacks;
+ JVM_DumpThreads;
+ JVM_EnableCompiler;
+ JVM_Exit;
+ JVM_FillInStackTrace;
+ JVM_FindClassFromClass;
+ JVM_FindClassFromClassLoader;
+ JVM_FindClassFromBootLoader;
+ JVM_FindLibraryEntry;
+ JVM_FindLoadedClass;
+ JVM_FindPrimitiveClass;
+ JVM_FindSignal;
+ JVM_FreeMemory;
+ JVM_GC;
+ JVM_GetAllThreads;
+ JVM_GetArrayElement;
+ JVM_GetArrayLength;
+ JVM_GetCPClassNameUTF;
+ JVM_GetCPFieldClassNameUTF;
+ JVM_GetCPFieldModifiers;
+ JVM_GetCPFieldNameUTF;
+ JVM_GetCPFieldSignatureUTF;
+ JVM_GetCPMethodClassNameUTF;
+ JVM_GetCPMethodModifiers;
+ JVM_GetCPMethodNameUTF;
+ JVM_GetCPMethodSignatureUTF;
+ JVM_GetCallerClass;
+ JVM_GetClassAccessFlags;
+ JVM_GetClassAnnotations;
+ JVM_GetClassCPEntriesCount;
+ JVM_GetClassCPTypes;
+ JVM_GetClassConstantPool;
+ JVM_GetClassContext;
+ JVM_GetClassDeclaredConstructors;
+ JVM_GetClassDeclaredFields;
+ JVM_GetClassDeclaredMethods;
+ JVM_GetClassFieldsCount;
+ JVM_GetClassInterfaces;
+ JVM_GetClassLoader;
+ JVM_GetClassMethodsCount;
+ JVM_GetClassModifiers;
+ JVM_GetClassName;
+ JVM_GetClassNameUTF;
+ JVM_GetClassSignature;
+ JVM_GetClassSigners;
+ JVM_GetComponentType;
+ JVM_GetDeclaredClasses;
+ JVM_GetDeclaringClass;
+ JVM_GetEnclosingMethodInfo;
+ JVM_GetFieldAnnotations;
+ JVM_GetFieldIxModifiers;
+ JVM_GetHostName;
+ JVM_GetInheritedAccessControlContext;
+ JVM_GetInterfaceVersion;
+ JVM_GetLastErrorString;
+ JVM_GetManagement;
+ JVM_GetMethodAnnotations;
+ JVM_GetMethodDefaultAnnotationValue;
+ JVM_GetMethodIxArgsSize;
+ JVM_GetMethodIxByteCode;
+ JVM_GetMethodIxByteCodeLength;
+ JVM_GetMethodIxExceptionIndexes;
+ JVM_GetMethodIxExceptionTableEntry;
+ JVM_GetMethodIxExceptionTableLength;
+ JVM_GetMethodIxExceptionsCount;
+ JVM_GetMethodIxLocalsCount;
+ JVM_GetMethodIxMaxStack;
+ JVM_GetMethodIxModifiers;
+ JVM_GetMethodIxNameUTF;
+ JVM_GetMethodIxSignatureUTF;
+ JVM_GetMethodParameterAnnotations;
+ JVM_GetPrimitiveArrayElement;
+ JVM_GetProtectionDomain;
+ JVM_GetSockName;
+ JVM_GetSockOpt;
+ JVM_GetStackAccessControlContext;
+ JVM_GetStackTraceDepth;
+ JVM_GetStackTraceElement;
+ JVM_GetSystemPackage;
+ JVM_GetSystemPackages;
+ JVM_GetThreadStateNames;
+ JVM_GetThreadStateValues;
+ JVM_GetVersionInfo;
+ JVM_Halt;
+ JVM_HoldsLock;
+ JVM_IHashCode;
+ JVM_InitAgentProperties;
+ JVM_InitProperties;
+ JVM_InitializeCompiler;
+ JVM_InitializeSocketLibrary;
+ JVM_InternString;
+ JVM_Interrupt;
+ JVM_InvokeMethod;
+ JVM_IsArrayClass;
+ JVM_IsConstructorIx;
+ JVM_IsInterface;
+ JVM_IsInterrupted;
+ JVM_IsNaN;
+ JVM_IsPrimitiveClass;
+ JVM_IsSameClassPackage;
+ JVM_IsSilentCompiler;
+ JVM_IsSupportedJNIVersion;
+ JVM_IsThreadAlive;
+ JVM_LatestUserDefinedLoader;
+ JVM_Listen;
+ JVM_LoadClass0;
+ JVM_LoadLibrary;
+ JVM_Lseek;
+ JVM_MaxObjectInspectionAge;
+ JVM_MaxMemory;
+ JVM_MonitorNotify;
+ JVM_MonitorNotifyAll;
+ JVM_MonitorWait;
+ JVM_NanoTime;
+ JVM_NativePath;
+ JVM_NewArray;
+ JVM_NewInstanceFromConstructor;
+ JVM_NewMultiArray;
+ JVM_OnExit;
+ JVM_Open;
+ JVM_PrintStackTrace;
+ JVM_RaiseSignal;
+ JVM_RawMonitorCreate;
+ JVM_RawMonitorDestroy;
+ JVM_RawMonitorEnter;
+ JVM_RawMonitorExit;
+ JVM_Read;
+ JVM_Recv;
+ JVM_RecvFrom;
+ JVM_RegisterSignal;
+ JVM_ReleaseUTF;
+ JVM_ResolveClass;
+ JVM_ResumeThread;
+ JVM_Send;
+ JVM_SendTo;
+ JVM_SetArrayElement;
+ JVM_SetClassSigners;
+ JVM_SetLength;
+ JVM_SetPrimitiveArrayElement;
+ JVM_SetProtectionDomain;
+ JVM_SetSockOpt;
+ JVM_SetThreadPriority;
+ JVM_Sleep;
+ JVM_Socket;
+ JVM_SocketAvailable;
+ JVM_SocketClose;
+ JVM_SocketShutdown;
+ JVM_StartThread;
+ JVM_StopThread;
+ JVM_SuspendThread;
+ JVM_SupportsCX8;
+ JVM_Sync;
+ JVM_Timeout;
+ JVM_TotalMemory;
+ JVM_TraceInstructions;
+ JVM_TraceMethodCalls;
+ JVM_UnloadLibrary;
+ JVM_Write;
+ JVM_Yield;
+ JVM_handle_bsd_signal;
+
+ # Old reflection routines
+ # These do not need to be present in the product build in JDK 1.4
+ # but their code has not been removed yet because there will not
+ # be a substantial code savings until JVM_InvokeMethod and
+ # JVM_NewInstanceFromConstructor can also be removed; see
+ # reflectionCompat.hpp.
+ JVM_GetClassConstructor;
+ JVM_GetClassConstructors;
+ JVM_GetClassField;
+ JVM_GetClassFields;
+ JVM_GetClassMethod;
+ JVM_GetClassMethods;
+ JVM_GetField;
+ JVM_GetPrimitiveField;
+ JVM_NewInstance;
+ JVM_SetField;
+ JVM_SetPrimitiveField;
+
+ # debug JVM
+ JVM_AccessVMBooleanFlag;
+ JVM_AccessVMIntFlag;
+ JVM_VMBreakPoint;
+
+ # miscellaneous functions
+ jio_fprintf;
+ jio_printf;
+ jio_snprintf;
+ jio_vfprintf;
+ jio_vsnprintf;
+ fork1;
+ numa_warn;
+ numa_error;
+
+ # Needed because there is no JVM interface for this.
+ sysThreadAvailableStackWithSlack;
+
+ # This is for Forte Analyzer profiling support.
+ AsyncGetCallTrace;
+
+ # INSERT VTABLE SYMBOLS HERE
+
+ local:
+ *;
+};
+
diff --git a/make/bsd/makefiles/mapfile-vers-jsig b/make/bsd/makefiles/mapfile-vers-jsig
new file mode 100644
index 000000000..8a675046b
--- /dev/null
+++ b/make/bsd/makefiles/mapfile-vers-jsig
@@ -0,0 +1,40 @@
+#
+
+#
+# Copyright (c) 2005, 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.
+#
+# 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.
+#
+#
+
+# Define library interface.
+
+SUNWprivate_1.1 {
+ global:
+ JVM_begin_signal_setting;
+ JVM_end_signal_setting;
+ JVM_get_libjsig_version;
+ JVM_get_signal_action;
+ sigaction;
+ signal;
+ sigset;
+ local:
+ *;
+};
diff --git a/make/bsd/makefiles/mapfile-vers-product b/make/bsd/makefiles/mapfile-vers-product
new file mode 100644
index 000000000..7a5d7c7df
--- /dev/null
+++ b/make/bsd/makefiles/mapfile-vers-product
@@ -0,0 +1,286 @@
+#
+# @(#)mapfile-vers-product 1.19 08/02/12 10:56:37
+#
+
+#
+# Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+#
+
+# Define public interface.
+
+SUNWprivate_1.1 {
+ global:
+ # JNI
+ JNI_CreateJavaVM;
+ JNI_GetCreatedJavaVMs;
+ JNI_GetDefaultJavaVMInitArgs;
+
+ # JVM
+ JVM_Accept;
+ JVM_ActiveProcessorCount;
+ JVM_AllocateNewArray;
+ JVM_AllocateNewObject;
+ JVM_ArrayCopy;
+ JVM_AssertionStatusDirectives;
+ JVM_Available;
+ JVM_Bind;
+ JVM_ClassDepth;
+ JVM_ClassLoaderDepth;
+ JVM_Clone;
+ JVM_Close;
+ JVM_CX8Field;
+ JVM_CompileClass;
+ JVM_CompileClasses;
+ JVM_CompilerCommand;
+ JVM_Connect;
+ JVM_ConstantPoolGetClassAt;
+ JVM_ConstantPoolGetClassAtIfLoaded;
+ JVM_ConstantPoolGetDoubleAt;
+ JVM_ConstantPoolGetFieldAt;
+ JVM_ConstantPoolGetFieldAtIfLoaded;
+ JVM_ConstantPoolGetFloatAt;
+ JVM_ConstantPoolGetIntAt;
+ JVM_ConstantPoolGetLongAt;
+ JVM_ConstantPoolGetMethodAt;
+ JVM_ConstantPoolGetMethodAtIfLoaded;
+ JVM_ConstantPoolGetMemberRefInfoAt;
+ JVM_ConstantPoolGetSize;
+ JVM_ConstantPoolGetStringAt;
+ JVM_ConstantPoolGetUTF8At;
+ JVM_CountStackFrames;
+ JVM_CurrentClassLoader;
+ JVM_CurrentLoadedClass;
+ JVM_CurrentThread;
+ JVM_CurrentTimeMillis;
+ JVM_DefineClass;
+ JVM_DefineClassWithSource;
+ JVM_DefineClassWithSourceCond;
+ JVM_DesiredAssertionStatus;
+ JVM_DisableCompiler;
+ JVM_DoPrivileged;
+ JVM_DTraceGetVersion;
+ JVM_DTraceActivate;
+ JVM_DTraceIsProbeEnabled;
+ JVM_DTraceIsSupported;
+ JVM_DTraceDispose;
+ JVM_DumpAllStacks;
+ JVM_DumpThreads;
+ JVM_EnableCompiler;
+ JVM_Exit;
+ JVM_FillInStackTrace;
+ JVM_FindClassFromClass;
+ JVM_FindClassFromClassLoader;
+ JVM_FindClassFromBootLoader;
+ JVM_FindLibraryEntry;
+ JVM_FindLoadedClass;
+ JVM_FindPrimitiveClass;
+ JVM_FindSignal;
+ JVM_FreeMemory;
+ JVM_GC;
+ JVM_GetAllThreads;
+ JVM_GetArrayElement;
+ JVM_GetArrayLength;
+ JVM_GetCPClassNameUTF;
+ JVM_GetCPFieldClassNameUTF;
+ JVM_GetCPFieldModifiers;
+ JVM_GetCPFieldNameUTF;
+ JVM_GetCPFieldSignatureUTF;
+ JVM_GetCPMethodClassNameUTF;
+ JVM_GetCPMethodModifiers;
+ JVM_GetCPMethodNameUTF;
+ JVM_GetCPMethodSignatureUTF;
+ JVM_GetCallerClass;
+ JVM_GetClassAccessFlags;
+ JVM_GetClassAnnotations;
+ JVM_GetClassCPEntriesCount;
+ JVM_GetClassCPTypes;
+ JVM_GetClassConstantPool;
+ JVM_GetClassContext;
+ JVM_GetClassDeclaredConstructors;
+ JVM_GetClassDeclaredFields;
+ JVM_GetClassDeclaredMethods;
+ JVM_GetClassFieldsCount;
+ JVM_GetClassInterfaces;
+ JVM_GetClassLoader;
+ JVM_GetClassMethodsCount;
+ JVM_GetClassModifiers;
+ JVM_GetClassName;
+ JVM_GetClassNameUTF;
+ JVM_GetClassSignature;
+ JVM_GetClassSigners;
+ JVM_GetComponentType;
+ JVM_GetDeclaredClasses;
+ JVM_GetDeclaringClass;
+ JVM_GetEnclosingMethodInfo;
+ JVM_GetFieldAnnotations;
+ JVM_GetFieldIxModifiers;
+ JVM_GetHostName;
+ JVM_GetInheritedAccessControlContext;
+ JVM_GetInterfaceVersion;
+ JVM_GetLastErrorString;
+ JVM_GetManagement;
+ JVM_GetMethodAnnotations;
+ JVM_GetMethodDefaultAnnotationValue;
+ JVM_GetMethodIxArgsSize;
+ JVM_GetMethodIxByteCode;
+ JVM_GetMethodIxByteCodeLength;
+ JVM_GetMethodIxExceptionIndexes;
+ JVM_GetMethodIxExceptionTableEntry;
+ JVM_GetMethodIxExceptionTableLength;
+ JVM_GetMethodIxExceptionsCount;
+ JVM_GetMethodIxLocalsCount;
+ JVM_GetMethodIxMaxStack;
+ JVM_GetMethodIxModifiers;
+ JVM_GetMethodIxNameUTF;
+ JVM_GetMethodIxSignatureUTF;
+ JVM_GetMethodParameterAnnotations;
+ JVM_GetPrimitiveArrayElement;
+ JVM_GetProtectionDomain;
+ JVM_GetSockName;
+ JVM_GetSockOpt;
+ JVM_GetStackAccessControlContext;
+ JVM_GetStackTraceDepth;
+ JVM_GetStackTraceElement;
+ JVM_GetSystemPackage;
+ JVM_GetSystemPackages;
+ JVM_GetThreadStateNames;
+ JVM_GetThreadStateValues;
+ JVM_GetVersionInfo;
+ JVM_Halt;
+ JVM_HoldsLock;
+ JVM_IHashCode;
+ JVM_InitAgentProperties;
+ JVM_InitProperties;
+ JVM_InitializeCompiler;
+ JVM_InitializeSocketLibrary;
+ JVM_InternString;
+ JVM_Interrupt;
+ JVM_InvokeMethod;
+ JVM_IsArrayClass;
+ JVM_IsConstructorIx;
+ JVM_IsInterface;
+ JVM_IsInterrupted;
+ JVM_IsNaN;
+ JVM_IsPrimitiveClass;
+ JVM_IsSameClassPackage;
+ JVM_IsSilentCompiler;
+ JVM_IsSupportedJNIVersion;
+ JVM_IsThreadAlive;
+ JVM_LatestUserDefinedLoader;
+ JVM_Listen;
+ JVM_LoadClass0;
+ JVM_LoadLibrary;
+ JVM_Lseek;
+ JVM_MaxObjectInspectionAge;
+ JVM_MaxMemory;
+ JVM_MonitorNotify;
+ JVM_MonitorNotifyAll;
+ JVM_MonitorWait;
+ JVM_NanoTime;
+ JVM_NativePath;
+ JVM_NewArray;
+ JVM_NewInstanceFromConstructor;
+ JVM_NewMultiArray;
+ JVM_OnExit;
+ JVM_Open;
+ JVM_PrintStackTrace;
+ JVM_RaiseSignal;
+ JVM_RawMonitorCreate;
+ JVM_RawMonitorDestroy;
+ JVM_RawMonitorEnter;
+ JVM_RawMonitorExit;
+ JVM_Read;
+ JVM_Recv;
+ JVM_RecvFrom;
+ JVM_RegisterSignal;
+ JVM_ReleaseUTF;
+ JVM_ResolveClass;
+ JVM_ResumeThread;
+ JVM_Send;
+ JVM_SendTo;
+ JVM_SetArrayElement;
+ JVM_SetClassSigners;
+ JVM_SetLength;
+ JVM_SetPrimitiveArrayElement;
+ JVM_SetProtectionDomain;
+ JVM_SetSockOpt;
+ JVM_SetThreadPriority;
+ JVM_Sleep;
+ JVM_Socket;
+ JVM_SocketAvailable;
+ JVM_SocketClose;
+ JVM_SocketShutdown;
+ JVM_StartThread;
+ JVM_StopThread;
+ JVM_SuspendThread;
+ JVM_SupportsCX8;
+ JVM_Sync;
+ JVM_Timeout;
+ JVM_TotalMemory;
+ JVM_TraceInstructions;
+ JVM_TraceMethodCalls;
+ JVM_UnloadLibrary;
+ JVM_Write;
+ JVM_Yield;
+ JVM_handle_bsd_signal;
+
+ # Old reflection routines
+ # These do not need to be present in the product build in JDK 1.4
+ # but their code has not been removed yet because there will not
+ # be a substantial code savings until JVM_InvokeMethod and
+ # JVM_NewInstanceFromConstructor can also be removed; see
+ # reflectionCompat.hpp.
+ JVM_GetClassConstructor;
+ JVM_GetClassConstructors;
+ JVM_GetClassField;
+ JVM_GetClassFields;
+ JVM_GetClassMethod;
+ JVM_GetClassMethods;
+ JVM_GetField;
+ JVM_GetPrimitiveField;
+ JVM_NewInstance;
+ JVM_SetField;
+ JVM_SetPrimitiveField;
+
+ # miscellaneous functions
+ jio_fprintf;
+ jio_printf;
+ jio_snprintf;
+ jio_vfprintf;
+ jio_vsnprintf;
+ fork1;
+ numa_warn;
+ numa_error;
+
+ # Needed because there is no JVM interface for this.
+ sysThreadAvailableStackWithSlack;
+
+ # This is for Forte Analyzer profiling support.
+ AsyncGetCallTrace;
+
+ # INSERT VTABLE SYMBOLS HERE
+
+ local:
+ *;
+};
+
diff --git a/make/bsd/makefiles/optimized.make b/make/bsd/makefiles/optimized.make
new file mode 100644
index 000000000..6090c9784
--- /dev/null
+++ b/make/bsd/makefiles/optimized.make
@@ -0,0 +1,44 @@
+#
+# Copyright (c) 1999, 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.
+#
+# 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.
+#
+#
+
+# Sets make macros for making optimized version of Gamma VM
+# (This is the "product", not the "release" version.)
+
+# Compiler specific OPT_CFLAGS are passed in from gcc.make, sparcWorks.make
+OPT_CFLAGS/DEFAULT= $(OPT_CFLAGS)
+OPT_CFLAGS/BYFILE = $(OPT_CFLAGS/$@)$(OPT_CFLAGS/DEFAULT$(OPT_CFLAGS/$@))
+
+# (OPT_CFLAGS/SLOWER is also available, to alter compilation of buggy files)
+
+# If you set HOTSPARC_GENERIC=yes, you disable all OPT_CFLAGS settings
+CFLAGS$(HOTSPARC_GENERIC) += $(OPT_CFLAGS/BYFILE)
+
+# Set the environment variable HOTSPARC_GENERIC to "true"
+# to inhibit the effect of the previous line on CFLAGS.
+
+# Linker mapfile
+MAPFILE = $(GAMMADIR)/make/bsd/makefiles/mapfile-vers-debug
+
+G_SUFFIX =
+VERSION = optimized
diff --git a/make/bsd/makefiles/ppc.make b/make/bsd/makefiles/ppc.make
new file mode 100644
index 000000000..92957f963
--- /dev/null
+++ b/make/bsd/makefiles/ppc.make
@@ -0,0 +1,30 @@
+#
+# Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+#
+
+# The copied fdlibm routines in sharedRuntimeTrig.o must not be optimized
+OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/NOOPT)
+
+# Must also specify if CPU is big endian
+CFLAGS += -DVM_BIG_ENDIAN
+
diff --git a/make/bsd/makefiles/product.make b/make/bsd/makefiles/product.make
new file mode 100644
index 000000000..1b8acbbca
--- /dev/null
+++ b/make/bsd/makefiles/product.make
@@ -0,0 +1,58 @@
+#
+# 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.
+#
+# 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.
+#
+#
+
+# Sets make macros for making optimized version of Gamma VM
+# (This is the "product", not the "release" version.)
+
+# Compiler specific OPT_CFLAGS are passed in from gcc.make, sparcWorks.make
+OPT_CFLAGS/DEFAULT= $(OPT_CFLAGS)
+OPT_CFLAGS/BYFILE = $(OPT_CFLAGS/$@)$(OPT_CFLAGS/DEFAULT$(OPT_CFLAGS/$@))
+
+# (OPT_CFLAGS/SLOWER is also available, to alter compilation of buggy files)
+
+# If you set HOTSPARC_GENERIC=yes, you disable all OPT_CFLAGS settings
+CFLAGS$(HOTSPARC_GENERIC) += $(OPT_CFLAGS/BYFILE)
+
+# Set the environment variable HOTSPARC_GENERIC to "true"
+# to inhibit the effect of the previous line on CFLAGS.
+
+# Linker mapfile
+MAPFILE = $(GAMMADIR)/make/bsd/makefiles/mapfile-vers-product
+
+G_SUFFIX =
+SYSDEFS += -DPRODUCT
+VERSION = optimized
+
+# use -g to strip library as -x will discard its symbol table; -x is fine for
+# executables.
+ifdef CROSS_COMPILE_ARCH
+ STRIP = $(ALT_COMPILER_PATH)/strip
+else
+ STRIP = strip
+endif
+STRIP_LIBJVM = $(STRIP) -g $@ || exit 1;
+STRIP_AOUT = $(STRIP) -x $@ || exit 1;
+
+# Don't strip in VM build; JDK build will strip libraries later
+# LINK_LIB.CC/POST_HOOK += $(STRIP_$(LINK_INTO))
diff --git a/make/bsd/makefiles/profiled.make b/make/bsd/makefiles/profiled.make
new file mode 100644
index 000000000..fa5c9153b
--- /dev/null
+++ b/make/bsd/makefiles/profiled.make
@@ -0,0 +1,30 @@
+#
+# Copyright (c) 1999, 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.
+#
+# 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.
+#
+#
+
+# Sets make macros for making profiled version of Gamma VM
+# (It is also optimized.)
+
+CFLAGS += -pg
+AOUT_FLAGS += -pg
+LDNOMAP = true
diff --git a/make/bsd/makefiles/rules.make b/make/bsd/makefiles/rules.make
new file mode 100644
index 000000000..12eafe8b3
--- /dev/null
+++ b/make/bsd/makefiles/rules.make
@@ -0,0 +1,216 @@
+#
+# Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+#
+
+# Common rules/macros for the vm, adlc.
+
+# Tell make that .cpp is important
+.SUFFIXES: .cpp $(SUFFIXES)
+
+# For now. Other makefiles use CPP as the c++ compiler, but that should really
+# name the preprocessor.
+ifeq ($(CCC),)
+CCC = $(CPP)
+endif
+
+DEMANGLER = c++filt
+DEMANGLE = $(DEMANGLER) < $@ > .$@ && mv -f .$@ $@
+
+# $(CC) is the c compiler (cc/gcc), $(CCC) is the c++ compiler (CC/g++).
+C_COMPILE = $(CC) $(CPPFLAGS) $(CFLAGS)
+CC_COMPILE = $(CCC) $(CPPFLAGS) $(CFLAGS)
+
+AS.S = $(AS) $(ASFLAGS)
+
+COMPILE.c = $(C_COMPILE) -c
+GENASM.c = $(C_COMPILE) -S
+LINK.c = $(CC) $(LFLAGS) $(AOUT_FLAGS) $(PROF_AOUT_FLAGS)
+LINK_LIB.c = $(CC) $(LFLAGS) $(SHARED_FLAG)
+PREPROCESS.c = $(C_COMPILE) -E
+
+COMPILE.CC = $(CC_COMPILE) -c
+GENASM.CC = $(CC_COMPILE) -S
+LINK.CC = $(CCC) $(LFLAGS) $(AOUT_FLAGS) $(PROF_AOUT_FLAGS)
+LINK_NOPROF.CC = $(CCC) $(LFLAGS) $(AOUT_FLAGS)
+LINK_LIB.CC = $(CCC) $(LFLAGS) $(SHARED_FLAG)
+PREPROCESS.CC = $(CC_COMPILE) -E
+
+# cross compiling the jvm with c2 requires host compilers to build
+# adlc tool
+
+HOST.CC_COMPILE = $(HOSTCPP) $(CPPFLAGS) $(CFLAGS)
+HOST.COMPILE.CC = $(HOST.CC_COMPILE) -c
+HOST.LINK_NOPROF.CC = $(HOSTCPP) $(LFLAGS) $(AOUT_FLAGS)
+
+
+# Effect of REMOVE_TARGET is to delete out-of-date files during "gnumake -k".
+REMOVE_TARGET = rm -f $@
+
+# Synonyms.
+COMPILE.cpp = $(COMPILE.CC)
+GENASM.cpp = $(GENASM.CC)
+LINK.cpp = $(LINK.CC)
+LINK_LIB.cpp = $(LINK_LIB.CC)
+PREPROCESS.cpp = $(PREPROCESS.CC)
+
+# Note use of ALT_BOOTDIR to explicitly specify location of java and
+# javac; this is the same environment variable used in the J2SE build
+# process for overriding the default spec, which is BOOTDIR.
+# Note also that we fall back to using JAVA_HOME if neither of these is
+# specified.
+
+ifdef ALT_BOOTDIR
+
+RUN.JAVA = $(ALT_BOOTDIR)/bin/java
+RUN.JAVAP = $(ALT_BOOTDIR)/bin/javap
+RUN.JAVAH = $(ALT_BOOTDIR)/bin/javah
+RUN.JAR = $(ALT_BOOTDIR)/bin/jar
+COMPILE.JAVAC = $(ALT_BOOTDIR)/bin/javac
+COMPILE.RMIC = $(ALT_BOOTDIR)/bin/rmic
+BOOT_JAVA_HOME = $(ALT_BOOTDIR)
+
+else
+
+ifdef BOOTDIR
+
+RUN.JAVA = $(BOOTDIR)/bin/java
+RUN.JAVAP = $(BOOTDIR)/bin/javap
+RUN.JAVAH = $(BOOTDIR)/bin/javah
+RUN.JAR = $(BOOTDIR)/bin/jar
+COMPILE.JAVAC = $(BOOTDIR)/bin/javac
+COMPILE.RMIC = $(BOOTDIR)/bin/rmic
+BOOT_JAVA_HOME = $(BOOTDIR)
+
+else
+
+ifdef JAVA_HOME
+
+RUN.JAVA = $(JAVA_HOME)/bin/java
+RUN.JAVAP = $(JAVA_HOME)/bin/javap
+RUN.JAVAH = $(JAVA_HOME)/bin/javah
+RUN.JAR = $(JAVA_HOME)/bin/jar
+COMPILE.JAVAC = $(JAVA_HOME)/bin/javac
+COMPILE.RMIC = $(JAVA_HOME)/bin/rmic
+BOOT_JAVA_HOME = $(JAVA_HOME)
+
+else
+
+# take from the PATH, if ALT_BOOTDIR, BOOTDIR and JAVA_HOME are not defined
+# note that this is to support hotspot build without SA. To build
+# SA along with hotspot, you need to define ALT_BOOTDIR, BOOTDIR or JAVA_HOME
+
+RUN.JAVA = java
+RUN.JAVAP = javap
+RUN.JAVAH = javah
+RUN.JAR = jar
+COMPILE.JAVAC = javac
+COMPILE.RMIC = rmic
+
+endif
+endif
+endif
+
+COMPILE.JAVAC += $(BOOTSTRAP_JAVAC_FLAGS)
+
+SUM = /usr/bin/sum
+
+# 'gmake MAKE_VERBOSE=y' gives all the gory details.
+QUIETLY$(MAKE_VERBOSE) = @
+RUN.JAR$(MAKE_VERBOSE) += >/dev/null
+
+# Settings for javac
+BOOT_SOURCE_LANGUAGE_VERSION = 6
+BOOT_TARGET_CLASS_VERSION = 6
+JAVAC_FLAGS = -g -encoding ascii
+BOOTSTRAP_JAVAC_FLAGS = $(JAVAC_FLAGS) -source $(BOOT_SOURCE_LANGUAGE_VERSION) -target $(BOOT_TARGET_CLASS_VERSION)
+
+# With parallel makes, print a message at the end of compilation.
+ifeq ($(findstring j,$(MFLAGS)),j)
+COMPILE_DONE = && { echo Done with $<; }
+endif
+
+# Include $(NONPIC_OBJ_FILES) definition
+ifndef LP64
+include $(GAMMADIR)/make/pic.make
+endif
+
+include $(GAMMADIR)/make/altsrc.make
+
+# The non-PIC object files are only generated for 32 bit platforms.
+ifdef LP64
+%.o: %.cpp
+ @echo Compiling $<
+ $(QUIETLY) $(REMOVE_TARGET)
+ $(QUIETLY) $(COMPILE.CC) $(DEPFLAGS) -o $@ $< $(COMPILE_DONE)
+else
+%.o: %.cpp
+ @echo Compiling $<
+ $(QUIETLY) $(REMOVE_TARGET)
+ $(QUIETLY) $(if $(findstring $@, $(NONPIC_OBJ_FILES)), \
+ $(subst $(VM_PICFLAG), ,$(COMPILE.CC)) $(DEPFLAGS) -o $@ $< $(COMPILE_DONE), \
+ $(COMPILE.CC) $(DEPFLAGS) -o $@ $< $(COMPILE_DONE))
+endif
+
+%.o: %.s
+ @echo Assembling $<
+ $(QUIETLY) $(REMOVE_TARGET)
+ $(QUIETLY) $(AS.S) $(DEPFLAGS) -o $@ $< $(COMPILE_DONE)
+
+%.s: %.cpp
+ @echo Generating assembly for $<
+ $(QUIETLY) $(GENASM.CC) -o $@ $<
+ $(QUIETLY) $(DEMANGLE) $(COMPILE_DONE)
+
+# Intermediate files (for debugging macros)
+%.i: %.cpp
+ @echo Preprocessing $< to $@
+ $(QUIETLY) $(PREPROCESS.CC) $< > $@ $(COMPILE_DONE)
+
+# Override gnumake built-in rules which do sccs get operations badly.
+# (They put the checked out code in the current directory, not in the
+# directory of the original file.) Since this is a symptom of a teamware
+# failure, and since not all problems can be detected by gnumake due
+# to incomplete dependency checking... just complain and stop.
+%:: s.%
+ @echo "========================================================="
+ @echo File $@
+ @echo is out of date with respect to its SCCS file.
+ @echo This file may be from an unresolved Teamware conflict.
+ @echo This is also a symptom of a Teamware bringover/putback failure
+ @echo in which SCCS files are updated but not checked out.
+ @echo Check for other out of date files in your workspace.
+ @echo "========================================================="
+ @exit 666
+
+%:: SCCS/s.%
+ @echo "========================================================="
+ @echo File $@
+ @echo is out of date with respect to its SCCS file.
+ @echo This file may be from an unresolved Teamware conflict.
+ @echo This is also a symptom of a Teamware bringover/putback failure
+ @echo in which SCCS files are updated but not checked out.
+ @echo Check for other out of date files in your workspace.
+ @echo "========================================================="
+ @exit 666
+
+.PHONY: default
diff --git a/make/bsd/makefiles/sa.make b/make/bsd/makefiles/sa.make
new file mode 100644
index 000000000..4e6a00eb4
--- /dev/null
+++ b/make/bsd/makefiles/sa.make
@@ -0,0 +1,121 @@
+#
+# Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+#
+
+# This makefile (sa.make) is included from the sa.make in the
+# build directories.
+
+# This makefile is used to build Serviceability Agent java code
+# and generate JNI header file for native methods.
+
+include $(GAMMADIR)/make/bsd/makefiles/rules.make
+
+AGENT_DIR = $(GAMMADIR)/agent
+
+include $(GAMMADIR)/make/sa.files
+
+TOPDIR = $(shell echo `pwd`)
+GENERATED = $(TOPDIR)/../generated
+
+# tools.jar is needed by the JDI - SA binding
+SA_CLASSPATH = $(BOOT_JAVA_HOME)/lib/tools.jar
+
+# TODO: if it's a modules image, check if SA module is installed.
+MODULELIB_PATH= $(BOOT_JAVA_HOME)/lib/modules
+
+# gnumake 3.78.1 does not accept the *s that
+# are in AGENT_FILES1 and AGENT_FILES2, so use the shell to expand them
+AGENT_FILES1 := $(shell /bin/test -d $(AGENT_DIR) && /bin/ls $(AGENT_FILES1))
+AGENT_FILES2 := $(shell /bin/test -d $(AGENT_DIR) && /bin/ls $(AGENT_FILES2))
+
+AGENT_FILES1_LIST := $(GENERATED)/agent1.classes.list
+AGENT_FILES2_LIST := $(GENERATED)/agent2.classes.list
+
+SA_CLASSDIR = $(GENERATED)/saclasses
+
+SA_BUILD_VERSION_PROP = "sun.jvm.hotspot.runtime.VM.saBuildVersion=$(SA_BUILD_VERSION)"
+
+SA_PROPERTIES = $(SA_CLASSDIR)/sa.properties
+
+# if $(AGENT_DIR) does not exist, we don't build SA
+# also, we don't build SA on Itanium, PowerPC, ARM or zero.
+
+all:
+ if [ -d $(AGENT_DIR) -a "$(SRCARCH)" != "ia64" \
+ -a "$(SRCARCH)" != "arm" \
+ -a "$(SRCARCH)" != "ppc" \
+ -a "$(SRCARCH)" != "zero" ] ; then \
+ $(MAKE) -f sa.make $(GENERATED)/sa-jdi.jar; \
+ fi
+
+$(GENERATED)/sa-jdi.jar: $(AGENT_FILES1) $(AGENT_FILES2)
+ $(QUIETLY) echo "Making $@"
+ $(QUIETLY) if [ "$(BOOT_JAVA_HOME)" = "" ]; then \
+ echo "ALT_BOOTDIR, BOOTDIR or JAVA_HOME needs to be defined to build SA"; \
+ exit 1; \
+ fi
+ $(QUIETLY) if [ ! -f $(SA_CLASSPATH) -a ! -d $(MODULELIB_PATH) ] ; then \
+ echo "Missing $(SA_CLASSPATH) file. Use 1.6.0 or later version of JDK";\
+ echo ""; \
+ exit 1; \
+ fi
+ $(QUIETLY) if [ ! -d $(SA_CLASSDIR) ] ; then \
+ mkdir -p $(SA_CLASSDIR); \
+ fi
+
+# Note: When indented, make tries to execute the '$(shell' comment.
+# In some environments, cmd processors have limited line length.
+# To prevent the javac invocation in the next block from using
+# a very long cmd line, we use javac's @file-list option. We
+# generate the file lists using make's built-in 'foreach' control
+# flow which also avoids cmd processor line length issues. Since
+# the 'foreach' is done as part of make's macro expansion phase,
+# the initialization of the lists is also done in the same phase
+# using '$(shell rm ...' instead of using the more traditional
+# 'rm ...' rule.
+ $(shell rm -rf $(AGENT_FILES1_LIST) $(AGENT_FILES2_LIST))
+ $(foreach file,$(AGENT_FILES1),$(shell echo $(file) >> $(AGENT_FILES1_LIST)))
+ $(foreach file,$(AGENT_FILES2),$(shell echo $(file) >> $(AGENT_FILES2_LIST)))
+
+ $(QUIETLY) $(REMOTE) $(COMPILE.JAVAC) -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) @$(AGENT_FILES1_LIST)
+ $(QUIETLY) $(REMOTE) $(COMPILE.JAVAC) -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) @$(AGENT_FILES2_LIST)
+
+ $(QUIETLY) $(REMOTE) $(COMPILE.RMIC) -classpath $(SA_CLASSDIR) -d $(SA_CLASSDIR) sun.jvm.hotspot.debugger.remote.RemoteDebuggerServer
+ $(QUIETLY) echo "$(SA_BUILD_VERSION_PROP)" > $(SA_PROPERTIES)
+ $(QUIETLY) rm -f $(SA_CLASSDIR)/sun/jvm/hotspot/utilities/soql/sa.js
+ $(QUIETLY) cp $(AGENT_SRC_DIR)/sun/jvm/hotspot/utilities/soql/sa.js $(SA_CLASSDIR)/sun/jvm/hotspot/utilities/soql
+ $(QUIETLY) mkdir -p $(SA_CLASSDIR)/sun/jvm/hotspot/ui/resources
+ $(QUIETLY) rm -f $(SA_CLASSDIR)/sun/jvm/hotspot/ui/resources/*
+ $(QUIETLY) cp $(AGENT_SRC_DIR)/sun/jvm/hotspot/ui/resources/*.png $(SA_CLASSDIR)/sun/jvm/hotspot/ui/resources/
+ $(QUIETLY) cp -r $(AGENT_SRC_DIR)/images/* $(SA_CLASSDIR)/
+ $(QUIETLY) $(REMOTE) $(RUN.JAR) cf $@ -C $(SA_CLASSDIR)/ .
+ $(QUIETLY) $(REMOTE) $(RUN.JAR) uf $@ -C $(AGENT_SRC_DIR) META-INF/services/com.sun.jdi.connect.Connector
+ $(QUIETLY) $(REMOTE) $(RUN.JAVAH) -classpath $(SA_CLASSDIR) -d $(GENERATED) -jni sun.jvm.hotspot.debugger.x86.X86ThreadContext
+ $(QUIETLY) $(REMOTE) $(RUN.JAVAH) -classpath $(SA_CLASSDIR) -d $(GENERATED) -jni sun.jvm.hotspot.debugger.ia64.IA64ThreadContext
+ $(QUIETLY) $(REMOTE) $(RUN.JAVAH) -classpath $(SA_CLASSDIR) -d $(GENERATED) -jni sun.jvm.hotspot.debugger.amd64.AMD64ThreadContext
+ $(QUIETLY) $(REMOTE) $(RUN.JAVAH) -classpath $(SA_CLASSDIR) -d $(GENERATED) -jni sun.jvm.hotspot.debugger.sparc.SPARCThreadContext
+
+clean:
+ rm -rf $(SA_CLASSDIR)
+ rm -rf $(GENERATED)/sa-jdi.jar
+ rm -rf $(AGENT_FILES1_LIST) $(AGENT_FILES2_LIST)
diff --git a/make/bsd/makefiles/saproc.make b/make/bsd/makefiles/saproc.make
new file mode 100644
index 000000000..6303b1be2
--- /dev/null
+++ b/make/bsd/makefiles/saproc.make
@@ -0,0 +1,107 @@
+#
+# Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+#
+
+# Rules to build serviceability agent library, used by vm.make
+
+# libsaproc[_g].so: serviceability agent
+SAPROC = saproc
+SAPROC_G = $(SAPROC)$(G_SUFFIX)
+
+ifeq ($(OS_VENDOR), Darwin)
+ LIBSAPROC = lib$(SAPROC).dylib
+ LIBSAPROC_G = lib$(SAPROC_G).dylib
+else
+ LIBSAPROC = lib$(SAPROC).so
+ LIBSAPROC_G = lib$(SAPROC_G).so
+endif
+
+AGENT_DIR = $(GAMMADIR)/agent
+
+SASRCDIR = $(AGENT_DIR)/src/os/$(Platform_os_family)
+
+# disable building saproc until hsearch_r license issues are resolved
+#ifeq ($(OS_VENDOR), FreeBSD)
+#SASRCFILES = $(SASRCDIR)/salibelf.c \
+# $(SASRCDIR)/symtab.c \
+# $(SASRCDIR)/libproc_impl.c \
+# $(SASRCDIR)/ps_proc.c \
+# $(SASRCDIR)/ps_core.c \
+# $(SASRCDIR)/hsearch_r.c \
+# $(SASRCDIR)/BsdDebuggerLocal.c
+#SALIBS = -lutil -lthread_db
+#else
+SASRCFILES = $(SASRCDIR)/StubDebuggerLocal.c
+SALIBS =
+#endif
+
+SAMAPFILE = $(SASRCDIR)/mapfile
+
+DEST_SAPROC = $(JDK_LIBDIR)/$(LIBSAPROC)
+
+# DEBUG_BINARIES overrides everything, use full -g debug information
+ifeq ($(DEBUG_BINARIES), true)
+ SA_DEBUG_CFLAGS = -g
+endif
+
+# if $(AGENT_DIR) does not exist, we don't build SA
+# also, we don't build SA on Itanium, PPC, ARM or zero.
+
+ifneq ($(wildcard $(AGENT_DIR)),)
+ifneq ($(filter-out ia64 arm ppc zero,$(SRCARCH)),)
+ BUILDLIBSAPROC = $(LIBSAPROC)
+endif
+endif
+
+
+ifneq ($(OS_VENDOR), Darwin)
+SA_LFLAGS = $(MAPFLAG:FILENAME=$(SAMAPFILE))
+endif
+SA_LFLAGS += $(LDFLAGS_HASH_STYLE)
+
+$(LIBSAPROC): $(SASRCFILES) $(SAMAPFILE)
+ $(QUIETLY) if [ "$(BOOT_JAVA_HOME)" = "" ]; then \
+ echo "ALT_BOOTDIR, BOOTDIR or JAVA_HOME needs to be defined to build SA"; \
+ exit 1; \
+ fi
+ @echo Making SA debugger back-end...
+ $(QUIETLY) $(CC) -D$(BUILDARCH) -D_GNU_SOURCE \
+ $(SYMFLAG) $(ARCHFLAG) $(SHARED_FLAG) $(PICFLAG) \
+ -I$(SASRCDIR) \
+ -I$(GENERATED) \
+ -I$(BOOT_JAVA_HOME)/include \
+ -I$(BOOT_JAVA_HOME)/include/$(shell uname -s | tr "[:upper:]" "[:lower:]") \
+ $(SASRCFILES) \
+ $(SA_LFLAGS) \
+ $(SA_DEBUG_CFLAGS) \
+ -o $@ \
+ $(SALIBS)
+ $(QUIETLY) [ -f $(LIBSAPROC_G) ] || { ln -s $@ $(LIBSAPROC_G); }
+
+install_saproc: $(BUILDLIBSAPROC)
+ $(QUIETLY) if [ -e $(LIBSAPROC) ] ; then \
+ echo "Copying $(LIBSAPROC) to $(DEST_SAPROC)"; \
+ cp -f $(LIBSAPROC) $(DEST_SAPROC) && echo "Done"; \
+ fi
+
+.PHONY: install_saproc
diff --git a/make/bsd/makefiles/shark.make b/make/bsd/makefiles/shark.make
new file mode 100644
index 000000000..ca702ee66
--- /dev/null
+++ b/make/bsd/makefiles/shark.make
@@ -0,0 +1,32 @@
+#
+# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright 2008, 2010 Red Hat, Inc.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+#
+
+# Sets make macros for making Shark version of VM
+
+TYPE = SHARK
+
+VM_SUBDIR = server
+
+CFLAGS += -DSHARK
diff --git a/make/bsd/makefiles/sparc.make b/make/bsd/makefiles/sparc.make
new file mode 100644
index 000000000..ddb05132f
--- /dev/null
+++ b/make/bsd/makefiles/sparc.make
@@ -0,0 +1,24 @@
+#
+# Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+#
+
diff --git a/make/bsd/makefiles/sparcWorks.make b/make/bsd/makefiles/sparcWorks.make
new file mode 100644
index 000000000..6e6c8418d
--- /dev/null
+++ b/make/bsd/makefiles/sparcWorks.make
@@ -0,0 +1,104 @@
+#
+# Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+#
+
+#------------------------------------------------------------------------
+# CC, CPP & AS
+
+CPP = CC
+CC = cc
+AS = $(CC) -c
+
+HOSTCPP = $(CPP)
+HOSTCC = $(CC)
+
+ARCHFLAG = $(ARCHFLAG/$(BUILDARCH))
+ARCHFLAG/i486 = -m32
+ARCHFLAG/amd64 = -m64
+
+CFLAGS += $(ARCHFLAG)
+AOUT_FLAGS += $(ARCHFLAG)
+LFLAGS += $(ARCHFLAG)
+ASFLAGS += $(ARCHFLAG)
+
+#------------------------------------------------------------------------
+# Compiler flags
+
+# position-independent code
+PICFLAG = -KPIC
+
+CFLAGS += $(PICFLAG)
+# no more exceptions
+CFLAGS += -features=no%except
+# Reduce code bloat by reverting back to 5.0 behavior for static initializers
+CFLAGS += -features=no%split_init
+# allow zero sized arrays
+CFLAGS += -features=zla
+
+# Use C++ Interpreter
+ifdef CC_INTERP
+ CFLAGS += -DCC_INTERP
+endif
+
+# We don't need libCstd.so and librwtools7.so, only libCrun.so
+CFLAGS += -library=Crun
+LIBS += -lCrun
+
+CFLAGS += -mt
+LFLAGS += -mt
+
+# Compiler warnings are treated as errors
+#WARNINGS_ARE_ERRORS = -errwarn=%all
+CFLAGS_WARN/DEFAULT = $(WARNINGS_ARE_ERRORS)
+# Special cases
+CFLAGS_WARN/BYFILE = $(CFLAGS_WARN/$@)$(CFLAGS_WARN/DEFAULT$(CFLAGS_WARN/$@))
+
+# The flags to use for an Optimized build
+OPT_CFLAGS+=-xO4
+OPT_CFLAGS/NOOPT=-xO0
+
+# Flags for creating the dependency files.
+ifeq ($(shell expr $(COMPILER_REV_NUMERIC) \>= 509), 1)
+DEPFLAGS = -xMMD -xMF $(DEP_DIR)/$(@:%=%.d)
+endif
+
+# -DDONT_USE_PRECOMPILED_HEADER will exclude all includes in precompiled.hpp.
+CFLAGS += -DDONT_USE_PRECOMPILED_HEADER
+
+#------------------------------------------------------------------------
+# Linker flags
+
+# Use $(MAPFLAG:FILENAME=real_file_name) to specify a map file.
+MAPFLAG = -Wl,--version-script=FILENAME
+
+# Use $(SONAMEFLAG:SONAME=soname) to specify the intrinsic name of a shared obj
+SONAMEFLAG = -h SONAME
+
+# Build shared library
+SHARED_FLAG = -G
+
+#------------------------------------------------------------------------
+# Debug flags
+DEBUG_CFLAGS += -g
+FASTDEBUG_CFLAGS = -g0
+
diff --git a/make/bsd/makefiles/sparcv9.make b/make/bsd/makefiles/sparcv9.make
new file mode 100644
index 000000000..b9e4e525d
--- /dev/null
+++ b/make/bsd/makefiles/sparcv9.make
@@ -0,0 +1,27 @@
+#
+# Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+# gcc 4.0 miscompiles this code in -m64
+OPT_CFLAGS/macro.o = -O0
+
+CFLAGS += -D_LP64=1
diff --git a/make/bsd/makefiles/tiered.make b/make/bsd/makefiles/tiered.make
new file mode 100644
index 000000000..da79ade9f
--- /dev/null
+++ b/make/bsd/makefiles/tiered.make
@@ -0,0 +1,31 @@
+#
+# Copyright (c) 2006, 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.
+#
+# 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.
+#
+#
+
+# Sets make macros for making tiered version of VM
+
+TYPE=TIERED
+
+VM_SUBDIR = server
+
+CFLAGS += -DCOMPILER2 -DCOMPILER1
diff --git a/make/bsd/makefiles/top.make b/make/bsd/makefiles/top.make
new file mode 100644
index 000000000..1b674dce9
--- /dev/null
+++ b/make/bsd/makefiles/top.make
@@ -0,0 +1,142 @@
+#
+# Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+#
+
+# top.make is included in the Makefile in the build directories.
+# It DOES NOT include the vm dependency info in order to be faster.
+# Its main job is to implement the incremental form of make lists.
+# It also:
+# -builds and runs adlc via adlc.make
+# -generates JVMTI source and docs via jvmti.make (JSR-163)
+# -generate sa-jdi.jar (JDI binding to core files)
+
+# It assumes the following flags are set:
+# CFLAGS Platform_file, Src_Dirs_I, Src_Dirs_V, SYSDEFS, AOUT, Obj_Files
+
+# -- D. Ungar (5/97) from a file by Bill Bush
+
+# Don't override the built-in $(MAKE).
+# Instead, use "gmake" (or "gnumake") from the command line. --Rose
+#MAKE = gmake
+
+include $(GAMMADIR)/make/altsrc.make
+
+TOPDIR = $(shell echo `pwd`)
+GENERATED = $(TOPDIR)/../generated
+VM = $(GAMMADIR)/src/share/vm
+Plat_File = $(Platform_file)
+CDG = cd $(GENERATED);
+
+ifdef USE_PRECOMPILED_HEADER
+PrecompiledOption = -DUSE_PRECOMPILED_HEADER
+UpdatePCH = $(MAKE) -f vm.make $(PRECOMPILED_HEADER) $(MFLAGS)
+else
+UpdatePCH = \# precompiled header is not used
+PrecompiledOption =
+endif
+
+Cached_plat = $(GENERATED)/platform.current
+
+AD_Dir = $(GENERATED)/adfiles
+ADLC = $(AD_Dir)/adlc
+AD_Spec = $(call altsrc-replace,$(HS_COMMON_SRC)/cpu/$(Platform_arch)/vm/$(Platform_arch_model).ad)
+AD_Src = $(call altsrc-replace,$(HS_COMMON_SRC)/share/vm/adlc)
+AD_Names = ad_$(Platform_arch_model).hpp ad_$(Platform_arch_model).cpp
+AD_Files = $(AD_Names:%=$(AD_Dir)/%)
+
+# AD_Files_If_Required/COMPILER1 = ad_stuff
+AD_Files_If_Required/COMPILER2 = ad_stuff
+AD_Files_If_Required/TIERED = ad_stuff
+AD_Files_If_Required = $(AD_Files_If_Required/$(TYPE))
+
+# Wierd argument adjustment for "gnumake -j..."
+adjust-mflags = $(GENERATED)/adjust-mflags
+MFLAGS-adjusted = -r `$(adjust-mflags) "$(MFLAGS)" "$(HOTSPOT_BUILD_JOBS)"`
+
+
+# default target: update lists, make vm
+# done in stages to force sequential order with parallel make
+#
+
+default: vm_build_preliminaries the_vm
+ @echo All done.
+
+# This is an explicit dependency for the sake of parallel makes.
+vm_build_preliminaries: checks $(Cached_plat) $(AD_Files_If_Required) jvmti_stuff sa_stuff
+ @# We need a null action here, so implicit rules don't get consulted.
+
+$(Cached_plat): $(Plat_File)
+ $(CDG) cp $(Plat_File) $(Cached_plat)
+
+# make AD files as necessary
+ad_stuff: $(Cached_plat) $(adjust-mflags)
+ @$(MAKE) -f adlc.make $(MFLAGS-adjusted)
+
+# generate JVMTI files from the spec
+jvmti_stuff: $(Cached_plat) $(adjust-mflags)
+ @$(MAKE) -f jvmti.make $(MFLAGS-adjusted)
+
+# generate SA jar files and native header
+sa_stuff:
+ @$(MAKE) -f sa.make $(MFLAGS-adjusted)
+
+# and the VM: must use other makefile with dependencies included
+
+# We have to go to great lengths to get control over the -jN argument
+# to the recursive invocation of vm.make. The problem is that gnumake
+# resets -jN to -j1 for recursive runs. (How helpful.)
+# Note that the user must specify the desired parallelism level via a
+# command-line or environment variable name HOTSPOT_BUILD_JOBS.
+$(adjust-mflags): $(GAMMADIR)/make/$(Platform_os_family)/makefiles/adjust-mflags.sh
+ @+rm -f $@ $@+
+ @+cat $< > $@+
+ @+chmod +x $@+
+ @+mv $@+ $@
+
+the_vm: vm_build_preliminaries $(adjust-mflags)
+ @$(UpdatePCH)
+ @$(MAKE) -f vm.make $(MFLAGS-adjusted)
+
+install: the_vm
+ @$(MAKE) -f vm.make install
+
+# next rules support "make foo.[ois]"
+
+%.o %.i %.s:
+ $(UpdatePCH)
+ $(MAKE) -f vm.make $(MFLAGS) $@
+ #$(MAKE) -f vm.make $@
+
+# this should force everything to be rebuilt
+clean:
+ rm -f $(GENERATED)/*.class
+ $(MAKE) -f vm.make $(MFLAGS) clean
+
+# just in case it doesn't, this should do it
+realclean:
+ $(MAKE) -f vm.make $(MFLAGS) clean
+ rm -fr $(GENERATED)
+
+.PHONY: default vm_build_preliminaries
+.PHONY: lists ad_stuff jvmti_stuff sa_stuff the_vm clean realclean
+.PHONY: checks check_os_version install
diff --git a/make/bsd/makefiles/vm.make b/make/bsd/makefiles/vm.make
new file mode 100644
index 000000000..bced09476
--- /dev/null
+++ b/make/bsd/makefiles/vm.make
@@ -0,0 +1,329 @@
+#
+# Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+#
+
+# Rules to build JVM and related libraries, included from vm.make in the build
+# directory.
+
+# Common build rules.
+MAKEFILES_DIR=$(GAMMADIR)/make/$(Platform_os_family)/makefiles
+include $(MAKEFILES_DIR)/rules.make
+include $(GAMMADIR)/make/altsrc.make
+
+default: build
+
+#----------------------------------------------------------------------
+# Defs
+
+GENERATED = ../generated
+DEP_DIR = $(GENERATED)/dependencies
+
+# reads the generated files defining the set of .o's and the .o .h dependencies
+-include $(DEP_DIR)/*.d
+
+# read machine-specific adjustments (%%% should do this via buildtree.make?)
+ifeq ($(ZERO_BUILD), true)
+ include $(MAKEFILES_DIR)/zeroshark.make
+else
+ include $(MAKEFILES_DIR)/$(BUILDARCH).make
+endif
+
+# set VPATH so make knows where to look for source files
+# Src_Dirs_V is everything in src/share/vm/*, plus the right os/*/vm and cpu/*/vm
+# The adfiles directory contains ad_<arch>.[ch]pp.
+# The jvmtifiles directory contains jvmti*.[ch]pp
+Src_Dirs_V += $(GENERATED)/adfiles $(GENERATED)/jvmtifiles
+VPATH += $(Src_Dirs_V:%=%:)
+
+# set INCLUDES for C preprocessor.
+Src_Dirs_I += $(GENERATED)
+# The order is important for the precompiled headers to work.
+INCLUDES += $(PRECOMPILED_HEADER_DIR:%=-I%) $(Src_Dirs_I:%=-I%)
+
+ifeq (${VERSION}, debug)
+ SYMFLAG = -g
+else
+ SYMFLAG =
+endif
+
+# HOTSPOT_RELEASE_VERSION and HOTSPOT_BUILD_VERSION are defined
+# in $(GAMMADIR)/make/defs.make
+ifeq ($(HOTSPOT_BUILD_VERSION),)
+ BUILD_VERSION = -DHOTSPOT_RELEASE_VERSION="\"$(HOTSPOT_RELEASE_VERSION)\""
+else
+ BUILD_VERSION = -DHOTSPOT_RELEASE_VERSION="\"$(HOTSPOT_RELEASE_VERSION)-$(HOTSPOT_BUILD_VERSION)\""
+endif
+
+# The following variables are defined in the generated flags.make file.
+BUILD_VERSION = -DHOTSPOT_RELEASE_VERSION="\"$(HS_BUILD_VER)\""
+JRE_VERSION = -DJRE_RELEASE_VERSION="\"$(JRE_RELEASE_VER)\""
+HS_LIB_ARCH = -DHOTSPOT_LIB_ARCH=\"$(LIBARCH)\"
+BUILD_TARGET = -DHOTSPOT_BUILD_TARGET="\"$(TARGET)\""
+BUILD_USER = -DHOTSPOT_BUILD_USER="\"$(HOTSPOT_BUILD_USER)\""
+VM_DISTRO = -DHOTSPOT_VM_DISTRO="\"$(HOTSPOT_VM_DISTRO)\""
+
+CPPFLAGS = \
+ ${SYSDEFS} \
+ ${INCLUDES} \
+ ${BUILD_VERSION} \
+ ${BUILD_TARGET} \
+ ${BUILD_USER} \
+ ${HS_LIB_ARCH} \
+ ${JRE_VERSION} \
+ ${VM_DISTRO}
+
+ifdef DEFAULT_LIBPATH
+CPPFLAGS += -DDEFAULT_LIBPATH="\"$(DEFAULT_LIBPATH)\""
+endif
+
+# CFLAGS_WARN holds compiler options to suppress/enable warnings.
+CFLAGS += $(CFLAGS_WARN/BYFILE)
+
+# Do not use C++ exception handling
+CFLAGS += $(CFLAGS/NOEX)
+
+# Extra flags from gnumake's invocation or environment
+CFLAGS += $(EXTRA_CFLAGS)
+LFLAGS += $(EXTRA_CFLAGS)
+
+# Don't set excutable bit on stack segment
+# the same could be done by separate execstack command
+ifneq ($(OS_VENDOR), Darwin)
+LFLAGS += -Xlinker -z -Xlinker noexecstack
+endif
+
+LIBS += -lm -pthread
+
+# By default, link the *.o into the library, not the executable.
+LINK_INTO$(LINK_INTO) = LIBJVM
+
+JDK_LIBDIR = $(JAVA_HOME)/jre/lib/$(LIBARCH)
+
+#----------------------------------------------------------------------
+# jvm_db & dtrace
+include $(MAKEFILES_DIR)/dtrace.make
+
+#----------------------------------------------------------------------
+# JVM
+
+JVM = jvm
+ifeq ($(OS_VENDOR), Darwin)
+ LIBJVM = lib$(JVM).dylib
+ LIBJVM_G = lib$(JVM)$(G_SUFFIX).dylib
+ CFLAGS += -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE
+else
+ LIBJVM = lib$(JVM).so
+ LIBJVM_G = lib$(JVM)$(G_SUFFIX).so
+endif
+
+SPECIAL_PATHS:=adlc c1 gc_implementation opto shark libadt
+
+SOURCE_PATHS=\
+ $(shell find $(HS_COMMON_SRC)/share/vm/* -type d \! \
+ \( -name DUMMY $(foreach dir,$(SPECIAL_PATHS),-o -name $(dir)) \))
+SOURCE_PATHS+=$(HS_COMMON_SRC)/os/$(Platform_os_family)/vm
+SOURCE_PATHS+=$(HS_COMMON_SRC)/os/posix/vm
+SOURCE_PATHS+=$(HS_COMMON_SRC)/cpu/$(Platform_arch)/vm
+SOURCE_PATHS+=$(HS_COMMON_SRC)/os_cpu/$(Platform_os_arch)/vm
+
+CORE_PATHS=$(foreach path,$(SOURCE_PATHS),$(call altsrc,$(path)) $(path))
+CORE_PATHS+=$(GENERATED)/jvmtifiles
+
+COMPILER1_PATHS := $(call altsrc,$(HS_COMMON_SRC)/share/vm/c1)
+COMPILER1_PATHS += $(HS_COMMON_SRC)/share/vm/c1
+
+COMPILER2_PATHS := $(call altsrc,$(HS_COMMON_SRC)/share/vm/opto)
+COMPILER2_PATHS += $(call altsrc,$(HS_COMMON_SRC)/share/vm/libadt)
+COMPILER2_PATHS += $(HS_COMMON_SRC)/share/vm/opto
+COMPILER2_PATHS += $(HS_COMMON_SRC)/share/vm/libadt
+COMPILER2_PATHS += $(GENERATED)/adfiles
+
+SHARK_PATHS := $(GAMMADIR)/src/share/vm/shark
+
+# Include dirs per type.
+Src_Dirs/CORE := $(CORE_PATHS)
+Src_Dirs/COMPILER1 := $(CORE_PATHS) $(COMPILER1_PATHS)
+Src_Dirs/COMPILER2 := $(CORE_PATHS) $(COMPILER2_PATHS)
+Src_Dirs/TIERED := $(CORE_PATHS) $(COMPILER1_PATHS) $(COMPILER2_PATHS)
+Src_Dirs/ZERO := $(CORE_PATHS)
+Src_Dirs/SHARK := $(CORE_PATHS) $(SHARK_PATHS)
+Src_Dirs := $(Src_Dirs/$(TYPE))
+
+COMPILER2_SPECIFIC_FILES := opto libadt bcEscapeAnalyzer.cpp chaitin\* c2_\* runtime_\*
+COMPILER1_SPECIFIC_FILES := c1_\*
+SHARK_SPECIFIC_FILES := shark
+ZERO_SPECIFIC_FILES := zero
+
+# Always exclude these.
+Src_Files_EXCLUDE := jsig.c jvmtiEnvRecommended.cpp jvmtiEnvStub.cpp
+
+# Exclude per type.
+Src_Files_EXCLUDE/CORE := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) ciTypeFlow.cpp
+Src_Files_EXCLUDE/COMPILER1 := $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) ciTypeFlow.cpp
+Src_Files_EXCLUDE/COMPILER2 := $(COMPILER1_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES)
+Src_Files_EXCLUDE/TIERED := $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES)
+Src_Files_EXCLUDE/ZERO := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) ciTypeFlow.cpp
+Src_Files_EXCLUDE/SHARK := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES)
+
+Src_Files_EXCLUDE += $(Src_Files_EXCLUDE/$(TYPE))
+
+# Special handling of arch model.
+ifeq ($(Platform_arch_model), x86_32)
+Src_Files_EXCLUDE += \*x86_64\*
+endif
+ifeq ($(Platform_arch_model), x86_64)
+Src_Files_EXCLUDE += \*x86_32\*
+endif
+
+# Locate all source files in the given directory, excluding files in Src_Files_EXCLUDE.
+define findsrc
+ $(notdir $(shell find $(1)/. ! -name . -prune \
+ -a \( -name \*.c -o -name \*.cpp -o -name \*.s \) \
+ -a ! \( -name DUMMY $(addprefix -o -name ,$(Src_Files_EXCLUDE)) \)))
+endef
+
+Src_Files := $(foreach e,$(Src_Dirs),$(call findsrc,$(e)))
+
+Obj_Files = $(sort $(addsuffix .o,$(basename $(Src_Files))))
+
+JVM_OBJ_FILES = $(Obj_Files)
+
+vm_version.o: $(filter-out vm_version.o,$(JVM_OBJ_FILES))
+
+mapfile : $(MAPFILE) vm.def
+ rm -f $@
+ awk '{ if ($$0 ~ "INSERT VTABLE SYMBOLS HERE") \
+ { system ("cat vm.def"); } \
+ else \
+ { print $$0 } \
+ }' > $@ < $(MAPFILE)
+
+mapfile_reorder : mapfile $(REORDERFILE)
+ rm -f $@
+ cat $^ > $@
+
+vm.def: $(Res_Files) $(Obj_Files)
+ sh $(GAMMADIR)/make/bsd/makefiles/build_vm_def.sh *.o > $@
+
+STATIC_CXX = false
+
+ifeq ($(LINK_INTO),AOUT)
+ LIBJVM.o =
+ LIBJVM_MAPFILE =
+ LIBS_VM = $(LIBS)
+else
+ LIBJVM.o = $(JVM_OBJ_FILES)
+ LIBJVM_MAPFILE$(LDNOMAP) = mapfile_reorder
+ LFLAGS_VM$(LDNOMAP) += $(MAPFLAG:FILENAME=$(LIBJVM_MAPFILE))
+ LFLAGS_VM += $(SONAMEFLAG:SONAME=$(LIBJVM))
+
+ ifeq ($(OS_VENDOR), Darwin)
+ LFLAGS_VM += -Xlinker -rpath -Xlinker @loader_path/.
+ LFLAGS_VM += -Xlinker -rpath -Xlinker @loader_path/..
+ LFLAGS_VM += -Xlinker -install_name -Xlinker @rpath/$(@F)
+ endif
+
+ # JVM is statically linked with libgcc[_s] and libstdc++; this is needed to
+ # get around library dependency and compatibility issues. Must use gcc not
+ # g++ to link.
+ ifeq ($(STATIC_CXX), true)
+ LFLAGS_VM += $(STATIC_LIBGCC)
+ LIBS_VM += $(STATIC_STDCXX)
+ LINK_VM = $(LINK_LIB.c)
+ else
+ LINK_VM = $(LINK_LIB.CC)
+ endif
+
+ LIBS_VM += $(LIBS)
+endif
+ifeq ($(ZERO_BUILD), true)
+ LIBS_VM += $(LIBFFI_LIBS)
+endif
+ifeq ($(SHARK_BUILD), true)
+ LFLAGS_VM += $(LLVM_LDFLAGS)
+ LIBS_VM += $(LLVM_LIBS)
+endif
+
+
+# rule for building precompiled header
+$(PRECOMPILED_HEADER):
+ $(QUIETLY) echo Generating precompiled header $@
+ $(QUIETLY) mkdir -p $(PRECOMPILED_HEADER_DIR)
+ $(QUIETLY) $(COMPILE.CC) $(DEPFLAGS) -x c++-header $(PRECOMPILED_HEADER_SRC) -o $@ $(COMPILE_DONE)
+
+# making the library:
+
+ifneq ($(JVM_BASE_ADDR),)
+# By default shared library is linked at base address == 0. Modify the
+# linker script if JVM prefers a different base location. It can also be
+# implemented with 'prelink -r'. But 'prelink' is not (yet) available on
+# our build platform (AS-2.1).
+LD_SCRIPT = libjvm.so.lds
+$(LD_SCRIPT): $(LIBJVM_MAPFILE)
+ $(QUIETLY) { \
+ rm -rf $@; \
+ $(LINK_VM) -Wl,--verbose $(LFLAGS_VM) 2>&1 | \
+ sed -e '/^======/,/^======/!d' \
+ -e '/^======/d' \
+ -e 's/0\( + SIZEOF_HEADERS\)/$(JVM_BASE_ADDR)\1/' \
+ > $@; \
+ }
+LD_SCRIPT_FLAG = -Wl,-T,$(LD_SCRIPT)
+endif
+
+$(LIBJVM): $(LIBJVM.o) $(LIBJVM_MAPFILE) $(LD_SCRIPT)
+ $(QUIETLY) { \
+ echo Linking vm...; \
+ $(LINK_LIB.CC/PRE_HOOK) \
+ $(LINK_VM) $(LD_SCRIPT_FLAG) \
+ $(LFLAGS_VM) -o $@ $(LIBJVM.o) $(LIBS_VM); \
+ $(LINK_LIB.CC/POST_HOOK) \
+ rm -f $@.1; ln -s $@ $@.1; \
+ [ -f $(LIBJVM_G) ] || { ln -s $@ $(LIBJVM_G); ln -s $@.1 $(LIBJVM_G).1; }; \
+ }
+
+DEST_JVM = $(JDK_LIBDIR)/$(VM_SUBDIR)/$(LIBJVM)
+
+install_jvm: $(LIBJVM)
+ @echo "Copying $(LIBJVM) to $(DEST_JVM)"
+ $(QUIETLY) cp -f $(LIBJVM) $(DEST_JVM) && echo "Done"
+
+#----------------------------------------------------------------------
+# Other files
+
+# Gamma launcher
+include $(MAKEFILES_DIR)/launcher.make
+
+# Signal interposition library
+include $(MAKEFILES_DIR)/jsig.make
+
+# Serviceability agent
+include $(MAKEFILES_DIR)/saproc.make
+
+#----------------------------------------------------------------------
+
+build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(LIBJVM_DB) $(BUILDLIBSAPROC)
+
+install: install_jvm install_jsig install_saproc
+
+.PHONY: default build install install_jvm
diff --git a/make/bsd/makefiles/zero.make b/make/bsd/makefiles/zero.make
new file mode 100644
index 000000000..0270711f5
--- /dev/null
+++ b/make/bsd/makefiles/zero.make
@@ -0,0 +1,32 @@
+#
+# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright 2009 Red Hat, Inc.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+#
+
+# Setup for Zero (non-Shark) version of VM
+
+# Select which files to use (in top.make)
+TYPE = ZERO
+
+# Install libjvm.so, etc in in server directory.
+VM_SUBDIR = server
diff --git a/make/bsd/makefiles/zeroshark.make b/make/bsd/makefiles/zeroshark.make
new file mode 100644
index 000000000..12c419819
--- /dev/null
+++ b/make/bsd/makefiles/zeroshark.make
@@ -0,0 +1,62 @@
+#
+# Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+# Copyright 2007, 2008 Red Hat, Inc.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+#
+
+# Setup common to Zero (non-Shark) and Shark versions of VM
+
+# The copied fdlibm routines in sharedRuntimeTrig.o must not be optimized
+OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/NOOPT)
+# The copied fdlibm routines in sharedRuntimeTrans.o must not be optimized
+OPT_CFLAGS/sharedRuntimeTrans.o = $(OPT_CFLAGS/NOOPT)
+
+# Specify that the CPU is little endian, if necessary
+ifeq ($(ZERO_ENDIANNESS), little)
+ CFLAGS += -DVM_LITTLE_ENDIAN
+endif
+
+# Specify that the CPU is 64 bit, if necessary
+ifeq ($(ARCH_DATA_MODEL), 64)
+ CFLAGS += -D_LP64=1
+endif
+
+# Specify the path to the FFI headers
+ifdef ALT_PACKAGE_PATH
+ PACKAGE_PATH = $(ALT_PACKAGE_PATH)
+else
+ ifeq ($(OS_VENDOR),Apple)
+ PACKAGE_PATH = /opt/local
+ else
+ ifeq ($(OS_VENDOR),NetBSD)
+ PACKAGE_PATH = /usr/pkg
+ LIBS += -Wl,-R${PACKAGE_PATH}/lib
+ else
+ PACKAGE_PATH = /usr/local
+ endif
+ endif
+endif
+
+CFLAGS += -I$(PACKAGE_PATH)/include
+LIBS += -L$(PACKAGE_PATH)/lib -lffi
+
+OPT_CFLAGS/compactingPermGenGen.o = -O1
diff --git a/make/bsd/platform_amd64 b/make/bsd/platform_amd64
new file mode 100644
index 000000000..51b2b1cd3
--- /dev/null
+++ b/make/bsd/platform_amd64
@@ -0,0 +1,15 @@
+os_family = bsd
+
+arch = x86
+
+arch_model = x86_64
+
+os_arch = bsd_x86
+
+os_arch_model = bsd_x86_64
+
+lib_arch = amd64
+
+compiler = gcc
+
+sysdefs = -D_ALLBSD_SOURCE -D_GNU_SOURCE -DAMD64
diff --git a/make/bsd/platform_amd64.suncc b/make/bsd/platform_amd64.suncc
new file mode 100644
index 000000000..68e0cc374
--- /dev/null
+++ b/make/bsd/platform_amd64.suncc
@@ -0,0 +1,17 @@
+os_family = bsd
+
+arch = x86
+
+arch_model = x86_64
+
+os_arch = bsd_x86
+
+os_arch_model = bsd_x86_64
+
+lib_arch = amd64
+
+compiler = sparcWorks
+
+gnu_dis_arch = amd64
+
+sysdefs = -D_ALLBSD_SOURCE -DSPARC_WORKS -D_GNU_SOURCE -DAMD64
diff --git a/make/bsd/platform_i486 b/make/bsd/platform_i486
new file mode 100644
index 000000000..2f77e79ff
--- /dev/null
+++ b/make/bsd/platform_i486
@@ -0,0 +1,15 @@
+os_family = bsd
+
+arch = x86
+
+arch_model = x86_32
+
+os_arch = bsd_x86
+
+os_arch_model = bsd_x86_32
+
+lib_arch = i386
+
+compiler = gcc
+
+sysdefs = -D_ALLBSD_SOURCE -D_GNU_SOURCE -DIA32
diff --git a/make/bsd/platform_i486.suncc b/make/bsd/platform_i486.suncc
new file mode 100644
index 000000000..5b203cd5c
--- /dev/null
+++ b/make/bsd/platform_i486.suncc
@@ -0,0 +1,17 @@
+os_family = bsd
+
+arch = x86
+
+arch_model = x86_32
+
+os_arch = bsd_x86
+
+os_arch_model = bsd_x86_32
+
+lib_arch = i386
+
+compiler = sparcWorks
+
+gnu_dis_arch = i386
+
+sysdefs = -D_ALLBSD_SOURCE -DSPARC_WORKS -D_GNU_SOURCE -DIA32
diff --git a/make/bsd/platform_ia64 b/make/bsd/platform_ia64
new file mode 100644
index 000000000..00b9f3380
--- /dev/null
+++ b/make/bsd/platform_ia64
@@ -0,0 +1,15 @@
+os_family = bsd
+
+arch = ia64
+
+os_arch = bsd_ia64
+
+lib_arch = ia64
+
+compiler = gcc
+
+gnu_dis_arch = ia64
+
+sysdefs = -D_ALLBSD_SOURCE -D_GNU_SOURCE -DIA64 -DCC_INTERP
+
+mark_style = alignment
diff --git a/make/bsd/platform_sparc b/make/bsd/platform_sparc
new file mode 100644
index 000000000..04772ad4f
--- /dev/null
+++ b/make/bsd/platform_sparc
@@ -0,0 +1,15 @@
+os_family = bsd
+
+arch = sparc
+
+arch_model = sparc
+
+os_arch = bsd_sparc
+
+os_arch_model = bsd_sparc
+
+lib_arch = sparc
+
+compiler = gcc
+
+sysdefs = -D_ALLBSD_SOURCE -D_GNU_SOURCE -DSPARC
diff --git a/make/bsd/platform_sparcv9 b/make/bsd/platform_sparcv9
new file mode 100644
index 000000000..89e51c5b2
--- /dev/null
+++ b/make/bsd/platform_sparcv9
@@ -0,0 +1,15 @@
+os_family = bsd
+
+arch = sparc
+
+arch_model = sparc
+
+os_arch = bsd_sparc
+
+os_arch_model = bsd_sparc
+
+lib_arch = sparcv9
+
+compiler = gcc
+
+sysdefs = -D_ALLBSD_SOURCE -D_GNU_SOURCE -DSPARC
diff --git a/make/bsd/platform_zero.in b/make/bsd/platform_zero.in
new file mode 100644
index 000000000..f6729c2c0
--- /dev/null
+++ b/make/bsd/platform_zero.in
@@ -0,0 +1,17 @@
+os_family = bsd
+
+arch = zero
+
+arch_model = zero
+
+os_arch = bsd_zero
+
+os_arch_model = bsd_zero
+
+lib_arch = zero
+
+compiler = gcc
+
+gnu_dis_arch = zero
+
+sysdefs = -D_ALLBSD_SOURCE -D_GNU_SOURCE -DCC_INTERP -DZERO -D@ZERO_ARCHDEF@ -DZERO_LIBARCH=\"@ZERO_LIBARCH@\"
diff --git a/make/cscope.make b/make/cscope.make
index 17c3aa374..c38b7a5c7 100644
--- a/make/cscope.make
+++ b/make/cscope.make
@@ -63,7 +63,7 @@ CS_PRUNE_GENERATED = -o -name '${OSNAME}_*_core' -o \
# space-separated list of identifiers to include only those systems.
ifdef CS_OS
CS_PRUNE_OS = $(patsubst %,-o -name '*%*',\
- $(filter-out ${CS_OS},linux macos solaris windows))
+ $(filter-out ${CS_OS},bsd linux macos solaris windows))
endif
# CPU-specific files for all processors are included by default. Set CS_CPU
diff --git a/make/defs.make b/make/defs.make
index fe6c4a27b..44f873d4e 100644
--- a/make/defs.make
+++ b/make/defs.make
@@ -118,13 +118,23 @@ endif
# Windows should have OS predefined
ifeq ($(OS),)
OS := $(shell uname -s)
+ ifneq ($(findstring BSD,$(OS)),)
+ OS=bsd
+ endif
+ ifeq ($(OS), Darwin)
+ OS=bsd
+ endif
HOST := $(shell uname -n)
endif
-# If not SunOS and not Linux, assume Windows
+# If not SunOS, not Linux and not BSD, assume Windows
ifneq ($(OS), Linux)
ifneq ($(OS), SunOS)
- OSNAME=windows
+ ifneq ($(OS), bsd)
+ OSNAME=windows
+ else
+ OSNAME=bsd
+ endif
else
OSNAME=solaris
endif
diff --git a/make/linux/build.sh b/make/linux/build.sh
index f46b8dfcf..79844c51e 100644
--- a/make/linux/build.sh
+++ b/make/linux/build.sh
@@ -1,6 +1,6 @@
#! /bin/sh
#
-# Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -45,6 +45,9 @@ case `uname -m` in
i386|i486|i586|i686)
mach=i386
;;
+ x86_64)
+ mach=amd64
+ ;;
*)
echo "Unsupported machine: " `uname -m`
exit 1
diff --git a/make/linux/makefiles/arm.make b/make/linux/makefiles/arm.make
index e210303dc..6d7079e56 100644
--- a/make/linux/makefiles/arm.make
+++ b/make/linux/makefiles/arm.make
@@ -1,6 +1,25 @@
#
# Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
-# ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
#
Obj_Files += linux_arm.o
diff --git a/make/linux/makefiles/defs.make b/make/linux/makefiles/defs.make
index c3279748c..df5b8e4fa 100644
--- a/make/linux/makefiles/defs.make
+++ b/make/linux/makefiles/defs.make
@@ -177,23 +177,25 @@ endif
JDK_INCLUDE_SUBDIR=linux
+# Library suffix
+LIBRARY_SUFFIX=so
+
# FIXUP: The subdirectory for a debug build is NOT the same on all platforms
VM_DEBUG=jvmg
EXPORT_LIST += $(EXPORT_DOCS_DIR)/platform/jvmti/jvmti.html
# client and server subdirectories have symbolic links to ../libjsig.so
-EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libjsig.so
+EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libjsig.$(LIBRARY_SUFFIX)
ifneq ($(OBJCOPY),)
EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libjsig.debuginfo
endif
-
EXPORT_SERVER_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/server
EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client
ifndef BUILD_CLIENT_ONLY
EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt
-EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.so
+EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.$(LIBRARY_SUFFIX)
ifneq ($(OBJCOPY),)
EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.debuginfo
endif
@@ -202,7 +204,7 @@ endif
ifneq ($(ZERO_BUILD), true)
ifeq ($(ARCH_DATA_MODEL), 32)
EXPORT_LIST += $(EXPORT_CLIENT_DIR)/Xusage.txt
- EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.so
+ EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.$(LIBRARY_SUFFIX)
ifneq ($(OBJCOPY),)
EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.debuginfo
endif
@@ -211,9 +213,9 @@ endif
# Serviceability Binaries
# No SA Support for PPC, IA64, ARM or zero
-ADD_SA_BINARIES/x86 = $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.so \
+ADD_SA_BINARIES/x86 = $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.$(LIBRARY_SUFFIX) \
$(EXPORT_LIB_DIR)/sa-jdi.jar
-ADD_SA_BINARIES/sparc = $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.so \
+ADD_SA_BINARIES/sparc = $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.$(LIBRARY_SUFFIX) \
$(EXPORT_LIB_DIR)/sa-jdi.jar
ifneq ($(OBJCOPY),)
ADD_SA_BINARIES/x86 += $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.debuginfo
diff --git a/make/linux/makefiles/ppc.make b/make/linux/makefiles/ppc.make
index a3a19bc24..92957f963 100644
--- a/make/linux/makefiles/ppc.make
+++ b/make/linux/makefiles/ppc.make
@@ -1,6 +1,25 @@
#
# Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
-# ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
#
# The copied fdlibm routines in sharedRuntimeTrig.o must not be optimized
diff --git a/make/linux/makefiles/sa.make b/make/linux/makefiles/sa.make
index 37a53b8cb..ede57619e 100644
--- a/make/linux/makefiles/sa.make
+++ b/make/linux/makefiles/sa.make
@@ -43,13 +43,7 @@ SA_CLASSPATH = $(BOOT_JAVA_HOME)/lib/tools.jar
# TODO: if it's a modules image, check if SA module is installed.
MODULELIB_PATH= $(BOOT_JAVA_HOME)/lib/modules
-# gnumake 3.78.1 does not accept the *s that
-# are in AGENT_FILES1 and AGENT_FILES2, so use the shell to expand them
-AGENT_FILES1 := $(shell /usr/bin/test -d $(AGENT_DIR) && /bin/ls $(AGENT_FILES1))
-AGENT_FILES2 := $(shell /usr/bin/test -d $(AGENT_DIR) && /bin/ls $(AGENT_FILES2))
-
-AGENT_FILES1_LIST := $(GENERATED)/agent1.classes.list
-AGENT_FILES2_LIST := $(GENERATED)/agent2.classes.list
+AGENT_FILES_LIST := $(GENERATED)/agent.classes.list
SA_CLASSDIR = $(GENERATED)/saclasses
@@ -68,7 +62,7 @@ all:
$(MAKE) -f sa.make $(GENERATED)/sa-jdi.jar; \
fi
-$(GENERATED)/sa-jdi.jar: $(AGENT_FILES1) $(AGENT_FILES2)
+$(GENERATED)/sa-jdi.jar: $(AGENT_FILES)
$(QUIETLY) echo "Making $@"
$(QUIETLY) if [ "$(BOOT_JAVA_HOME)" = "" ]; then \
echo "ALT_BOOTDIR, BOOTDIR or JAVA_HOME needs to be defined to build SA"; \
@@ -82,7 +76,6 @@ $(GENERATED)/sa-jdi.jar: $(AGENT_FILES1) $(AGENT_FILES2)
$(QUIETLY) if [ ! -d $(SA_CLASSDIR) ] ; then \
mkdir -p $(SA_CLASSDIR); \
fi
-
# Note: When indented, make tries to execute the '$(shell' comment.
# In some environments, cmd processors have limited line length.
# To prevent the javac invocation in the next block from using
@@ -93,13 +86,12 @@ $(GENERATED)/sa-jdi.jar: $(AGENT_FILES1) $(AGENT_FILES2)
# the initialization of the lists is also done in the same phase
# using '$(shell rm ...' instead of using the more traditional
# 'rm ...' rule.
- $(shell rm -rf $(AGENT_FILES1_LIST) $(AGENT_FILES2_LIST))
- $(foreach file,$(AGENT_FILES1),$(shell echo $(file) >> $(AGENT_FILES1_LIST)))
- $(foreach file,$(AGENT_FILES2),$(shell echo $(file) >> $(AGENT_FILES2_LIST)))
-
- $(QUIETLY) $(REMOTE) $(COMPILE.JAVAC) -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) @$(AGENT_FILES1_LIST)
- $(QUIETLY) $(REMOTE) $(COMPILE.JAVAC) -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) @$(AGENT_FILES2_LIST)
-
+ $(shell rm -rf $(AGENT_FILES_LIST))
+# gnumake 3.78.1 does not accept the *'s that
+# are in AGENT_FILES, so use the shell to expand them.
+# Be extra carefull to not produce too long command lines in the shell!
+ $(foreach file,$(AGENT_FILES),$(shell ls -1 $(file) >> $(AGENT_FILES_LIST)))
+ $(QUIETLY) $(REMOTE) $(COMPILE.JAVAC) -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) @$(AGENT_FILES_LIST)
$(QUIETLY) $(REMOTE) $(COMPILE.RMIC) -classpath $(SA_CLASSDIR) -d $(SA_CLASSDIR) sun.jvm.hotspot.debugger.remote.RemoteDebuggerServer
$(QUIETLY) echo "$(SA_BUILD_VERSION_PROP)" > $(SA_PROPERTIES)
$(QUIETLY) rm -f $(SA_CLASSDIR)/sun/jvm/hotspot/utilities/soql/sa.js
@@ -118,4 +110,4 @@ $(GENERATED)/sa-jdi.jar: $(AGENT_FILES1) $(AGENT_FILES2)
clean:
rm -rf $(SA_CLASSDIR)
rm -rf $(GENERATED)/sa-jdi.jar
- rm -rf $(AGENT_FILES1_LIST) $(AGENT_FILES2_LIST)
+ rm -rf $(AGENT_FILES_LIST)
diff --git a/make/sa.files b/make/sa.files
index 929843202..4836c966c 100644
--- a/make/sa.files
+++ b/make/sa.files
@@ -36,7 +36,7 @@ AGENT_SRC_DIR = $(AGENT_DIR)/src/share/classes
# Splitted the set of files into two sets because on linux plaform
# listing or compiling all the files results in 'Argument list too long' error.
-AGENT_FILES1 = \
+AGENT_FILES = \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/asm/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/asm/amd64/*.java \
@@ -51,6 +51,9 @@ $(AGENT_SRC_DIR)/sun/jvm/hotspot/code/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/compiler/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/amd64/*.java \
+$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/bsd/*.java \
+$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/bsd/amd64/*.java \
+$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/bsd/x86/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/cdbg/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/cdbg/basic/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/cdbg/basic/x86/*.java \
@@ -88,12 +91,12 @@ $(AGENT_SRC_DIR)/sun/jvm/hotspot/livejvm/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/memory/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/oops/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/opto/*.java \
-$(AGENT_SRC_DIR)/sun/jvm/hotspot/prims/*.java
-
-
-AGENT_FILES2 = \
+$(AGENT_SRC_DIR)/sun/jvm/hotspot/prims/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/amd64/*.java \
+$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/bsd/*.java \
+$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/bsd_amd64/*.java \
+$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/bsd_x86/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/ia64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/linux/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/linux_amd64/*.java \
diff --git a/make/solaris/makefiles/defs.make b/make/solaris/makefiles/defs.make
index 64e96bea8..f4b6ea379 100644
--- a/make/solaris/makefiles/defs.make
+++ b/make/solaris/makefiles/defs.make
@@ -134,13 +134,16 @@ endif
JDK_INCLUDE_SUBDIR=solaris
+# Library suffix
+LIBRARY_SUFFIX=so
+
# FIXUP: The subdirectory for a debug build is NOT the same on all platforms
VM_DEBUG=jvmg
EXPORT_LIST += $(EXPORT_DOCS_DIR)/platform/jvmti/jvmti.html
-# client and server subdirectories have symbolic links to ../libjsig.so
-EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libjsig.so
+# client and server subdirectories have symbolic links to ../libjsig.$(LIBRARY_SUFFIX)
+EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libjsig.$(LIBRARY_SUFFIX)
ifneq ($(OBJCOPY),)
EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libjsig.debuginfo
endif
@@ -150,9 +153,9 @@ EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client
ifneq ($(BUILD_CLIENT_ONLY),true)
EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt
-EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.so
-EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm_db.so
-EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm_dtrace.so
+EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.$(LIBRARY_SUFFIX)
+EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm_db.$(LIBRARY_SUFFIX)
+EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm_dtrace.$(LIBRARY_SUFFIX)
ifneq ($(OBJCOPY),)
EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.debuginfo
EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm_db.debuginfo
@@ -161,21 +164,21 @@ EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm_dtrace.so
endif
ifeq ($(ARCH_DATA_MODEL), 32)
EXPORT_LIST += $(EXPORT_CLIENT_DIR)/Xusage.txt
- EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.so
- EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm_db.so
- EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm_dtrace.so
- EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_db.so
- EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_dtrace.so
+ EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.$(LIBRARY_SUFFIX)
+ EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm_db.$(LIBRARY_SUFFIX)
+ EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm_dtrace.$(LIBRARY_SUFFIX)
+ EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_db.$(LIBRARY_SUFFIX)
+ EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_dtrace.$(LIBRARY_SUFFIX)
ifneq ($(OBJCOPY),)
- EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.debuginfo
- EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm_db.debuginfo
+ EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.debuginfo
+ EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm_db.debuginfo
EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm_dtrace.debuginfo
EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_db.debuginfo
EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_dtrace.debuginfo
endif
ifneq ($(BUILD_CLIENT_ONLY), true)
- EXPORT_LIST += $(EXPORT_SERVER_DIR)/64/libjvm_db.so
- EXPORT_LIST += $(EXPORT_SERVER_DIR)/64/libjvm_dtrace.so
+ EXPORT_LIST += $(EXPORT_SERVER_DIR)/64/libjvm_db.$(LIBRARY_SUFFIX)
+ EXPORT_LIST += $(EXPORT_SERVER_DIR)/64/libjvm_dtrace.$(LIBRARY_SUFFIX)
ifneq ($(OBJCOPY),)
EXPORT_LIST += $(EXPORT_SERVER_DIR)/64/libjvm_db.debuginfo
EXPORT_LIST += $(EXPORT_SERVER_DIR)/64/libjvm_dtrace.debuginfo
@@ -183,7 +186,7 @@ ifeq ($(ARCH_DATA_MODEL), 32)
endif
endif
-EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.so
+EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.$(LIBRARY_SUFFIX)
ifneq ($(OBJCOPY),)
EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.debuginfo
endif
diff --git a/make/solaris/makefiles/sa.make b/make/solaris/makefiles/sa.make
index d51044333..ec27f5613 100644
--- a/make/solaris/makefiles/sa.make
+++ b/make/solaris/makefiles/sa.make
@@ -39,13 +39,7 @@ SA_CLASSPATH = $(BOOT_JAVA_HOME)/lib/tools.jar
# TODO: if it's a modules image, check if SA module is installed.
MODULELIB_PATH= $(BOOT_JAVA_HOME)/lib/modules
-# gnumake 3.78.1 does not accept the *s that
-# are in AGENT_FILES1 and AGENT_FILES2, so use the shell to expand them
-AGENT_FILES1 := $(shell /usr/bin/test -d $(AGENT_DIR) && /bin/ls $(AGENT_FILES1))
-AGENT_FILES2 := $(shell /usr/bin/test -d $(AGENT_DIR) && /bin/ls $(AGENT_FILES2))
-
-AGENT_FILES1_LIST := $(GENERATED)/agent1.classes.list
-AGENT_FILES2_LIST := $(GENERATED)/agent2.classes.list
+AGENT_FILES_LIST := $(GENERATED)/agent.classes.list
SA_CLASSDIR = $(GENERATED)/saclasses
@@ -59,7 +53,7 @@ all:
$(MAKE) -f sa.make $(GENERATED)/sa-jdi.jar; \
fi
-$(GENERATED)/sa-jdi.jar: $(AGENT_FILES1) $(AGENT_FILES2)
+$(GENERATED)/sa-jdi.jar: $(AGENT_FILES)
$(QUIETLY) echo "Making $@";
$(QUIETLY) if [ "$(BOOT_JAVA_HOME)" = "" ]; then \
echo "ALT_BOOTDIR, BOOTDIR or JAVA_HOME needs to be defined to build SA"; \
@@ -73,7 +67,6 @@ $(GENERATED)/sa-jdi.jar: $(AGENT_FILES1) $(AGENT_FILES2)
$(QUIETLY) if [ ! -d $(SA_CLASSDIR) ] ; then \
mkdir -p $(SA_CLASSDIR); \
fi
-
# Note: When indented, make tries to execute the '$(shell' comment.
# In some environments, cmd processors have limited line length.
# To prevent the javac invocation in the next block from using
@@ -84,13 +77,12 @@ $(GENERATED)/sa-jdi.jar: $(AGENT_FILES1) $(AGENT_FILES2)
# the initialization of the lists is also done in the same phase
# using '$(shell rm ...' instead of using the more traditional
# 'rm ...' rule.
- $(shell rm -rf $(AGENT_FILES1_LIST) $(AGENT_FILES2_LIST))
- $(foreach file,$(AGENT_FILES1),$(shell echo $(file) >> $(AGENT_FILES1_LIST)))
- $(foreach file,$(AGENT_FILES2),$(shell echo $(file) >> $(AGENT_FILES2_LIST)))
-
- $(QUIETLY) $(COMPILE.JAVAC) -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) @$(AGENT_FILES1_LIST)
- $(QUIETLY) $(COMPILE.JAVAC) -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) @$(AGENT_FILES2_LIST)
-
+ $(shell rm -rf $(AGENT_FILES_LIST))
+# gnumake 3.78.1 does not accept the *'s that
+# are in AGENT_FILES, so use the shell to expand them.
+# Be extra carefull to not produce too long command lines in the shell!
+ $(foreach file,$(AGENT_FILES),$(shell ls -1 $(file) >> $(AGENT_FILES_LIST)))
+ $(QUIETLY) $(COMPILE.JAVAC) -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) @$(AGENT_FILES_LIST)
$(QUIETLY) $(COMPILE.RMIC) -classpath $(SA_CLASSDIR) -d $(SA_CLASSDIR) sun.jvm.hotspot.debugger.remote.RemoteDebuggerServer
$(QUIETLY) echo "$(SA_BUILD_VERSION_PROP)" > $(SA_PROPERTIES)
$(QUIETLY) rm -f $(SA_CLASSDIR)/sun/jvm/hotspot/utilities/soql/sa.js
@@ -106,4 +98,4 @@ $(GENERATED)/sa-jdi.jar: $(AGENT_FILES1) $(AGENT_FILES2)
clean:
rm -rf $(SA_CLASSDIR)
rm -rf $(GENERATED)/sa-jdi.jar
- rm -rf $(AGENT_FILES1_LIST) $(AGENT_FILES2_LIST)
+ rm -rf $(AGENT_FILES_LIST)
diff --git a/make/windows/makefiles/defs.make b/make/windows/makefiles/defs.make
index b4b345449..c1be7d2c8 100644
--- a/make/windows/makefiles/defs.make
+++ b/make/windows/makefiles/defs.make
@@ -109,6 +109,9 @@ endif
JDK_INCLUDE_SUBDIR=win32
+# Library suffix
+LIBRARY_SUFFIX=dll
+
# HOTSPOT_RELEASE_VERSION and HOTSPOT_BUILD_VERSION are defined
# and added to MAKE_ARGS list in $(GAMMADIR)/make/defs.make.
@@ -175,24 +178,24 @@ EXPORT_CLIENT_DIR = $(EXPORT_JRE_BIN_DIR)/client
EXPORT_KERNEL_DIR = $(EXPORT_JRE_BIN_DIR)/kernel
EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt
-EXPORT_LIST += $(EXPORT_SERVER_DIR)/jvm.dll
+EXPORT_LIST += $(EXPORT_SERVER_DIR)/jvm.$(LIBRARY_SUFFIX)
EXPORT_LIST += $(EXPORT_SERVER_DIR)/jvm.pdb
EXPORT_LIST += $(EXPORT_SERVER_DIR)/jvm.map
EXPORT_LIST += $(EXPORT_LIB_DIR)/jvm.lib
ifeq ($(ARCH_DATA_MODEL), 32)
EXPORT_LIST += $(EXPORT_CLIENT_DIR)/Xusage.txt
- EXPORT_LIST += $(EXPORT_CLIENT_DIR)/jvm.dll
+ EXPORT_LIST += $(EXPORT_CLIENT_DIR)/jvm.$(LIBRARY_SUFFIX)
EXPORT_LIST += $(EXPORT_CLIENT_DIR)/jvm.pdb
EXPORT_LIST += $(EXPORT_CLIENT_DIR)/jvm.map
# kernel vm
EXPORT_LIST += $(EXPORT_KERNEL_DIR)/Xusage.txt
- EXPORT_LIST += $(EXPORT_KERNEL_DIR)/jvm.dll
+ EXPORT_LIST += $(EXPORT_KERNEL_DIR)/jvm.$(LIBRARY_SUFFIX)
EXPORT_LIST += $(EXPORT_KERNEL_DIR)/jvm.pdb
EXPORT_LIST += $(EXPORT_KERNEL_DIR)/jvm.map
endif
ifeq ($(BUILD_WIN_SA), 1)
- EXPORT_LIST += $(EXPORT_JRE_BIN_DIR)/sawindbg.dll
+ EXPORT_LIST += $(EXPORT_JRE_BIN_DIR)/sawindbg.$(LIBRARY_SUFFIX)
EXPORT_LIST += $(EXPORT_JRE_BIN_DIR)/sawindbg.pdb
EXPORT_LIST += $(EXPORT_JRE_BIN_DIR)/sawindbg.map
EXPORT_LIST += $(EXPORT_LIB_DIR)/sa-jdi.jar
diff --git a/make/windows/makefiles/sa.make b/make/windows/makefiles/sa.make
index 00d2e9eea..ac59711aa 100644
--- a/make/windows/makefiles/sa.make
+++ b/make/windows/makefiles/sa.make
@@ -52,12 +52,11 @@ default:: $(GENERATED)\sa-jdi.jar
# Remove the space between $(SA_BUILD_VERSION_PROP) and > below as it adds a white space
# at the end of SA version string and causes a version mismatch with the target VM version.
-$(GENERATED)\sa-jdi.jar: $(AGENT_FILES1:/=\) $(AGENT_FILES2:/=\)
+$(GENERATED)\sa-jdi.jar: $(AGENT_FILES:/=\)
@if not exist $(SA_CLASSDIR) mkdir $(SA_CLASSDIR)
@echo ...Building sa-jdi.jar
@echo ...$(COMPILE_JAVAC) -classpath $(SA_CLASSPATH) -d $(SA_CLASSDIR) ....
- @$(COMPILE_JAVAC) -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) $(AGENT_FILES1:/=\)
- @$(COMPILE_JAVAC) -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) $(AGENT_FILES2:/=\)
+ @$(COMPILE_JAVAC) -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) $(AGENT_FILES:/=\)
$(COMPILE_RMIC) -classpath $(SA_CLASSDIR) -d $(SA_CLASSDIR) sun.jvm.hotspot.debugger.remote.RemoteDebuggerServer
$(QUIETLY) echo $(SA_BUILD_VERSION_PROP)> $(SA_PROPERTIES)
$(QUIETLY) rm -f $(SA_CLASSDIR)/sun/jvm/hotspot/utilities/soql/sa.js
diff --git a/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp b/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp
index 7b60789d2..abf3ab9d5 100644
--- a/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp
+++ b/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp
@@ -328,7 +328,8 @@ void LIRGenerator::do_StoreIndexed(StoreIndexed* x) {
bool use_length = x->length() != NULL;
bool obj_store = x->elt_type() == T_ARRAY || x->elt_type() == T_OBJECT;
bool needs_store_check = obj_store && (x->value()->as_Constant() == NULL ||
- !get_jobject_constant(x->value())->is_null_object());
+ !get_jobject_constant(x->value())->is_null_object() ||
+ x->should_profile());
LIRItem array(x->array(), this);
LIRItem index(x->index(), this);
@@ -382,7 +383,7 @@ void LIRGenerator::do_StoreIndexed(StoreIndexed* x) {
LIR_Opr tmp3 = FrameMap::G5_opr;
CodeEmitInfo* store_check_info = new CodeEmitInfo(range_check_info);
- __ store_check(value.result(), array.result(), tmp1, tmp2, tmp3, store_check_info);
+ __ store_check(value.result(), array.result(), tmp1, tmp2, tmp3, store_check_info, x->profiled_method(), x->profiled_bci());
}
if (obj_store) {
diff --git a/src/cpu/sparc/vm/stubGenerator_sparc.cpp b/src/cpu/sparc/vm/stubGenerator_sparc.cpp
index cf403040d..9415c7b6c 100644
--- a/src/cpu/sparc/vm/stubGenerator_sparc.cpp
+++ b/src/cpu/sparc/vm/stubGenerator_sparc.cpp
@@ -2359,10 +2359,10 @@ class StubGenerator: public StubCodeGenerator {
for (int off = 0; off < 64; off += 16) {
if (use_prefetch && (off & 31) == 0) {
if (ArraycopySrcPrefetchDistance > 0) {
- __ prefetch(from, ArraycopySrcPrefetchDistance, Assembler::severalReads);
+ __ prefetch(from, ArraycopySrcPrefetchDistance+off, Assembler::severalReads);
}
if (ArraycopyDstPrefetchDistance > 0) {
- __ prefetch(to, ArraycopyDstPrefetchDistance, Assembler::severalWritesAndPossiblyReads);
+ __ prefetch(to, ArraycopyDstPrefetchDistance+off, Assembler::severalWritesAndPossiblyReads);
}
}
__ ldx(from, off+0, O4);
diff --git a/src/cpu/x86/vm/bytes_x86.hpp b/src/cpu/x86/vm/bytes_x86.hpp
index ac096dc37..9f939a389 100644
--- a/src/cpu/x86/vm/bytes_x86.hpp
+++ b/src/cpu/x86/vm/bytes_x86.hpp
@@ -81,6 +81,9 @@ class Bytes: AllStatic {
#ifdef TARGET_OS_ARCH_windows_x86
# include "bytes_windows_x86.inline.hpp"
#endif
+#ifdef TARGET_OS_ARCH_bsd_x86
+# include "bytes_bsd_x86.inline.hpp"
+#endif
#endif // CPU_X86_VM_BYTES_X86_HPP
diff --git a/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp b/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp
index 407f0fc58..dbdd7087f 100644
--- a/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp
+++ b/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp
@@ -427,8 +427,8 @@ int LIR_Assembler::emit_unwind_handler() {
// Fetch the exception from TLS and clear out exception related thread state
__ get_thread(rsi);
__ movptr(rax, Address(rsi, JavaThread::exception_oop_offset()));
- __ movptr(Address(rsi, JavaThread::exception_oop_offset()), (int32_t)NULL_WORD);
- __ movptr(Address(rsi, JavaThread::exception_pc_offset()), (int32_t)NULL_WORD);
+ __ movptr(Address(rsi, JavaThread::exception_oop_offset()), (intptr_t)NULL_WORD);
+ __ movptr(Address(rsi, JavaThread::exception_pc_offset()), (intptr_t)NULL_WORD);
__ bind(_unwind_handler_entry);
__ verify_not_null_oop(rax);
diff --git a/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp b/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp
index c71590a26..1ff91cafb 100644
--- a/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp
+++ b/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp
@@ -267,7 +267,8 @@ void LIRGenerator::do_StoreIndexed(StoreIndexed* x) {
bool use_length = x->length() != NULL;
bool obj_store = x->elt_type() == T_ARRAY || x->elt_type() == T_OBJECT;
bool needs_store_check = obj_store && (x->value()->as_Constant() == NULL ||
- !get_jobject_constant(x->value())->is_null_object());
+ !get_jobject_constant(x->value())->is_null_object() ||
+ x->should_profile());
LIRItem array(x->array(), this);
LIRItem index(x->index(), this);
@@ -321,7 +322,7 @@ void LIRGenerator::do_StoreIndexed(StoreIndexed* x) {
LIR_Opr tmp3 = new_register(objectType);
CodeEmitInfo* store_check_info = new CodeEmitInfo(range_check_info);
- __ store_check(value.result(), array.result(), tmp1, tmp2, tmp3, store_check_info);
+ __ store_check(value.result(), array.result(), tmp1, tmp2, tmp3, store_check_info, x->profiled_method(), x->profiled_bci());
}
if (obj_store) {
diff --git a/src/cpu/x86/vm/copy_x86.hpp b/src/cpu/x86/vm/copy_x86.hpp
index dbadb0e9f..d5c6d5efa 100644
--- a/src/cpu/x86/vm/copy_x86.hpp
+++ b/src/cpu/x86/vm/copy_x86.hpp
@@ -37,6 +37,9 @@
#ifdef TARGET_OS_ARCH_windows_x86
# include "copy_windows_x86.inline.hpp"
#endif
+#ifdef TARGET_OS_ARCH_bsd_x86
+# include "copy_bsd_x86.inline.hpp"
+#endif
static void pd_fill_to_words(HeapWord* tohw, size_t count, juint value) {
diff --git a/src/cpu/x86/vm/globals_x86.hpp b/src/cpu/x86/vm/globals_x86.hpp
index 8b79f8ee9..d40f5592d 100644
--- a/src/cpu/x86/vm/globals_x86.hpp
+++ b/src/cpu/x86/vm/globals_x86.hpp
@@ -70,7 +70,11 @@ define_pd_global(intx, PreInflateSpin, 10);
define_pd_global(bool, RewriteBytecodes, true);
define_pd_global(bool, RewriteFrequentPairs, true);
+#ifdef _ALLBSD_SOURCE
+define_pd_global(bool, UseMembar, true);
+#else
define_pd_global(bool, UseMembar, false);
+#endif
// GC Ergo Flags
define_pd_global(intx, CMSYoungGenPerWorker, 64*M); // default max size of CMS young gen, per GC worker thread
diff --git a/src/cpu/x86/vm/interp_masm_x86_32.cpp b/src/cpu/x86/vm/interp_masm_x86_32.cpp
index 96514700e..f06d54e2c 100644
--- a/src/cpu/x86/vm/interp_masm_x86_32.cpp
+++ b/src/cpu/x86/vm/interp_masm_x86_32.cpp
@@ -45,6 +45,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
// Implementation of InterpreterMacroAssembler
@@ -1158,7 +1161,7 @@ void InterpreterMacroAssembler::record_klass_in_profile_helper(
int recvr_offset = in_bytes(VirtualCallData::receiver_offset(start_row));
set_mdp_data_at(mdp, recvr_offset, receiver);
int count_offset = in_bytes(VirtualCallData::receiver_count_offset(start_row));
- movptr(reg2, (int32_t)DataLayout::counter_increment);
+ movptr(reg2, (intptr_t)DataLayout::counter_increment);
set_mdp_data_at(mdp, count_offset, reg2);
if (start_row > 0) {
jmp(done);
@@ -1301,7 +1304,7 @@ void InterpreterMacroAssembler::profile_switch_case(Register index, Register mdp
test_method_data_pointer(mdp, profile_continue);
// Build the base (index * per_case_size_in_bytes()) + case_array_offset_in_bytes()
- movptr(reg2, (int32_t)in_bytes(MultiBranchData::per_case_size()));
+ movptr(reg2, (intptr_t)in_bytes(MultiBranchData::per_case_size()));
// index is positive and so should have correct value if this code were
// used on 64bits
imulptr(index, reg2);
diff --git a/src/cpu/x86/vm/interp_masm_x86_64.cpp b/src/cpu/x86/vm/interp_masm_x86_64.cpp
index 3cd4355e6..e41843683 100644
--- a/src/cpu/x86/vm/interp_masm_x86_64.cpp
+++ b/src/cpu/x86/vm/interp_masm_x86_64.cpp
@@ -45,6 +45,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
// Implementation of InterpreterMacroAssembler
diff --git a/src/cpu/x86/vm/jni_x86.h b/src/cpu/x86/vm/jni_x86.h
index d06bb5ca2..d1b37b992 100644
--- a/src/cpu/x86/vm/jni_x86.h
+++ b/src/cpu/x86/vm/jni_x86.h
@@ -26,7 +26,7 @@
#ifndef _JAVASOFT_JNI_MD_H_
#define _JAVASOFT_JNI_MD_H_
-#if defined(SOLARIS) || defined(LINUX)
+#if defined(SOLARIS) || defined(LINUX) || defined(_ALLBSD_SOURCE)
#if defined(__GNUC__) && (__GNUC__ > 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ > 2)
#define JNIEXPORT __attribute__((visibility("default")))
diff --git a/src/cpu/x86/vm/stubGenerator_x86_32.cpp b/src/cpu/x86/vm/stubGenerator_x86_32.cpp
index e8a853361..fb85fffd7 100644
--- a/src/cpu/x86/vm/stubGenerator_x86_32.cpp
+++ b/src/cpu/x86/vm/stubGenerator_x86_32.cpp
@@ -47,6 +47,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
#ifdef COMPILER2
#include "opto/runtime.hpp"
#endif
diff --git a/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/src/cpu/x86/vm/stubGenerator_x86_64.cpp
index a58b8d9eb..53d9431db 100644
--- a/src/cpu/x86/vm/stubGenerator_x86_64.cpp
+++ b/src/cpu/x86/vm/stubGenerator_x86_64.cpp
@@ -47,6 +47,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
#ifdef COMPILER2
#include "opto/runtime.hpp"
#endif
diff --git a/src/cpu/x86/vm/stubRoutines_x86_32.cpp b/src/cpu/x86/vm/stubRoutines_x86_32.cpp
index dfdab6f00..6ec4121b9 100644
--- a/src/cpu/x86/vm/stubRoutines_x86_32.cpp
+++ b/src/cpu/x86/vm/stubRoutines_x86_32.cpp
@@ -35,6 +35,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
// Implementation of the platform-specific part of StubRoutines - for
// a description of how to extend it, see the stubRoutines.hpp file.
diff --git a/src/cpu/x86/vm/stubRoutines_x86_64.cpp b/src/cpu/x86/vm/stubRoutines_x86_64.cpp
index caab63bfc..182872b88 100644
--- a/src/cpu/x86/vm/stubRoutines_x86_64.cpp
+++ b/src/cpu/x86/vm/stubRoutines_x86_64.cpp
@@ -35,6 +35,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
// Implementation of the platform-specific part of StubRoutines - for
// a description of how to extend it, see the stubRoutines.hpp file.
diff --git a/src/cpu/x86/vm/vm_version_x86.cpp b/src/cpu/x86/vm/vm_version_x86.cpp
index 42a4c3c8d..7a8ee727b 100644
--- a/src/cpu/x86/vm/vm_version_x86.cpp
+++ b/src/cpu/x86/vm/vm_version_x86.cpp
@@ -37,6 +37,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "os_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "os_bsd.inline.hpp"
+#endif
int VM_Version::_cpu;
diff --git a/src/cpu/zero/vm/bytes_zero.hpp b/src/cpu/zero/vm/bytes_zero.hpp
index 39caaeabc..be2e09adf 100644
--- a/src/cpu/zero/vm/bytes_zero.hpp
+++ b/src/cpu/zero/vm/bytes_zero.hpp
@@ -168,6 +168,9 @@ class Bytes: AllStatic {
#ifdef TARGET_OS_ARCH_linux_zero
# include "bytes_linux_zero.inline.hpp"
#endif
+#ifdef TARGET_OS_ARCH_bsd_zero
+# include "bytes_bsd_zero.inline.hpp"
+#endif
#endif // VM_LITTLE_ENDIAN
diff --git a/src/cpu/zero/vm/globals_zero.hpp b/src/cpu/zero/vm/globals_zero.hpp
index c45f1f576..6754e6907 100644
--- a/src/cpu/zero/vm/globals_zero.hpp
+++ b/src/cpu/zero/vm/globals_zero.hpp
@@ -52,7 +52,11 @@ define_pd_global(intx, StackShadowPages, 5 LP64_ONLY(+1) DEBUG_ONLY(+3));
define_pd_global(bool, RewriteBytecodes, true);
define_pd_global(bool, RewriteFrequentPairs, true);
+#ifdef _ALLBSD_SOURCE
+define_pd_global(bool, UseMembar, true);
+#else
define_pd_global(bool, UseMembar, false);
+#endif
// GC Ergo Flags
define_pd_global(intx, CMSYoungGenPerWorker, 16*M); // default max size of CMS young gen, per GC worker thread
diff --git a/src/cpu/zero/vm/interp_masm_zero.cpp b/src/cpu/zero/vm/interp_masm_zero.cpp
index 8b470ebce..a85431bbe 100644
--- a/src/cpu/zero/vm/interp_masm_zero.cpp
+++ b/src/cpu/zero/vm/interp_masm_zero.cpp
@@ -40,5 +40,8 @@
#ifdef TARGET_OS_FAMILY_linux
# include "thread_linux.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
// This file is intentionally empty
diff --git a/src/cpu/zero/vm/stubGenerator_zero.cpp b/src/cpu/zero/vm/stubGenerator_zero.cpp
index b13c0f3ef..4142e0250 100644
--- a/src/cpu/zero/vm/stubGenerator_zero.cpp
+++ b/src/cpu/zero/vm/stubGenerator_zero.cpp
@@ -43,6 +43,9 @@
#ifdef TARGET_OS_FAMILY_linux
# include "thread_linux.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
#ifdef COMPILER2
#include "opto/runtime.hpp"
#endif
diff --git a/src/cpu/zero/vm/stubRoutines_zero.cpp b/src/cpu/zero/vm/stubRoutines_zero.cpp
index 96df53e0f..8b21dde68 100644
--- a/src/cpu/zero/vm/stubRoutines_zero.cpp
+++ b/src/cpu/zero/vm/stubRoutines_zero.cpp
@@ -30,3 +30,6 @@
#ifdef TARGET_OS_FAMILY_linux
# include "thread_linux.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
diff --git a/src/cpu/zero/vm/vm_version_zero.cpp b/src/cpu/zero/vm/vm_version_zero.cpp
index 87ff88be5..391e29de9 100644
--- a/src/cpu/zero/vm/vm_version_zero.cpp
+++ b/src/cpu/zero/vm/vm_version_zero.cpp
@@ -32,5 +32,8 @@
#ifdef TARGET_OS_FAMILY_linux
# include "os_linux.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "os_bsd.inline.hpp"
+#endif
// This file is intentionally empty
diff --git a/src/os/bsd/vm/attachListener_bsd.cpp b/src/os/bsd/vm/attachListener_bsd.cpp
new file mode 100644
index 000000000..f74247063
--- /dev/null
+++ b/src/os/bsd/vm/attachListener_bsd.cpp
@@ -0,0 +1,520 @@
+/*
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "runtime/interfaceSupport.hpp"
+#include "runtime/os.hpp"
+#include "services/attachListener.hpp"
+#include "services/dtraceAttacher.hpp"
+
+#include <unistd.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+
+#ifndef UNIX_PATH_MAX
+#define UNIX_PATH_MAX sizeof(((struct sockaddr_un *)0)->sun_path)
+#endif
+
+// The attach mechanism on Bsd uses a UNIX domain socket. An attach listener
+// thread is created at startup or is created on-demand via a signal from
+// the client tool. The attach listener creates a socket and binds it to a file
+// in the filesystem. The attach listener then acts as a simple (single-
+// threaded) server - it waits for a client to connect, reads the request,
+// executes it, and returns the response to the client via the socket
+// connection.
+//
+// As the socket is a UNIX domain socket it means that only clients on the
+// local machine can connect. In addition there are two other aspects to
+// the security:
+// 1. The well known file that the socket is bound to has permission 400
+// 2. When a client connect, the SO_PEERCRED socket option is used to
+// obtain the credentials of client. We check that the effective uid
+// of the client matches this process.
+
+// forward reference
+class BsdAttachOperation;
+
+class BsdAttachListener: AllStatic {
+ private:
+ // the path to which we bind the UNIX domain socket
+ static char _path[UNIX_PATH_MAX];
+ static bool _has_path;
+
+ // the file descriptor for the listening socket
+ static int _listener;
+
+ static void set_path(char* path) {
+ if (path == NULL) {
+ _has_path = false;
+ } else {
+ strncpy(_path, path, UNIX_PATH_MAX);
+ _path[UNIX_PATH_MAX-1] = '\0';
+ _has_path = true;
+ }
+ }
+
+ static void set_listener(int s) { _listener = s; }
+
+ // reads a request from the given connected socket
+ static BsdAttachOperation* read_request(int s);
+
+ public:
+ enum {
+ ATTACH_PROTOCOL_VER = 1 // protocol version
+ };
+ enum {
+ ATTACH_ERROR_BADVERSION = 101 // error codes
+ };
+
+ // initialize the listener, returns 0 if okay
+ static int init();
+
+ static char* path() { return _path; }
+ static bool has_path() { return _has_path; }
+ static int listener() { return _listener; }
+
+ // write the given buffer to a socket
+ static int write_fully(int s, char* buf, int len);
+
+ static BsdAttachOperation* dequeue();
+};
+
+class BsdAttachOperation: public AttachOperation {
+ private:
+ // the connection to the client
+ int _socket;
+
+ public:
+ void complete(jint res, bufferedStream* st);
+
+ void set_socket(int s) { _socket = s; }
+ int socket() const { return _socket; }
+
+ BsdAttachOperation(char* name) : AttachOperation(name) {
+ set_socket(-1);
+ }
+};
+
+// statics
+char BsdAttachListener::_path[UNIX_PATH_MAX];
+bool BsdAttachListener::_has_path;
+int BsdAttachListener::_listener = -1;
+
+// Supporting class to help split a buffer into individual components
+class ArgumentIterator : public StackObj {
+ private:
+ char* _pos;
+ char* _end;
+ public:
+ ArgumentIterator(char* arg_buffer, size_t arg_size) {
+ _pos = arg_buffer;
+ _end = _pos + arg_size - 1;
+ }
+ char* next() {
+ if (*_pos == '\0') {
+ return NULL;
+ }
+ char* res = _pos;
+ char* next_pos = strchr(_pos, '\0');
+ if (next_pos < _end) {
+ next_pos++;
+ }
+ _pos = next_pos;
+ return res;
+ }
+};
+
+
+// atexit hook to stop listener and unlink the file that it is
+// bound too.
+extern "C" {
+ static void listener_cleanup() {
+ static int cleanup_done;
+ if (!cleanup_done) {
+ cleanup_done = 1;
+ int s = BsdAttachListener::listener();
+ if (s != -1) {
+ ::close(s);
+ }
+ if (BsdAttachListener::has_path()) {
+ ::unlink(BsdAttachListener::path());
+ }
+ }
+ }
+}
+
+// Initialization - create a listener socket and bind it to a file
+
+int BsdAttachListener::init() {
+ char path[UNIX_PATH_MAX]; // socket file
+ char initial_path[UNIX_PATH_MAX]; // socket file during setup
+ int listener; // listener socket (file descriptor)
+
+ // register function to cleanup
+ ::atexit(listener_cleanup);
+
+ int n = snprintf(path, UNIX_PATH_MAX, "%s/.java_pid%d",
+ os::get_temp_directory(), os::current_process_id());
+ if (n < (int)UNIX_PATH_MAX) {
+ n = snprintf(initial_path, UNIX_PATH_MAX, "%s.tmp", path);
+ }
+ if (n >= (int)UNIX_PATH_MAX) {
+ return -1;
+ }
+
+ // create the listener socket
+ listener = ::socket(PF_UNIX, SOCK_STREAM, 0);
+ if (listener == -1) {
+ return -1;
+ }
+
+ // bind socket
+ struct sockaddr_un addr;
+ addr.sun_family = AF_UNIX;
+ strcpy(addr.sun_path, initial_path);
+ ::unlink(initial_path);
+ int res = ::bind(listener, (struct sockaddr*)&addr, sizeof(addr));
+ if (res == -1) {
+ RESTARTABLE(::close(listener), res);
+ return -1;
+ }
+
+ // put in listen mode, set permissions, and rename into place
+ res = ::listen(listener, 5);
+ if (res == 0) {
+ RESTARTABLE(::chmod(initial_path, S_IREAD|S_IWRITE), res);
+ if (res == 0) {
+ res = ::rename(initial_path, path);
+ }
+ }
+ if (res == -1) {
+ RESTARTABLE(::close(listener), res);
+ ::unlink(initial_path);
+ return -1;
+ }
+ set_path(path);
+ set_listener(listener);
+
+ return 0;
+}
+
+// Given a socket that is connected to a peer we read the request and
+// create an AttachOperation. As the socket is blocking there is potential
+// for a denial-of-service if the peer does not response. However this happens
+// after the peer credentials have been checked and in the worst case it just
+// means that the attach listener thread is blocked.
+//
+BsdAttachOperation* BsdAttachListener::read_request(int s) {
+ char ver_str[8];
+ sprintf(ver_str, "%d", ATTACH_PROTOCOL_VER);
+
+ // The request is a sequence of strings so we first figure out the
+ // expected count and the maximum possible length of the request.
+ // The request is:
+ // <ver>0<cmd>0<arg>0<arg>0<arg>0
+ // where <ver> is the protocol version (1), <cmd> is the command
+ // name ("load", "datadump", ...), and <arg> is an argument
+ int expected_str_count = 2 + AttachOperation::arg_count_max;
+ const int max_len = (sizeof(ver_str) + 1) + (AttachOperation::name_length_max + 1) +
+ AttachOperation::arg_count_max*(AttachOperation::arg_length_max + 1);
+
+ char buf[max_len];
+ int str_count = 0;
+
+ // Read until all (expected) strings have been read, the buffer is
+ // full, or EOF.
+
+ int off = 0;
+ int left = max_len;
+
+ do {
+ int n;
+ RESTARTABLE(read(s, buf+off, left), n);
+ if (n == -1) {
+ return NULL; // reset by peer or other error
+ }
+ if (n == 0) {
+ break;
+ }
+ for (int i=0; i<n; i++) {
+ if (buf[off+i] == 0) {
+ // EOS found
+ str_count++;
+
+ // The first string is <ver> so check it now to
+ // check for protocol mis-match
+ if (str_count == 1) {
+ if ((strlen(buf) != strlen(ver_str)) ||
+ (atoi(buf) != ATTACH_PROTOCOL_VER)) {
+ char msg[32];
+ sprintf(msg, "%d\n", ATTACH_ERROR_BADVERSION);
+ write_fully(s, msg, strlen(msg));
+ return NULL;
+ }
+ }
+ }
+ }
+ off += n;
+ left -= n;
+ } while (left > 0 && str_count < expected_str_count);
+
+ if (str_count != expected_str_count) {
+ return NULL; // incomplete request
+ }
+
+ // parse request
+
+ ArgumentIterator args(buf, (max_len)-left);
+
+ // version already checked
+ char* v = args.next();
+
+ char* name = args.next();
+ if (name == NULL || strlen(name) > AttachOperation::name_length_max) {
+ return NULL;
+ }
+
+ BsdAttachOperation* op = new BsdAttachOperation(name);
+
+ for (int i=0; i<AttachOperation::arg_count_max; i++) {
+ char* arg = args.next();
+ if (arg == NULL) {
+ op->set_arg(i, NULL);
+ } else {
+ if (strlen(arg) > AttachOperation::arg_length_max) {
+ delete op;
+ return NULL;
+ }
+ op->set_arg(i, arg);
+ }
+ }
+
+ op->set_socket(s);
+ return op;
+}
+
+
+// Dequeue an operation
+//
+// In the Bsd implementation there is only a single operation and clients
+// cannot queue commands (except at the socket level).
+//
+BsdAttachOperation* BsdAttachListener::dequeue() {
+ for (;;) {
+ int s;
+
+ // wait for client to connect
+ struct sockaddr addr;
+ socklen_t len = sizeof(addr);
+ RESTARTABLE(::accept(listener(), &addr, &len), s);
+ if (s == -1) {
+ return NULL; // log a warning?
+ }
+
+ // get the credentials of the peer and check the effective uid/guid
+ // - check with jeff on this.
+#ifdef _ALLBSD_SOURCE
+ uid_t puid;
+ gid_t pgid;
+ if (::getpeereid(s, &puid, &pgid) != 0) {
+ int res;
+ RESTARTABLE(::close(s), res);
+ continue;
+ }
+#else
+ struct ucred cred_info;
+ socklen_t optlen = sizeof(cred_info);
+ if (::getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void*)&cred_info, &optlen) == -1) {
+ int res;
+ RESTARTABLE(::close(s), res);
+ continue;
+ }
+ uid_t puid = cred_info.uid;
+ gid_t pgid = cred_info.gid;
+#endif
+ uid_t euid = geteuid();
+ gid_t egid = getegid();
+
+ if (puid != euid || pgid != egid) {
+ int res;
+ RESTARTABLE(::close(s), res);
+ continue;
+ }
+
+ // peer credential look okay so we read the request
+ BsdAttachOperation* op = read_request(s);
+ if (op == NULL) {
+ int res;
+ RESTARTABLE(::close(s), res);
+ continue;
+ } else {
+ return op;
+ }
+ }
+}
+
+// write the given buffer to the socket
+int BsdAttachListener::write_fully(int s, char* buf, int len) {
+ do {
+ int n = ::write(s, buf, len);
+ if (n == -1) {
+ if (errno != EINTR) return -1;
+ } else {
+ buf += n;
+ len -= n;
+ }
+ }
+ while (len > 0);
+ return 0;
+}
+
+// Complete an operation by sending the operation result and any result
+// output to the client. At this time the socket is in blocking mode so
+// potentially we can block if there is a lot of data and the client is
+// non-responsive. For most operations this is a non-issue because the
+// default send buffer is sufficient to buffer everything. In the future
+// if there are operations that involves a very big reply then it the
+// socket could be made non-blocking and a timeout could be used.
+
+void BsdAttachOperation::complete(jint result, bufferedStream* st) {
+ JavaThread* thread = JavaThread::current();
+ ThreadBlockInVM tbivm(thread);
+
+ thread->set_suspend_equivalent();
+ // cleared by handle_special_suspend_equivalent_condition() or
+ // java_suspend_self() via check_and_wait_while_suspended()
+
+ // write operation result
+ char msg[32];
+ sprintf(msg, "%d\n", result);
+ int rc = BsdAttachListener::write_fully(this->socket(), msg, strlen(msg));
+
+ // write any result data
+ if (rc == 0) {
+ BsdAttachListener::write_fully(this->socket(), (char*) st->base(), st->size());
+ ::shutdown(this->socket(), 2);
+ }
+
+ // done
+ RESTARTABLE(::close(this->socket()), rc);
+
+ // were we externally suspended while we were waiting?
+ thread->check_and_wait_while_suspended();
+
+ delete this;
+}
+
+
+// AttachListener functions
+
+AttachOperation* AttachListener::dequeue() {
+ JavaThread* thread = JavaThread::current();
+ ThreadBlockInVM tbivm(thread);
+
+ thread->set_suspend_equivalent();
+ // cleared by handle_special_suspend_equivalent_condition() or
+ // java_suspend_self() via check_and_wait_while_suspended()
+
+ AttachOperation* op = BsdAttachListener::dequeue();
+
+ // were we externally suspended while we were waiting?
+ thread->check_and_wait_while_suspended();
+
+ return op;
+}
+
+int AttachListener::pd_init() {
+ JavaThread* thread = JavaThread::current();
+ ThreadBlockInVM tbivm(thread);
+
+ thread->set_suspend_equivalent();
+ // cleared by handle_special_suspend_equivalent_condition() or
+ // java_suspend_self() via check_and_wait_while_suspended()
+
+ int ret_code = BsdAttachListener::init();
+
+ // were we externally suspended while we were waiting?
+ thread->check_and_wait_while_suspended();
+
+ return ret_code;
+}
+
+// Attach Listener is started lazily except in the case when
+// +ReduseSignalUsage is used
+bool AttachListener::init_at_startup() {
+ if (ReduceSignalUsage) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+// If the file .attach_pid<pid> exists in the working directory
+// or /tmp then this is the trigger to start the attach mechanism
+bool AttachListener::is_init_trigger() {
+ if (init_at_startup() || is_initialized()) {
+ return false; // initialized at startup or already initialized
+ }
+ char path[PATH_MAX + 1];
+ int ret;
+ struct stat st;
+
+ snprintf(path, PATH_MAX + 1, "%s/.attach_pid%d",
+ os::get_temp_directory(), os::current_process_id());
+ RESTARTABLE(::stat(path, &st), ret);
+ if (ret == 0) {
+ // simple check to avoid starting the attach mechanism when
+ // a bogus user creates the file
+ if (st.st_uid == geteuid()) {
+ init();
+ return true;
+ }
+ }
+ return false;
+}
+
+// if VM aborts then remove listener
+void AttachListener::abort() {
+ listener_cleanup();
+}
+
+void AttachListener::pd_data_dump() {
+ os::signal_notify(SIGQUIT);
+}
+
+AttachOperationFunctionInfo* AttachListener::pd_find_operation(const char* n) {
+ return NULL;
+}
+
+jint AttachListener::pd_set_flag(AttachOperation* op, outputStream* out) {
+ out->print_cr("flag '%s' cannot be changed", op->arg(0));
+ return JNI_ERR;
+}
+
+void AttachListener::pd_detachall() {
+ // do nothing for now
+}
diff --git a/src/os/bsd/vm/c1_globals_bsd.hpp b/src/os/bsd/vm/c1_globals_bsd.hpp
new file mode 100644
index 000000000..27e26af11
--- /dev/null
+++ b/src/os/bsd/vm/c1_globals_bsd.hpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef OS_BSD_VM_C1_GLOBALS_BSD_HPP
+#define OS_BSD_VM_C1_GLOBALS_BSD_HPP
+
+#include "utilities/globalDefinitions.hpp"
+#include "utilities/macros.hpp"
+
+//
+// Sets the default values for operating system dependent flags used by the
+// client compiler. (see c1_globals.hpp)
+//
+
+#endif // OS_BSD_VM_C1_GLOBALS_BSD_HPP
diff --git a/src/os/bsd/vm/c2_globals_bsd.hpp b/src/os/bsd/vm/c2_globals_bsd.hpp
new file mode 100644
index 000000000..21737f19b
--- /dev/null
+++ b/src/os/bsd/vm/c2_globals_bsd.hpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef OS_BSD_VM_C2_GLOBALS_BSD_HPP
+#define OS_BSD_VM_C2_GLOBALS_BSD_HPP
+
+#include "utilities/globalDefinitions.hpp"
+#include "utilities/macros.hpp"
+
+//
+// Sets the default values for operating system dependent flags used by the
+// server compiler. (see c2_globals.hpp)
+//
+
+#endif // OS_BSD_VM_C2_GLOBALS_BSD_HPP
diff --git a/src/os/bsd/vm/chaitin_bsd.cpp b/src/os/bsd/vm/chaitin_bsd.cpp
new file mode 100644
index 000000000..e4925644d
--- /dev/null
+++ b/src/os/bsd/vm/chaitin_bsd.cpp
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ *
+ * 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 "precompiled.hpp"
+#include "opto/chaitin.hpp"
+#include "opto/machnode.hpp"
+
+void PhaseRegAlloc::pd_preallocate_hook() {
+ // no action
+}
+
+#ifdef ASSERT
+void PhaseRegAlloc::pd_postallocate_verify_hook() {
+ // no action
+}
+#endif
+
+
+// Reconciliation History
+// chaitin_solaris.cpp 1.7 99/07/12 23:54:22
+// End
diff --git a/src/os/bsd/vm/decoder_bsd.cpp b/src/os/bsd/vm/decoder_bsd.cpp
new file mode 100644
index 000000000..dd959298f
--- /dev/null
+++ b/src/os/bsd/vm/decoder_bsd.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "prims/jvm.h"
+#include "utilities/decoder.hpp"
+
+#include <cxxabi.h>
+
+#ifdef __APPLE__
+
+void Decoder::initialize() {
+ _initialized = true;
+}
+
+void Decoder::uninitialize() {
+ _initialized = false;
+}
+
+bool Decoder::can_decode_C_frame_in_vm() {
+ return false;
+}
+
+Decoder::decoder_status Decoder::decode(address addr, const char* filepath, char *buf, int buflen, int *offset) {
+ return symbol_not_found;
+}
+
+
+#endif
+
+bool Decoder::demangle(const char* symbol, char *buf, int buflen) {
+ int status;
+ char* result;
+ size_t size = (size_t)buflen;
+
+ // Don't pass buf to __cxa_demangle. In case of the 'buf' is too small,
+ // __cxa_demangle will call system "realloc" for additional memory, which
+ // may use different malloc/realloc mechanism that allocates 'buf'.
+ if ((result = abi::__cxa_demangle(symbol, NULL, NULL, &status)) != NULL) {
+ jio_snprintf(buf, buflen, "%s", result);
+ // call c library's free
+ ::free(result);
+ return true;
+ }
+ return false;
+}
diff --git a/src/os/bsd/vm/dtraceJSDT_bsd.cpp b/src/os/bsd/vm/dtraceJSDT_bsd.cpp
new file mode 100644
index 000000000..0f340fb57
--- /dev/null
+++ b/src/os/bsd/vm/dtraceJSDT_bsd.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "classfile/javaClasses.hpp"
+#include "code/codeBlob.hpp"
+#include "memory/allocation.hpp"
+#include "prims/jvm.h"
+#include "runtime/dtraceJSDT.hpp"
+#include "runtime/jniHandles.hpp"
+#include "runtime/os.hpp"
+#include "runtime/signature.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+int DTraceJSDT::pd_activate(
+ void* baseAddress, jstring module,
+ jint providers_count, JVM_DTraceProvider* providers) {
+ return -1;
+}
+
+void DTraceJSDT::pd_dispose(int handle) {
+}
+
+jboolean DTraceJSDT::pd_is_supported() {
+ return false;
+}
diff --git a/src/os/bsd/vm/globals_bsd.hpp b/src/os/bsd/vm/globals_bsd.hpp
new file mode 100644
index 000000000..213f47009
--- /dev/null
+++ b/src/os/bsd/vm/globals_bsd.hpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef OS_BSD_VM_GLOBALS_BSD_HPP
+#define OS_BSD_VM_GLOBALS_BSD_HPP
+
+//
+// Defines Bsd specific flags. They are not available on other platforms.
+//
+#define RUNTIME_OS_FLAGS(develop, develop_pd, product, product_pd, diagnostic, notproduct) \
+ product(bool, UseOprofile, false, \
+ "enable support for Oprofile profiler") \
+ \
+ product(bool, UseBsdPosixThreadCPUClocks, true, \
+ "enable fast Bsd Posix clocks where available") \
+/* NB: The default value of UseBsdPosixThreadCPUClocks may be \
+ overridden in Arguments::parse_each_vm_init_arg. */ \
+ \
+ product(bool, UseHugeTLBFS, false, \
+ "Use MAP_HUGETLB for large pages") \
+ \
+ product(bool, UseSHM, false, \
+ "Use SYSV shared memory for large pages")
+
+//
+// Defines Bsd-specific default values. The flags are available on all
+// platforms, but they may have different default values on other platforms.
+//
+define_pd_global(bool, UseLargePages, false);
+define_pd_global(bool, UseLargePagesIndividualAllocation, false);
+define_pd_global(bool, UseOSErrorReporting, false);
+define_pd_global(bool, UseThreadPriorities, true) ;
+
+#endif // OS_BSD_VM_GLOBALS_BSD_HPP
diff --git a/src/os/bsd/vm/interfaceSupport_bsd.hpp b/src/os/bsd/vm/interfaceSupport_bsd.hpp
new file mode 100644
index 000000000..795bf4d16
--- /dev/null
+++ b/src/os/bsd/vm/interfaceSupport_bsd.hpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef OS_BSD_VM_INTERFACESUPPORT_BSD_HPP
+#define OS_BSD_VM_INTERFACESUPPORT_BSD_HPP
+
+// Contains inlined functions for class InterfaceSupport
+
+static inline void serialize_memory(JavaThread *thread) {
+ os::write_memory_serialize_page(thread);
+}
+
+#endif // OS_BSD_VM_INTERFACESUPPORT_BSD_HPP
diff --git a/src/os/bsd/vm/jsig.c b/src/os/bsd/vm/jsig.c
new file mode 100644
index 000000000..a8d98a084
--- /dev/null
+++ b/src/os/bsd/vm/jsig.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/* CopyrightVersion 1.2 */
+
+/* This is a special library that should be loaded before libc &
+ * libthread to interpose the signal handler installation functions:
+ * sigaction(), signal(), sigset().
+ * Used for signal-chaining. See RFE 4381843.
+ */
+
+#include <signal.h>
+#include <dlfcn.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+
+#define MAXSIGNUM 32
+#define MASK(sig) ((unsigned int)1 << sig)
+
+static struct sigaction sact[MAXSIGNUM]; /* saved signal handlers */
+static unsigned int jvmsigs = 0; /* signals used by jvm */
+
+/* used to synchronize the installation of signal handlers */
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static pthread_t tid = 0;
+
+typedef void (*sa_handler_t)(int);
+typedef void (*sa_sigaction_t)(int, siginfo_t *, void *);
+typedef sa_handler_t (*signal_t)(int, sa_handler_t);
+typedef int (*sigaction_t)(int, const struct sigaction *, struct sigaction *);
+
+static signal_t os_signal = 0; /* os's version of signal()/sigset() */
+static sigaction_t os_sigaction = 0; /* os's version of sigaction() */
+
+static bool jvm_signal_installing = false;
+static bool jvm_signal_installed = false;
+
+static void signal_lock() {
+ pthread_mutex_lock(&mutex);
+ /* When the jvm is installing its set of signal handlers, threads
+ * other than the jvm thread should wait */
+ if (jvm_signal_installing) {
+ if (tid != pthread_self()) {
+ pthread_cond_wait(&cond, &mutex);
+ }
+ }
+}
+
+static void signal_unlock() {
+ pthread_mutex_unlock(&mutex);
+}
+
+static sa_handler_t call_os_signal(int sig, sa_handler_t disp,
+ bool is_sigset) {
+ if (os_signal == NULL) {
+ if (!is_sigset) {
+ os_signal = (signal_t)dlsym(RTLD_NEXT, "signal");
+ } else {
+ os_signal = (signal_t)dlsym(RTLD_NEXT, "sigset");
+ }
+ if (os_signal == NULL) {
+ printf("%s\n", dlerror());
+ exit(0);
+ }
+ }
+ return (*os_signal)(sig, disp);
+}
+
+static void save_signal_handler(int sig, sa_handler_t disp) {
+ sigset_t set;
+ sact[sig].sa_handler = disp;
+ sigemptyset(&set);
+ sact[sig].sa_mask = set;
+ sact[sig].sa_flags = 0;
+}
+
+static sa_handler_t set_signal(int sig, sa_handler_t disp, bool is_sigset) {
+ sa_handler_t oldhandler;
+ bool sigused;
+
+ signal_lock();
+
+ sigused = (MASK(sig) & jvmsigs) != 0;
+ if (jvm_signal_installed && sigused) {
+ /* jvm has installed its signal handler for this signal. */
+ /* Save the handler. Don't really install it. */
+ oldhandler = sact[sig].sa_handler;
+ save_signal_handler(sig, disp);
+
+ signal_unlock();
+ return oldhandler;
+ } else if (jvm_signal_installing) {
+ /* jvm is installing its signal handlers. Install the new
+ * handlers and save the old ones. jvm uses sigaction().
+ * Leave the piece here just in case. */
+ oldhandler = call_os_signal(sig, disp, is_sigset);
+ save_signal_handler(sig, oldhandler);
+
+ /* Record the signals used by jvm */
+ jvmsigs |= MASK(sig);
+
+ signal_unlock();
+ return oldhandler;
+ } else {
+ /* jvm has no relation with this signal (yet). Install the
+ * the handler. */
+ oldhandler = call_os_signal(sig, disp, is_sigset);
+
+ signal_unlock();
+ return oldhandler;
+ }
+}
+
+sa_handler_t signal(int sig, sa_handler_t disp) {
+ return set_signal(sig, disp, false);
+}
+
+sa_handler_t sigset(int sig, sa_handler_t disp) {
+ printf("sigset() is not supported by BSD");
+ exit(0);
+ }
+
+static int call_os_sigaction(int sig, const struct sigaction *act,
+ struct sigaction *oact) {
+ if (os_sigaction == NULL) {
+ os_sigaction = (sigaction_t)dlsym(RTLD_NEXT, "sigaction");
+ if (os_sigaction == NULL) {
+ printf("%s\n", dlerror());
+ exit(0);
+ }
+ }
+ return (*os_sigaction)(sig, act, oact);
+}
+
+int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) {
+ int res;
+ bool sigused;
+ struct sigaction oldAct;
+
+ signal_lock();
+
+ sigused = (MASK(sig) & jvmsigs) != 0;
+ if (jvm_signal_installed && sigused) {
+ /* jvm has installed its signal handler for this signal. */
+ /* Save the handler. Don't really install it. */
+ if (oact != NULL) {
+ *oact = sact[sig];
+ }
+ if (act != NULL) {
+ sact[sig] = *act;
+ }
+
+ signal_unlock();
+ return 0;
+ } else if (jvm_signal_installing) {
+ /* jvm is installing its signal handlers. Install the new
+ * handlers and save the old ones. */
+ res = call_os_sigaction(sig, act, &oldAct);
+ sact[sig] = oldAct;
+ if (oact != NULL) {
+ *oact = oldAct;
+ }
+
+ /* Record the signals used by jvm */
+ jvmsigs |= MASK(sig);
+
+ signal_unlock();
+ return res;
+ } else {
+ /* jvm has no relation with this signal (yet). Install the
+ * the handler. */
+ res = call_os_sigaction(sig, act, oact);
+
+ signal_unlock();
+ return res;
+ }
+}
+
+/* The three functions for the jvm to call into */
+void JVM_begin_signal_setting() {
+ signal_lock();
+ jvm_signal_installing = true;
+ tid = pthread_self();
+ signal_unlock();
+}
+
+void JVM_end_signal_setting() {
+ signal_lock();
+ jvm_signal_installed = true;
+ jvm_signal_installing = false;
+ pthread_cond_broadcast(&cond);
+ signal_unlock();
+}
+
+struct sigaction *JVM_get_signal_action(int sig) {
+ /* Does race condition make sense here? */
+ if ((MASK(sig) & jvmsigs) != 0) {
+ return &sact[sig];
+ }
+ return NULL;
+}
diff --git a/src/os/bsd/vm/jvm_bsd.cpp b/src/os/bsd/vm/jvm_bsd.cpp
new file mode 100644
index 000000000..a82863135
--- /dev/null
+++ b/src/os/bsd/vm/jvm_bsd.cpp
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "prims/jvm.h"
+#include "runtime/interfaceSupport.hpp"
+#include "runtime/osThread.hpp"
+
+#include <signal.h>
+
+
+// sun.misc.Signal ///////////////////////////////////////////////////////////
+// Signal code is mostly copied from classic vm, signals_md.c 1.4 98/08/23
+/*
+ * This function is included primarily as a debugging aid. If Java is
+ * running in a console window, then pressing <CTRL-\\> will cause
+ * the current state of all active threads and monitors to be written
+ * to the console window.
+ */
+
+JVM_ENTRY_NO_ENV(void*, JVM_RegisterSignal(jint sig, void* handler))
+ // Copied from classic vm
+ // signals_md.c 1.4 98/08/23
+ void* newHandler = handler == (void *)2
+ ? os::user_handler()
+ : handler;
+ switch (sig) {
+ /* The following are already used by the VM. */
+ case INTERRUPT_SIGNAL:
+ case SIGFPE:
+ case SIGILL:
+ case SIGSEGV:
+
+ /* The following signal is used by the VM to dump thread stacks unless
+ ReduceSignalUsage is set, in which case the user is allowed to set
+ his own _native_ handler for this signal; thus, in either case,
+ we do not allow JVM_RegisterSignal to change the handler. */
+ case BREAK_SIGNAL:
+ return (void *)-1;
+
+ /* The following signals are used for Shutdown Hooks support. However, if
+ ReduceSignalUsage (-Xrs) is set, Shutdown Hooks must be invoked via
+ System.exit(), Java is not allowed to use these signals, and the the
+ user is allowed to set his own _native_ handler for these signals and
+ invoke System.exit() as needed. Terminator.setup() is avoiding
+ registration of these signals when -Xrs is present.
+ - If the HUP signal is ignored (from the nohup) command, then Java
+ is not allowed to use this signal.
+ */
+
+ case SHUTDOWN1_SIGNAL:
+ case SHUTDOWN2_SIGNAL:
+ case SHUTDOWN3_SIGNAL:
+ if (ReduceSignalUsage) return (void*)-1;
+ if (os::Bsd::is_sig_ignored(sig)) return (void*)1;
+ }
+
+ void* oldHandler = os::signal(sig, newHandler);
+ if (oldHandler == os::user_handler()) {
+ return (void *)2;
+ } else {
+ return oldHandler;
+ }
+JVM_END
+
+
+JVM_ENTRY_NO_ENV(jboolean, JVM_RaiseSignal(jint sig))
+ if (ReduceSignalUsage) {
+ // do not allow SHUTDOWN1_SIGNAL,SHUTDOWN2_SIGNAL,SHUTDOWN3_SIGNAL,
+ // BREAK_SIGNAL to be raised when ReduceSignalUsage is set, since
+ // no handler for them is actually registered in JVM or via
+ // JVM_RegisterSignal.
+ if (sig == SHUTDOWN1_SIGNAL || sig == SHUTDOWN2_SIGNAL ||
+ sig == SHUTDOWN3_SIGNAL || sig == BREAK_SIGNAL) {
+ return JNI_FALSE;
+ }
+ }
+ else if ((sig == SHUTDOWN1_SIGNAL || sig == SHUTDOWN2_SIGNAL ||
+ sig == SHUTDOWN3_SIGNAL) && os::Bsd::is_sig_ignored(sig)) {
+ // do not allow SHUTDOWN1_SIGNAL to be raised when SHUTDOWN1_SIGNAL
+ // is ignored, since no handler for them is actually registered in JVM
+ // or via JVM_RegisterSignal.
+ // This also applies for SHUTDOWN2_SIGNAL and SHUTDOWN3_SIGNAL
+ return JNI_FALSE;
+ }
+
+ os::signal_raise(sig);
+ return JNI_TRUE;
+JVM_END
+
+/*
+ All the defined signal names for Bsd.
+
+ NOTE that not all of these names are accepted by our Java implementation
+
+ Via an existing claim by the VM, sigaction restrictions, or
+ the "rules of Unix" some of these names will be rejected at runtime.
+ For example the VM sets up to handle USR1, sigaction returns EINVAL for
+ STOP, and Bsd simply doesn't allow catching of KILL.
+
+ Here are the names currently accepted by a user of sun.misc.Signal with
+ 1.4.1 (ignoring potential interaction with use of chaining, etc):
+
+ HUP, INT, TRAP, ABRT, IOT, BUS, USR2, PIPE, ALRM, TERM, STKFLT,
+ CLD, CHLD, CONT, TSTP, TTIN, TTOU, URG, XCPU, XFSZ, VTALRM, PROF,
+ WINCH, POLL, IO, PWR, SYS
+
+*/
+
+struct siglabel {
+ const char *name;
+ int number;
+};
+
+struct siglabel siglabels[] = {
+ /* derived from /usr/include/bits/signum.h on RH7.2 */
+ "HUP", SIGHUP, /* Hangup (POSIX). */
+ "INT", SIGINT, /* Interrupt (ANSI). */
+ "QUIT", SIGQUIT, /* Quit (POSIX). */
+ "ILL", SIGILL, /* Illegal instruction (ANSI). */
+ "TRAP", SIGTRAP, /* Trace trap (POSIX). */
+ "ABRT", SIGABRT, /* Abort (ANSI). */
+ "EMT", SIGEMT, /* EMT trap */
+ "FPE", SIGFPE, /* Floating-point exception (ANSI). */
+ "KILL", SIGKILL, /* Kill, unblockable (POSIX). */
+ "BUS", SIGBUS, /* BUS error (4.2 BSD). */
+ "SEGV", SIGSEGV, /* Segmentation violation (ANSI). */
+ "SYS", SIGSYS, /* Bad system call. Only on some Bsden! */
+ "PIPE", SIGPIPE, /* Broken pipe (POSIX). */
+ "ALRM", SIGALRM, /* Alarm clock (POSIX). */
+ "TERM", SIGTERM, /* Termination (ANSI). */
+ "URG", SIGURG, /* Urgent condition on socket (4.2 BSD). */
+ "STOP", SIGSTOP, /* Stop, unblockable (POSIX). */
+ "TSTP", SIGTSTP, /* Keyboard stop (POSIX). */
+ "CONT", SIGCONT, /* Continue (POSIX). */
+ "CHLD", SIGCHLD, /* Child status has changed (POSIX). */
+ "TTIN", SIGTTIN, /* Background read from tty (POSIX). */
+ "TTOU", SIGTTOU, /* Background write to tty (POSIX). */
+ "IO", SIGIO, /* I/O now possible (4.2 BSD). */
+ "XCPU", SIGXCPU, /* CPU limit exceeded (4.2 BSD). */
+ "XFSZ", SIGXFSZ, /* File size limit exceeded (4.2 BSD). */
+ "VTALRM", SIGVTALRM, /* Virtual alarm clock (4.2 BSD). */
+ "PROF", SIGPROF, /* Profiling alarm clock (4.2 BSD). */
+ "WINCH", SIGWINCH, /* Window size change (4.3 BSD, Sun). */
+ "INFO", SIGINFO, /* Information request. */
+ "USR1", SIGUSR1, /* User-defined signal 1 (POSIX). */
+ "USR2", SIGUSR2 /* User-defined signal 2 (POSIX). */
+ };
+
+JVM_ENTRY_NO_ENV(jint, JVM_FindSignal(const char *name))
+
+ /* find and return the named signal's number */
+
+ for(uint i=0; i<ARRAY_SIZE(siglabels); i++)
+ if(!strcmp(name, siglabels[i].name))
+ return siglabels[i].number;
+
+ return -1;
+
+JVM_END
+
+// used by os::exception_name()
+extern bool signal_name(int signo, char* buf, size_t len) {
+ for(uint i = 0; i < ARRAY_SIZE(siglabels); i++) {
+ if (signo == siglabels[i].number) {
+ jio_snprintf(buf, len, "SIG%s", siglabels[i].name);
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/src/os/bsd/vm/jvm_bsd.h b/src/os/bsd/vm/jvm_bsd.h
new file mode 100644
index 000000000..971d98ac4
--- /dev/null
+++ b/src/os/bsd/vm/jvm_bsd.h
@@ -0,0 +1,120 @@
+/*
+ * 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.
+ *
+ * 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 OS_BSD_VM_JVM_BSD_H
+#define OS_BSD_VM_JVM_BSD_H
+
+/*
+// HotSpot integration note:
+//
+// This is derived from the JDK classic file:
+// "$JDK/src/solaris/javavm/export/jvm_md.h":15 (ver. 1.10 98/04/22)
+// All local includes have been commented out.
+*/
+
+
+#ifndef JVM_MD_H
+#define JVM_MD_H
+
+/*
+ * This file is currently collecting system-specific dregs for the
+ * JNI conversion, which should be sorted out later.
+ */
+
+#include <dirent.h> /* For DIR */
+#include <sys/param.h> /* For MAXPATHLEN */
+#include <unistd.h> /* For F_OK, R_OK, W_OK */
+
+#define JNI_ONLOAD_SYMBOLS {"JNI_OnLoad"}
+#define JNI_ONUNLOAD_SYMBOLS {"JNI_OnUnload"}
+#define JVM_ONLOAD_SYMBOLS {"JVM_OnLoad"}
+#define AGENT_ONLOAD_SYMBOLS {"Agent_OnLoad"}
+#define AGENT_ONUNLOAD_SYMBOLS {"Agent_OnUnload"}
+#define AGENT_ONATTACH_SYMBOLS {"Agent_OnAttach"}
+
+#define JNI_LIB_PREFIX "lib"
+#ifdef __APPLE__
+#define JNI_LIB_SUFFIX ".dylib"
+#else
+#define JNI_LIB_SUFFIX ".so"
+#endif
+
+// Hack: MAXPATHLEN is 4095 on some Bsd and 4096 on others. This may
+// cause problems if JVM and the rest of JDK are built on different
+// Bsd releases. Here we define JVM_MAXPATHLEN to be MAXPATHLEN + 1,
+// so buffers declared in VM are always >= 4096.
+#define JVM_MAXPATHLEN MAXPATHLEN + 1
+
+#define JVM_R_OK R_OK
+#define JVM_W_OK W_OK
+#define JVM_X_OK X_OK
+#define JVM_F_OK F_OK
+
+/*
+ * File I/O
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+/* O Flags */
+
+#define JVM_O_RDONLY O_RDONLY
+#define JVM_O_WRONLY O_WRONLY
+#define JVM_O_RDWR O_RDWR
+#define JVM_O_O_APPEND O_APPEND
+#define JVM_O_EXCL O_EXCL
+#define JVM_O_CREAT O_CREAT
+
+/* Signal definitions */
+
+#define BREAK_SIGNAL SIGQUIT /* Thread dumping support. */
+#define INTERRUPT_SIGNAL SIGUSR1 /* Interruptible I/O support. */
+#define SHUTDOWN1_SIGNAL SIGHUP /* Shutdown Hooks support. */
+#define SHUTDOWN2_SIGNAL SIGINT
+#define SHUTDOWN3_SIGNAL SIGTERM
+
+#ifndef SIGRTMIN
+#ifdef __OpenBSD__
+#define SIGRTMIN 1
+#else
+#define SIGRTMIN 33
+#endif
+#endif
+#ifndef SIGRTMAX
+#ifdef __OpenBSD__
+#define SIGRTMAX 31
+#else
+#define SIGRTMAX 63
+#endif
+#endif
+#endif /* JVM_MD_H */
+
+// Reconciliation History
+// jvm_solaris.h 1.6 99/06/22 16:38:47
+// End
+
+#endif // OS_BSD_VM_JVM_BSD_H
diff --git a/src/os/bsd/vm/mutex_bsd.cpp b/src/os/bsd/vm/mutex_bsd.cpp
new file mode 100644
index 000000000..f39482ea6
--- /dev/null
+++ b/src/os/bsd/vm/mutex_bsd.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "mutex_bsd.inline.hpp"
+#include "runtime/interfaceSupport.hpp"
+#include "runtime/mutex.hpp"
+#include "thread_bsd.inline.hpp"
+#include "utilities/events.hpp"
+
+// put OS-includes here
+# include <signal.h>
diff --git a/src/os/bsd/vm/mutex_bsd.inline.hpp b/src/os/bsd/vm/mutex_bsd.inline.hpp
new file mode 100644
index 000000000..f75267fb5
--- /dev/null
+++ b/src/os/bsd/vm/mutex_bsd.inline.hpp
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ *
+ * 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 OS_BSD_VM_MUTEX_BSD_INLINE_HPP
+#define OS_BSD_VM_MUTEX_BSD_INLINE_HPP
+
+#include "os_bsd.inline.hpp"
+#include "runtime/interfaceSupport.hpp"
+#include "thread_bsd.inline.hpp"
+
+
+// Reconciliation History
+// mutex_solaris.inline.hpp 1.5 99/06/22 16:38:49
+// End
+
+#endif // OS_BSD_VM_MUTEX_BSD_INLINE_HPP
diff --git a/src/os/bsd/vm/osThread_bsd.cpp b/src/os/bsd/vm/osThread_bsd.cpp
new file mode 100644
index 000000000..efac80376
--- /dev/null
+++ b/src/os/bsd/vm/osThread_bsd.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+// no precompiled headers
+#include "runtime/atomic.hpp"
+#include "runtime/handles.inline.hpp"
+#include "runtime/mutexLocker.hpp"
+#include "runtime/os.hpp"
+#include "runtime/osThread.hpp"
+#include "runtime/safepoint.hpp"
+#include "runtime/vmThread.hpp"
+#ifdef TARGET_ARCH_x86
+# include "assembler_x86.inline.hpp"
+#endif
+#ifdef TARGET_ARCH_sparc
+# include "assembler_sparc.inline.hpp"
+#endif
+#ifdef TARGET_ARCH_zero
+# include "assembler_zero.inline.hpp"
+#endif
+#ifdef TARGET_ARCH_arm
+# include "assembler_arm.inline.hpp"
+#endif
+#ifdef TARGET_ARCH_ppc
+# include "assembler_ppc.inline.hpp"
+#endif
+
+
+void OSThread::pd_initialize() {
+ assert(this != NULL, "check");
+ _thread_id = NULL;
+ _pthread_id = NULL;
+ _siginfo = NULL;
+ _ucontext = NULL;
+ _expanding_stack = 0;
+ _alt_sig_stack = NULL;
+
+ sigemptyset(&_caller_sigmask);
+
+ _startThread_lock = new Monitor(Mutex::event, "startThread_lock", true);
+ assert(_startThread_lock !=NULL, "check");
+}
+
+void OSThread::pd_destroy() {
+ delete _startThread_lock;
+}
diff --git a/src/os/bsd/vm/osThread_bsd.hpp b/src/os/bsd/vm/osThread_bsd.hpp
new file mode 100644
index 000000000..82dd34fcb
--- /dev/null
+++ b/src/os/bsd/vm/osThread_bsd.hpp
@@ -0,0 +1,165 @@
+/*
+ * 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.
+ *
+ * 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 OS_BSD_VM_OSTHREAD_BSD_HPP
+#define OS_BSD_VM_OSTHREAD_BSD_HPP
+
+ private:
+ int _thread_type;
+
+ public:
+
+ int thread_type() const {
+ return _thread_type;
+ }
+ void set_thread_type(int type) {
+ _thread_type = type;
+ }
+
+ private:
+
+#ifdef _ALLBSD_SOURCE
+ // _thread_id and _pthread_id are the same on BSD
+ // keep both to minimize code divergence in os_bsd.cpp
+ pthread_t _thread_id;
+ pthread_t _pthread_id;
+#else
+ // _thread_id is kernel thread id (similar to LWP id on Solaris). Each
+ // thread has a unique thread_id (BsdThreads or NPTL). It can be used
+ // to access /proc.
+ pid_t _thread_id;
+
+ // _pthread_id is the pthread id, which is used by library calls
+ // (e.g. pthread_kill).
+ pthread_t _pthread_id;
+#endif
+
+ sigset_t _caller_sigmask; // Caller's signal mask
+
+ public:
+
+ // Methods to save/restore caller's signal mask
+ sigset_t caller_sigmask() const { return _caller_sigmask; }
+ void set_caller_sigmask(sigset_t sigmask) { _caller_sigmask = sigmask; }
+
+#ifdef _ALLBSD_SOURCE
+ pthread_t thread_id() const {
+ return _thread_id;
+ }
+#else
+ pid_t thread_id() const {
+ return _thread_id;
+ }
+#endif
+#ifndef PRODUCT
+ // Used for debugging, return a unique integer for each thread.
+ intptr_t thread_identifier() const { return (intptr_t)_pthread_id; }
+#endif
+#ifdef ASSERT
+ // We expect no reposition failures so kill vm if we get one.
+ //
+ bool valid_reposition_failure() {
+ return false;
+ }
+#endif // ASSERT
+#ifdef _ALLBSD_SOURCE
+ void set_thread_id(pthread_t id) {
+ _thread_id = id;
+ }
+#else
+ void set_thread_id(pid_t id) {
+ _thread_id = id;
+ }
+#endif
+ pthread_t pthread_id() const {
+ return _pthread_id;
+ }
+ void set_pthread_id(pthread_t tid) {
+ _pthread_id = tid;
+ }
+
+ // ***************************************************************
+ // suspension support.
+ // ***************************************************************
+
+public:
+ // flags that support signal based suspend/resume on Bsd are in a
+ // separate class to avoid confusion with many flags in OSThread that
+ // are used by VM level suspend/resume.
+ os::Bsd::SuspendResume sr;
+
+ // _ucontext and _siginfo are used by SR_handler() to save thread context,
+ // and they will later be used to walk the stack or reposition thread PC.
+ // If the thread is not suspended in SR_handler() (e.g. self suspend),
+ // the value in _ucontext is meaningless, so we must use the last Java
+ // frame information as the frame. This will mean that for threads
+ // that are parked on a mutex the profiler (and safepoint mechanism)
+ // will see the thread as if it were still in the Java frame. This
+ // not a problem for the profiler since the Java frame is a close
+ // enough result. For the safepoint mechanism when the give it the
+ // Java frame we are not at a point where the safepoint needs the
+ // frame to that accurate (like for a compiled safepoint) since we
+ // should be in a place where we are native and will block ourselves
+ // if we transition.
+private:
+ void* _siginfo;
+ ucontext_t* _ucontext;
+ int _expanding_stack; /* non zero if manually expanding stack */
+ address _alt_sig_stack; /* address of base of alternate signal stack */
+
+public:
+ void* siginfo() const { return _siginfo; }
+ void set_siginfo(void* ptr) { _siginfo = ptr; }
+ ucontext_t* ucontext() const { return _ucontext; }
+ void set_ucontext(ucontext_t* ptr) { _ucontext = ptr; }
+ void set_expanding_stack(void) { _expanding_stack = 1; }
+ void clear_expanding_stack(void) { _expanding_stack = 0; }
+ int expanding_stack(void) { return _expanding_stack; }
+
+ void set_alt_sig_stack(address val) { _alt_sig_stack = val; }
+ address alt_sig_stack(void) { return _alt_sig_stack; }
+
+private:
+ Monitor* _startThread_lock; // sync parent and child in thread creation
+
+public:
+
+ Monitor* startThread_lock() const {
+ return _startThread_lock;
+ }
+
+ // ***************************************************************
+ // Platform dependent initialization and cleanup
+ // ***************************************************************
+
+private:
+
+ void pd_initialize();
+ void pd_destroy();
+
+// Reconciliation History
+// osThread_solaris.hpp 1.24 99/08/27 13:11:54
+// End
+
+#endif // OS_BSD_VM_OSTHREAD_BSD_HPP
diff --git a/src/os/bsd/vm/os_bsd.cpp b/src/os/bsd/vm/os_bsd.cpp
new file mode 100644
index 000000000..b783de69f
--- /dev/null
+++ b/src/os/bsd/vm/os_bsd.cpp
@@ -0,0 +1,5709 @@
+/*
+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+// no precompiled headers
+#include "classfile/classLoader.hpp"
+#include "classfile/systemDictionary.hpp"
+#include "classfile/vmSymbols.hpp"
+#include "code/icBuffer.hpp"
+#include "code/vtableStubs.hpp"
+#include "compiler/compileBroker.hpp"
+#include "interpreter/interpreter.hpp"
+#include "jvm_bsd.h"
+#include "memory/allocation.inline.hpp"
+#include "memory/filemap.hpp"
+#include "mutex_bsd.inline.hpp"
+#include "oops/oop.inline.hpp"
+#include "os_share_bsd.hpp"
+#include "prims/jniFastGetField.hpp"
+#include "prims/jvm.h"
+#include "prims/jvm_misc.hpp"
+#include "runtime/arguments.hpp"
+#include "runtime/extendedPC.hpp"
+#include "runtime/globals.hpp"
+#include "runtime/interfaceSupport.hpp"
+#include "runtime/java.hpp"
+#include "runtime/javaCalls.hpp"
+#include "runtime/mutexLocker.hpp"
+#include "runtime/objectMonitor.hpp"
+#include "runtime/osThread.hpp"
+#include "runtime/perfMemory.hpp"
+#include "runtime/sharedRuntime.hpp"
+#include "runtime/statSampler.hpp"
+#include "runtime/stubRoutines.hpp"
+#include "runtime/threadCritical.hpp"
+#include "runtime/timer.hpp"
+#include "services/attachListener.hpp"
+#include "services/runtimeService.hpp"
+#include "thread_bsd.inline.hpp"
+#include "utilities/decoder.hpp"
+#include "utilities/defaultStream.hpp"
+#include "utilities/events.hpp"
+#include "utilities/growableArray.hpp"
+#include "utilities/vmError.hpp"
+#ifdef TARGET_ARCH_x86
+# include "assembler_x86.inline.hpp"
+# include "nativeInst_x86.hpp"
+#endif
+#ifdef TARGET_ARCH_sparc
+# include "assembler_sparc.inline.hpp"
+# include "nativeInst_sparc.hpp"
+#endif
+#ifdef TARGET_ARCH_zero
+# include "assembler_zero.inline.hpp"
+# include "nativeInst_zero.hpp"
+#endif
+#ifdef TARGET_ARCH_arm
+# include "assembler_arm.inline.hpp"
+# include "nativeInst_arm.hpp"
+#endif
+#ifdef TARGET_ARCH_ppc
+# include "assembler_ppc.inline.hpp"
+# include "nativeInst_ppc.hpp"
+#endif
+#ifdef COMPILER1
+#include "c1/c1_Runtime1.hpp"
+#endif
+#ifdef COMPILER2
+#include "opto/runtime.hpp"
+#endif
+
+// put OS-includes here
+# include <sys/types.h>
+# include <sys/mman.h>
+# include <sys/stat.h>
+# include <sys/select.h>
+# include <pthread.h>
+# include <signal.h>
+# include <errno.h>
+# include <dlfcn.h>
+# include <stdio.h>
+# include <unistd.h>
+# include <sys/resource.h>
+# include <pthread.h>
+# include <sys/stat.h>
+# include <sys/time.h>
+# include <sys/times.h>
+# include <sys/utsname.h>
+# include <sys/socket.h>
+# include <sys/wait.h>
+# include <time.h>
+# include <pwd.h>
+# include <poll.h>
+# include <semaphore.h>
+# include <fcntl.h>
+# include <string.h>
+#ifdef _ALLBSD_SOURCE
+# include <sys/param.h>
+# include <sys/sysctl.h>
+#else
+# include <syscall.h>
+# include <sys/sysinfo.h>
+# include <gnu/libc-version.h>
+#endif
+# include <sys/ipc.h>
+# include <sys/shm.h>
+#ifndef __APPLE__
+# include <link.h>
+#endif
+# include <stdint.h>
+# include <inttypes.h>
+# include <sys/ioctl.h>
+
+#if defined(__FreeBSD__) || defined(__NetBSD__)
+# include <elf.h>
+#endif
+
+#ifdef __APPLE__
+#include <mach/mach.h> // semaphore_* API
+#include <mach-o/dyld.h>
+#endif
+
+#ifndef MAP_ANONYMOUS
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+
+#define MAX_PATH (2 * K)
+
+// for timer info max values which include all bits
+#define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF)
+#define SEC_IN_NANOSECS 1000000000LL
+
+#define LARGEPAGES_BIT (1 << 6)
+////////////////////////////////////////////////////////////////////////////////
+// global variables
+julong os::Bsd::_physical_memory = 0;
+
+#ifndef _ALLBSD_SOURCE
+address os::Bsd::_initial_thread_stack_bottom = NULL;
+uintptr_t os::Bsd::_initial_thread_stack_size = 0;
+#endif
+
+int (*os::Bsd::_clock_gettime)(clockid_t, struct timespec *) = NULL;
+#ifndef _ALLBSD_SOURCE
+int (*os::Bsd::_pthread_getcpuclockid)(pthread_t, clockid_t *) = NULL;
+Mutex* os::Bsd::_createThread_lock = NULL;
+#endif
+pthread_t os::Bsd::_main_thread;
+int os::Bsd::_page_size = -1;
+#ifndef _ALLBSD_SOURCE
+bool os::Bsd::_is_floating_stack = false;
+bool os::Bsd::_is_NPTL = false;
+bool os::Bsd::_supports_fast_thread_cpu_time = false;
+const char * os::Bsd::_glibc_version = NULL;
+const char * os::Bsd::_libpthread_version = NULL;
+#endif
+
+static jlong initial_time_count=0;
+
+static int clock_tics_per_sec = 100;
+
+// For diagnostics to print a message once. see run_periodic_checks
+static sigset_t check_signal_done;
+static bool check_signals = true;;
+
+static pid_t _initial_pid = 0;
+
+/* Signal number used to suspend/resume a thread */
+
+/* do not use any signal number less than SIGSEGV, see 4355769 */
+static int SR_signum = SIGUSR2;
+sigset_t SR_sigset;
+
+
+////////////////////////////////////////////////////////////////////////////////
+// utility functions
+
+static int SR_initialize();
+static int SR_finalize();
+
+julong os::available_memory() {
+ return Bsd::available_memory();
+}
+
+julong os::Bsd::available_memory() {
+#ifdef _ALLBSD_SOURCE
+ // XXXBSD: this is just a stopgap implementation
+ return physical_memory() >> 2;
+#else
+ // values in struct sysinfo are "unsigned long"
+ struct sysinfo si;
+ sysinfo(&si);
+
+ return (julong)si.freeram * si.mem_unit;
+#endif
+}
+
+julong os::physical_memory() {
+ return Bsd::physical_memory();
+}
+
+julong os::allocatable_physical_memory(julong size) {
+#ifdef _LP64
+ return size;
+#else
+ julong result = MIN2(size, (julong)3800*M);
+ if (!is_allocatable(result)) {
+ // See comments under solaris for alignment considerations
+ julong reasonable_size = (julong)2*G - 2 * os::vm_page_size();
+ result = MIN2(size, reasonable_size);
+ }
+ return result;
+#endif // _LP64
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// environment support
+
+bool os::getenv(const char* name, char* buf, int len) {
+ const char* val = ::getenv(name);
+ if (val != NULL && strlen(val) < (size_t)len) {
+ strcpy(buf, val);
+ return true;
+ }
+ if (len > 0) buf[0] = 0; // return a null string
+ return false;
+}
+
+
+// Return true if user is running as root.
+
+bool os::have_special_privileges() {
+ static bool init = false;
+ static bool privileges = false;
+ if (!init) {
+ privileges = (getuid() != geteuid()) || (getgid() != getegid());
+ init = true;
+ }
+ return privileges;
+}
+
+
+#ifndef _ALLBSD_SOURCE
+#ifndef SYS_gettid
+// i386: 224, ia64: 1105, amd64: 186, sparc 143
+#ifdef __ia64__
+#define SYS_gettid 1105
+#elif __i386__
+#define SYS_gettid 224
+#elif __amd64__
+#define SYS_gettid 186
+#elif __sparc__
+#define SYS_gettid 143
+#else
+#error define gettid for the arch
+#endif
+#endif
+#endif
+
+// Cpu architecture string
+#if defined(ZERO)
+static char cpu_arch[] = ZERO_LIBARCH;
+#elif defined(IA64)
+static char cpu_arch[] = "ia64";
+#elif defined(IA32)
+static char cpu_arch[] = "i386";
+#elif defined(AMD64)
+static char cpu_arch[] = "amd64";
+#elif defined(ARM)
+static char cpu_arch[] = "arm";
+#elif defined(PPC)
+static char cpu_arch[] = "ppc";
+#elif defined(SPARC)
+# ifdef _LP64
+static char cpu_arch[] = "sparcv9";
+# else
+static char cpu_arch[] = "sparc";
+# endif
+#else
+#error Add appropriate cpu_arch setting
+#endif
+
+
+#ifndef _ALLBSD_SOURCE
+// pid_t gettid()
+//
+// Returns the kernel thread id of the currently running thread. Kernel
+// thread id is used to access /proc.
+//
+// (Note that getpid() on BsdThreads returns kernel thread id too; but
+// on NPTL, it returns the same pid for all threads, as required by POSIX.)
+//
+pid_t os::Bsd::gettid() {
+ int rslt = syscall(SYS_gettid);
+ if (rslt == -1) {
+ // old kernel, no NPTL support
+ return getpid();
+ } else {
+ return (pid_t)rslt;
+ }
+}
+
+// Most versions of bsd have a bug where the number of processors are
+// determined by looking at the /proc file system. In a chroot environment,
+// the system call returns 1. This causes the VM to act as if it is
+// a single processor and elide locking (see is_MP() call).
+static bool unsafe_chroot_detected = false;
+static const char *unstable_chroot_error = "/proc file system not found.\n"
+ "Java may be unstable running multithreaded in a chroot "
+ "environment on Bsd when /proc filesystem is not mounted.";
+#endif
+
+#ifdef _ALLBSD_SOURCE
+void os::Bsd::initialize_system_info() {
+ int mib[2];
+ size_t len;
+ int cpu_val;
+ u_long mem_val;
+
+ /* get processors count via hw.ncpus sysctl */
+ mib[0] = CTL_HW;
+ mib[1] = HW_NCPU;
+ len = sizeof(cpu_val);
+ if (sysctl(mib, 2, &cpu_val, &len, NULL, 0) != -1 && cpu_val >= 1) {
+ set_processor_count(cpu_val);
+ }
+ else {
+ set_processor_count(1); // fallback
+ }
+
+ /* get physical memory via hw.usermem sysctl (hw.usermem is used
+ * instead of hw.physmem because we need size of allocatable memory
+ */
+ mib[0] = CTL_HW;
+ mib[1] = HW_USERMEM;
+ len = sizeof(mem_val);
+ if (sysctl(mib, 2, &mem_val, &len, NULL, 0) != -1)
+ _physical_memory = mem_val;
+ else
+ _physical_memory = 256*1024*1024; // fallback (XXXBSD?)
+
+#ifdef __OpenBSD__
+ {
+ // limit _physical_memory memory view on OpenBSD since
+ // datasize rlimit restricts us anyway.
+ struct rlimit limits;
+ getrlimit(RLIMIT_DATA, &limits);
+ _physical_memory = MIN2(_physical_memory, (julong)limits.rlim_cur);
+ }
+#endif
+}
+#else
+void os::Bsd::initialize_system_info() {
+ set_processor_count(sysconf(_SC_NPROCESSORS_CONF));
+ if (processor_count() == 1) {
+ pid_t pid = os::Bsd::gettid();
+ char fname[32];
+ jio_snprintf(fname, sizeof(fname), "/proc/%d", pid);
+ FILE *fp = fopen(fname, "r");
+ if (fp == NULL) {
+ unsafe_chroot_detected = true;
+ } else {
+ fclose(fp);
+ }
+ }
+ _physical_memory = (julong)sysconf(_SC_PHYS_PAGES) * (julong)sysconf(_SC_PAGESIZE);
+ assert(processor_count() > 0, "bsd error");
+}
+#endif
+
+void os::init_system_properties_values() {
+// char arch[12];
+// sysinfo(SI_ARCHITECTURE, arch, sizeof(arch));
+
+ // The next steps are taken in the product version:
+ //
+ // Obtain the JAVA_HOME value from the location of libjvm[_g].so.
+ // This library should be located at:
+ // <JAVA_HOME>/jre/lib/<arch>/{client|server}/libjvm[_g].so.
+ //
+ // If "/jre/lib/" appears at the right place in the path, then we
+ // assume libjvm[_g].so is installed in a JDK and we use this path.
+ //
+ // Otherwise exit with message: "Could not create the Java virtual machine."
+ //
+ // The following extra steps are taken in the debugging version:
+ //
+ // If "/jre/lib/" does NOT appear at the right place in the path
+ // instead of exit check for $JAVA_HOME environment variable.
+ //
+ // If it is defined and we are able to locate $JAVA_HOME/jre/lib/<arch>,
+ // then we append a fake suffix "hotspot/libjvm[_g].so" to this path so
+ // it looks like libjvm[_g].so is installed there
+ // <JAVA_HOME>/jre/lib/<arch>/hotspot/libjvm[_g].so.
+ //
+ // Otherwise exit.
+ //
+ // Important note: if the location of libjvm.so changes this
+ // code needs to be changed accordingly.
+
+ // The next few definitions allow the code to be verbatim:
+#define malloc(n) (char*)NEW_C_HEAP_ARRAY(char, (n))
+#define getenv(n) ::getenv(n)
+
+/*
+ * See ld(1):
+ * The linker uses the following search paths to locate required
+ * shared libraries:
+ * 1: ...
+ * ...
+ * 7: The default directories, normally /lib and /usr/lib.
+ */
+#ifndef DEFAULT_LIBPATH
+#define DEFAULT_LIBPATH "/lib:/usr/lib"
+#endif
+
+#define EXTENSIONS_DIR "/lib/ext"
+#define ENDORSED_DIR "/lib/endorsed"
+#define REG_DIR "/usr/java/packages"
+
+ {
+ /* sysclasspath, java_home, dll_dir */
+ {
+ char *home_path;
+ char *dll_path;
+ char *pslash;
+ char buf[MAXPATHLEN];
+ os::jvm_path(buf, sizeof(buf));
+
+ // Found the full path to libjvm.so.
+ // Now cut the path to <java_home>/jre if we can.
+ *(strrchr(buf, '/')) = '\0'; /* get rid of /libjvm.so */
+ pslash = strrchr(buf, '/');
+ if (pslash != NULL)
+ *pslash = '\0'; /* get rid of /{client|server|hotspot} */
+ dll_path = malloc(strlen(buf) + 1);
+ if (dll_path == NULL)
+ return;
+ strcpy(dll_path, buf);
+ Arguments::set_dll_dir(dll_path);
+
+ if (pslash != NULL) {
+ pslash = strrchr(buf, '/');
+ if (pslash != NULL) {
+ *pslash = '\0'; /* get rid of /<arch> */
+ pslash = strrchr(buf, '/');
+ if (pslash != NULL)
+ *pslash = '\0'; /* get rid of /lib */
+ }
+ }
+
+ home_path = malloc(strlen(buf) + 1);
+ if (home_path == NULL)
+ return;
+ strcpy(home_path, buf);
+ Arguments::set_java_home(home_path);
+
+ if (!set_boot_path('/', ':'))
+ return;
+ }
+
+ /*
+ * Where to look for native libraries
+ *
+ * Note: Due to a legacy implementation, most of the library path
+ * is set in the launcher. This was to accomodate linking restrictions
+ * on legacy Bsd implementations (which are no longer supported).
+ * Eventually, all the library path setting will be done here.
+ *
+ * However, to prevent the proliferation of improperly built native
+ * libraries, the new path component /usr/java/packages is added here.
+ * Eventually, all the library path setting will be done here.
+ */
+ {
+ char *ld_library_path;
+
+ /*
+ * Construct the invariant part of ld_library_path. Note that the
+ * space for the colon and the trailing null are provided by the
+ * nulls included by the sizeof operator (so actually we allocate
+ * a byte more than necessary).
+ */
+ ld_library_path = (char *) malloc(sizeof(REG_DIR) + sizeof("/lib/") +
+ strlen(cpu_arch) + sizeof(DEFAULT_LIBPATH));
+ sprintf(ld_library_path, REG_DIR "/lib/%s:" DEFAULT_LIBPATH, cpu_arch);
+
+ /*
+ * Get the user setting of LD_LIBRARY_PATH, and prepended it. It
+ * should always exist (until the legacy problem cited above is
+ * addressed).
+ */
+#ifdef __APPLE__
+ char *v = getenv("DYLD_LIBRARY_PATH");
+#else
+ char *v = getenv("LD_LIBRARY_PATH");
+#endif
+ if (v != NULL) {
+ char *t = ld_library_path;
+ /* That's +1 for the colon and +1 for the trailing '\0' */
+ ld_library_path = (char *) malloc(strlen(v) + 1 + strlen(t) + 1);
+ sprintf(ld_library_path, "%s:%s", v, t);
+ }
+ Arguments::set_library_path(ld_library_path);
+ }
+
+ /*
+ * Extensions directories.
+ *
+ * Note that the space for the colon and the trailing null are provided
+ * by the nulls included by the sizeof operator (so actually one byte more
+ * than necessary is allocated).
+ */
+ {
+ char *buf = malloc(strlen(Arguments::get_java_home()) +
+ sizeof(EXTENSIONS_DIR) + sizeof(REG_DIR) + sizeof(EXTENSIONS_DIR));
+ sprintf(buf, "%s" EXTENSIONS_DIR ":" REG_DIR EXTENSIONS_DIR,
+ Arguments::get_java_home());
+ Arguments::set_ext_dirs(buf);
+ }
+
+ /* Endorsed standards default directory. */
+ {
+ char * buf;
+ buf = malloc(strlen(Arguments::get_java_home()) + sizeof(ENDORSED_DIR));
+ sprintf(buf, "%s" ENDORSED_DIR, Arguments::get_java_home());
+ Arguments::set_endorsed_dirs(buf);
+ }
+ }
+
+#undef malloc
+#undef getenv
+#undef EXTENSIONS_DIR
+#undef ENDORSED_DIR
+
+ // Done
+ return;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// breakpoint support
+
+void os::breakpoint() {
+ BREAKPOINT;
+}
+
+extern "C" void breakpoint() {
+ // use debugger to set breakpoint here
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// signal support
+
+debug_only(static bool signal_sets_initialized = false);
+static sigset_t unblocked_sigs, vm_sigs, allowdebug_blocked_sigs;
+
+bool os::Bsd::is_sig_ignored(int sig) {
+ struct sigaction oact;
+ sigaction(sig, (struct sigaction*)NULL, &oact);
+ void* ohlr = oact.sa_sigaction ? CAST_FROM_FN_PTR(void*, oact.sa_sigaction)
+ : CAST_FROM_FN_PTR(void*, oact.sa_handler);
+ if (ohlr == CAST_FROM_FN_PTR(void*, SIG_IGN))
+ return true;
+ else
+ return false;
+}
+
+void os::Bsd::signal_sets_init() {
+ // Should also have an assertion stating we are still single-threaded.
+ assert(!signal_sets_initialized, "Already initialized");
+ // Fill in signals that are necessarily unblocked for all threads in
+ // the VM. Currently, we unblock the following signals:
+ // SHUTDOWN{1,2,3}_SIGNAL: for shutdown hooks support (unless over-ridden
+ // by -Xrs (=ReduceSignalUsage));
+ // BREAK_SIGNAL which is unblocked only by the VM thread and blocked by all
+ // other threads. The "ReduceSignalUsage" boolean tells us not to alter
+ // the dispositions or masks wrt these signals.
+ // Programs embedding the VM that want to use the above signals for their
+ // own purposes must, at this time, use the "-Xrs" option to prevent
+ // interference with shutdown hooks and BREAK_SIGNAL thread dumping.
+ // (See bug 4345157, and other related bugs).
+ // In reality, though, unblocking these signals is really a nop, since
+ // these signals are not blocked by default.
+ sigemptyset(&unblocked_sigs);
+ sigemptyset(&allowdebug_blocked_sigs);
+ sigaddset(&unblocked_sigs, SIGILL);
+ sigaddset(&unblocked_sigs, SIGSEGV);
+ sigaddset(&unblocked_sigs, SIGBUS);
+ sigaddset(&unblocked_sigs, SIGFPE);
+ sigaddset(&unblocked_sigs, SR_signum);
+
+ if (!ReduceSignalUsage) {
+ if (!os::Bsd::is_sig_ignored(SHUTDOWN1_SIGNAL)) {
+ sigaddset(&unblocked_sigs, SHUTDOWN1_SIGNAL);
+ sigaddset(&allowdebug_blocked_sigs, SHUTDOWN1_SIGNAL);
+ }
+ if (!os::Bsd::is_sig_ignored(SHUTDOWN2_SIGNAL)) {
+ sigaddset(&unblocked_sigs, SHUTDOWN2_SIGNAL);
+ sigaddset(&allowdebug_blocked_sigs, SHUTDOWN2_SIGNAL);
+ }
+ if (!os::Bsd::is_sig_ignored(SHUTDOWN3_SIGNAL)) {
+ sigaddset(&unblocked_sigs, SHUTDOWN3_SIGNAL);
+ sigaddset(&allowdebug_blocked_sigs, SHUTDOWN3_SIGNAL);
+ }
+ }
+ // Fill in signals that are blocked by all but the VM thread.
+ sigemptyset(&vm_sigs);
+ if (!ReduceSignalUsage)
+ sigaddset(&vm_sigs, BREAK_SIGNAL);
+ debug_only(signal_sets_initialized = true);
+
+}
+
+// These are signals that are unblocked while a thread is running Java.
+// (For some reason, they get blocked by default.)
+sigset_t* os::Bsd::unblocked_signals() {
+ assert(signal_sets_initialized, "Not initialized");
+ return &unblocked_sigs;
+}
+
+// These are the signals that are blocked while a (non-VM) thread is
+// running Java. Only the VM thread handles these signals.
+sigset_t* os::Bsd::vm_signals() {
+ assert(signal_sets_initialized, "Not initialized");
+ return &vm_sigs;
+}
+
+// These are signals that are blocked during cond_wait to allow debugger in
+sigset_t* os::Bsd::allowdebug_blocked_signals() {
+ assert(signal_sets_initialized, "Not initialized");
+ return &allowdebug_blocked_sigs;
+}
+
+void os::Bsd::hotspot_sigmask(Thread* thread) {
+
+ //Save caller's signal mask before setting VM signal mask
+ sigset_t caller_sigmask;
+ pthread_sigmask(SIG_BLOCK, NULL, &caller_sigmask);
+
+ OSThread* osthread = thread->osthread();
+ osthread->set_caller_sigmask(caller_sigmask);
+
+ pthread_sigmask(SIG_UNBLOCK, os::Bsd::unblocked_signals(), NULL);
+
+ if (!ReduceSignalUsage) {
+ if (thread->is_VM_thread()) {
+ // Only the VM thread handles BREAK_SIGNAL ...
+ pthread_sigmask(SIG_UNBLOCK, vm_signals(), NULL);
+ } else {
+ // ... all other threads block BREAK_SIGNAL
+ pthread_sigmask(SIG_BLOCK, vm_signals(), NULL);
+ }
+ }
+}
+
+#ifndef _ALLBSD_SOURCE
+//////////////////////////////////////////////////////////////////////////////
+// detecting pthread library
+
+void os::Bsd::libpthread_init() {
+ // Save glibc and pthread version strings. Note that _CS_GNU_LIBC_VERSION
+ // and _CS_GNU_LIBPTHREAD_VERSION are supported in glibc >= 2.3.2. Use a
+ // generic name for earlier versions.
+ // Define macros here so we can build HotSpot on old systems.
+# ifndef _CS_GNU_LIBC_VERSION
+# define _CS_GNU_LIBC_VERSION 2
+# endif
+# ifndef _CS_GNU_LIBPTHREAD_VERSION
+# define _CS_GNU_LIBPTHREAD_VERSION 3
+# endif
+
+ size_t n = confstr(_CS_GNU_LIBC_VERSION, NULL, 0);
+ if (n > 0) {
+ char *str = (char *)malloc(n);
+ confstr(_CS_GNU_LIBC_VERSION, str, n);
+ os::Bsd::set_glibc_version(str);
+ } else {
+ // _CS_GNU_LIBC_VERSION is not supported, try gnu_get_libc_version()
+ static char _gnu_libc_version[32];
+ jio_snprintf(_gnu_libc_version, sizeof(_gnu_libc_version),
+ "glibc %s %s", gnu_get_libc_version(), gnu_get_libc_release());
+ os::Bsd::set_glibc_version(_gnu_libc_version);
+ }
+
+ n = confstr(_CS_GNU_LIBPTHREAD_VERSION, NULL, 0);
+ if (n > 0) {
+ char *str = (char *)malloc(n);
+ confstr(_CS_GNU_LIBPTHREAD_VERSION, str, n);
+ // Vanilla RH-9 (glibc 2.3.2) has a bug that confstr() always tells
+ // us "NPTL-0.29" even we are running with BsdThreads. Check if this
+ // is the case. BsdThreads has a hard limit on max number of threads.
+ // So sysconf(_SC_THREAD_THREADS_MAX) will return a positive value.
+ // On the other hand, NPTL does not have such a limit, sysconf()
+ // will return -1 and errno is not changed. Check if it is really NPTL.
+ if (strcmp(os::Bsd::glibc_version(), "glibc 2.3.2") == 0 &&
+ strstr(str, "NPTL") &&
+ sysconf(_SC_THREAD_THREADS_MAX) > 0) {
+ free(str);
+ os::Bsd::set_libpthread_version("bsdthreads");
+ } else {
+ os::Bsd::set_libpthread_version(str);
+ }
+ } else {
+ // glibc before 2.3.2 only has BsdThreads.
+ os::Bsd::set_libpthread_version("bsdthreads");
+ }
+
+ if (strstr(libpthread_version(), "NPTL")) {
+ os::Bsd::set_is_NPTL();
+ } else {
+ os::Bsd::set_is_BsdThreads();
+ }
+
+ // BsdThreads have two flavors: floating-stack mode, which allows variable
+ // stack size; and fixed-stack mode. NPTL is always floating-stack.
+ if (os::Bsd::is_NPTL() || os::Bsd::supports_variable_stack_size()) {
+ os::Bsd::set_is_floating_stack();
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// thread stack
+
+// Force Bsd kernel to expand current thread stack. If "bottom" is close
+// to the stack guard, caller should block all signals.
+//
+// MAP_GROWSDOWN:
+// A special mmap() flag that is used to implement thread stacks. It tells
+// kernel that the memory region should extend downwards when needed. This
+// allows early versions of BsdThreads to only mmap the first few pages
+// when creating a new thread. Bsd kernel will automatically expand thread
+// stack as needed (on page faults).
+//
+// However, because the memory region of a MAP_GROWSDOWN stack can grow on
+// demand, if a page fault happens outside an already mapped MAP_GROWSDOWN
+// region, it's hard to tell if the fault is due to a legitimate stack
+// access or because of reading/writing non-exist memory (e.g. buffer
+// overrun). As a rule, if the fault happens below current stack pointer,
+// Bsd kernel does not expand stack, instead a SIGSEGV is sent to the
+// application (see Bsd kernel fault.c).
+//
+// This Bsd feature can cause SIGSEGV when VM bangs thread stack for
+// stack overflow detection.
+//
+// Newer version of BsdThreads (since glibc-2.2, or, RH-7.x) and NPTL do
+// not use this flag. However, the stack of initial thread is not created
+// by pthread, it is still MAP_GROWSDOWN. Also it's possible (though
+// unlikely) that user code can create a thread with MAP_GROWSDOWN stack
+// and then attach the thread to JVM.
+//
+// To get around the problem and allow stack banging on Bsd, we need to
+// manually expand thread stack after receiving the SIGSEGV.
+//
+// There are two ways to expand thread stack to address "bottom", we used
+// both of them in JVM before 1.5:
+// 1. adjust stack pointer first so that it is below "bottom", and then
+// touch "bottom"
+// 2. mmap() the page in question
+//
+// Now alternate signal stack is gone, it's harder to use 2. For instance,
+// if current sp is already near the lower end of page 101, and we need to
+// call mmap() to map page 100, it is possible that part of the mmap() frame
+// will be placed in page 100. When page 100 is mapped, it is zero-filled.
+// That will destroy the mmap() frame and cause VM to crash.
+//
+// The following code works by adjusting sp first, then accessing the "bottom"
+// page to force a page fault. Bsd kernel will then automatically expand the
+// stack mapping.
+//
+// _expand_stack_to() assumes its frame size is less than page size, which
+// should always be true if the function is not inlined.
+
+#if __GNUC__ < 3 // gcc 2.x does not support noinline attribute
+#define NOINLINE
+#else
+#define NOINLINE __attribute__ ((noinline))
+#endif
+
+static void _expand_stack_to(address bottom) NOINLINE;
+
+static void _expand_stack_to(address bottom) {
+ address sp;
+ size_t size;
+ volatile char *p;
+
+ // Adjust bottom to point to the largest address within the same page, it
+ // gives us a one-page buffer if alloca() allocates slightly more memory.
+ bottom = (address)align_size_down((uintptr_t)bottom, os::Bsd::page_size());
+ bottom += os::Bsd::page_size() - 1;
+
+ // sp might be slightly above current stack pointer; if that's the case, we
+ // will alloca() a little more space than necessary, which is OK. Don't use
+ // os::current_stack_pointer(), as its result can be slightly below current
+ // stack pointer, causing us to not alloca enough to reach "bottom".
+ sp = (address)&sp;
+
+ if (sp > bottom) {
+ size = sp - bottom;
+ p = (volatile char *)alloca(size);
+ assert(p != NULL && p <= (volatile char *)bottom, "alloca problem?");
+ p[0] = '\0';
+ }
+}
+
+bool os::Bsd::manually_expand_stack(JavaThread * t, address addr) {
+ assert(t!=NULL, "just checking");
+ assert(t->osthread()->expanding_stack(), "expand should be set");
+ assert(t->stack_base() != NULL, "stack_base was not initialized");
+
+ if (addr < t->stack_base() && addr >= t->stack_yellow_zone_base()) {
+ sigset_t mask_all, old_sigset;
+ sigfillset(&mask_all);
+ pthread_sigmask(SIG_SETMASK, &mask_all, &old_sigset);
+ _expand_stack_to(addr);
+ pthread_sigmask(SIG_SETMASK, &old_sigset, NULL);
+ return true;
+ }
+ return false;
+}
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+// create new thread
+
+static address highest_vm_reserved_address();
+
+// check if it's safe to start a new thread
+static bool _thread_safety_check(Thread* thread) {
+#ifdef _ALLBSD_SOURCE
+ return true;
+#else
+ if (os::Bsd::is_BsdThreads() && !os::Bsd::is_floating_stack()) {
+ // Fixed stack BsdThreads (SuSE Bsd/x86, and some versions of Redhat)
+ // Heap is mmap'ed at lower end of memory space. Thread stacks are
+ // allocated (MAP_FIXED) from high address space. Every thread stack
+ // occupies a fixed size slot (usually 2Mbytes, but user can change
+ // it to other values if they rebuild BsdThreads).
+ //
+ // Problem with MAP_FIXED is that mmap() can still succeed even part of
+ // the memory region has already been mmap'ed. That means if we have too
+ // many threads and/or very large heap, eventually thread stack will
+ // collide with heap.
+ //
+ // Here we try to prevent heap/stack collision by comparing current
+ // stack bottom with the highest address that has been mmap'ed by JVM
+ // plus a safety margin for memory maps created by native code.
+ //
+ // This feature can be disabled by setting ThreadSafetyMargin to 0
+ //
+ if (ThreadSafetyMargin > 0) {
+ address stack_bottom = os::current_stack_base() - os::current_stack_size();
+
+ // not safe if our stack extends below the safety margin
+ return stack_bottom - ThreadSafetyMargin >= highest_vm_reserved_address();
+ } else {
+ return true;
+ }
+ } else {
+ // Floating stack BsdThreads or NPTL:
+ // Unlike fixed stack BsdThreads, thread stacks are not MAP_FIXED. When
+ // there's not enough space left, pthread_create() will fail. If we come
+ // here, that means enough space has been reserved for stack.
+ return true;
+ }
+#endif
+}
+
+// Thread start routine for all newly created threads
+static void *java_start(Thread *thread) {
+ // Try to randomize the cache line index of hot stack frames.
+ // This helps when threads of the same stack traces evict each other's
+ // cache lines. The threads can be either from the same JVM instance, or
+ // from different JVM instances. The benefit is especially true for
+ // processors with hyperthreading technology.
+ static int counter = 0;
+ int pid = os::current_process_id();
+ alloca(((pid ^ counter++) & 7) * 128);
+
+ ThreadLocalStorage::set_thread(thread);
+
+ OSThread* osthread = thread->osthread();
+ Monitor* sync = osthread->startThread_lock();
+
+ // non floating stack BsdThreads needs extra check, see above
+ if (!_thread_safety_check(thread)) {
+ // notify parent thread
+ MutexLockerEx ml(sync, Mutex::_no_safepoint_check_flag);
+ osthread->set_state(ZOMBIE);
+ sync->notify_all();
+ return NULL;
+ }
+
+#ifdef _ALLBSD_SOURCE
+ // thread_id is pthread_id on BSD
+ osthread->set_thread_id(::pthread_self());
+#else
+ // thread_id is kernel thread id (similar to Solaris LWP id)
+ osthread->set_thread_id(os::Bsd::gettid());
+
+ if (UseNUMA) {
+ int lgrp_id = os::numa_get_group_id();
+ if (lgrp_id != -1) {
+ thread->set_lgrp_id(lgrp_id);
+ }
+ }
+#endif
+ // initialize signal mask for this thread
+ os::Bsd::hotspot_sigmask(thread);
+
+ // initialize floating point control register
+ os::Bsd::init_thread_fpu_state();
+
+ // handshaking with parent thread
+ {
+ MutexLockerEx ml(sync, Mutex::_no_safepoint_check_flag);
+
+ // notify parent thread
+ osthread->set_state(INITIALIZED);
+ sync->notify_all();
+
+ // wait until os::start_thread()
+ while (osthread->get_state() == INITIALIZED) {
+ sync->wait(Mutex::_no_safepoint_check_flag);
+ }
+ }
+
+ // call one more level start routine
+ thread->run();
+
+ return 0;
+}
+
+bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) {
+ assert(thread->osthread() == NULL, "caller responsible");
+
+ // Allocate the OSThread object
+ OSThread* osthread = new OSThread(NULL, NULL);
+ if (osthread == NULL) {
+ return false;
+ }
+
+ // set the correct thread state
+ osthread->set_thread_type(thr_type);
+
+ // Initial state is ALLOCATED but not INITIALIZED
+ osthread->set_state(ALLOCATED);
+
+ thread->set_osthread(osthread);
+
+ // init thread attributes
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
+ // stack size
+ if (os::Bsd::supports_variable_stack_size()) {
+ // calculate stack size if it's not specified by caller
+ if (stack_size == 0) {
+ stack_size = os::Bsd::default_stack_size(thr_type);
+
+ switch (thr_type) {
+ case os::java_thread:
+ // Java threads use ThreadStackSize which default value can be
+ // changed with the flag -Xss
+ assert (JavaThread::stack_size_at_create() > 0, "this should be set");
+ stack_size = JavaThread::stack_size_at_create();
+ break;
+ case os::compiler_thread:
+ if (CompilerThreadStackSize > 0) {
+ stack_size = (size_t)(CompilerThreadStackSize * K);
+ break;
+ } // else fall through:
+ // use VMThreadStackSize if CompilerThreadStackSize is not defined
+ case os::vm_thread:
+ case os::pgc_thread:
+ case os::cgc_thread:
+ case os::watcher_thread:
+ if (VMThreadStackSize > 0) stack_size = (size_t)(VMThreadStackSize * K);
+ break;
+ }
+ }
+
+ stack_size = MAX2(stack_size, os::Bsd::min_stack_allowed);
+ pthread_attr_setstacksize(&attr, stack_size);
+ } else {
+ // let pthread_create() pick the default value.
+ }
+
+#ifndef _ALLBSD_SOURCE
+ // glibc guard page
+ pthread_attr_setguardsize(&attr, os::Bsd::default_guard_size(thr_type));
+#endif
+
+ ThreadState state;
+
+ {
+
+#ifndef _ALLBSD_SOURCE
+ // Serialize thread creation if we are running with fixed stack BsdThreads
+ bool lock = os::Bsd::is_BsdThreads() && !os::Bsd::is_floating_stack();
+ if (lock) {
+ os::Bsd::createThread_lock()->lock_without_safepoint_check();
+ }
+#endif
+
+ pthread_t tid;
+ int ret = pthread_create(&tid, &attr, (void* (*)(void*)) java_start, thread);
+
+ pthread_attr_destroy(&attr);
+
+ if (ret != 0) {
+ if (PrintMiscellaneous && (Verbose || WizardMode)) {
+ perror("pthread_create()");
+ }
+ // Need to clean up stuff we've allocated so far
+ thread->set_osthread(NULL);
+ delete osthread;
+#ifndef _ALLBSD_SOURCE
+ if (lock) os::Bsd::createThread_lock()->unlock();
+#endif
+ return false;
+ }
+
+ // Store pthread info into the OSThread
+ osthread->set_pthread_id(tid);
+
+ // Wait until child thread is either initialized or aborted
+ {
+ Monitor* sync_with_child = osthread->startThread_lock();
+ MutexLockerEx ml(sync_with_child, Mutex::_no_safepoint_check_flag);
+ while ((state = osthread->get_state()) == ALLOCATED) {
+ sync_with_child->wait(Mutex::_no_safepoint_check_flag);
+ }
+ }
+
+#ifndef _ALLBSD_SOURCE
+ if (lock) {
+ os::Bsd::createThread_lock()->unlock();
+ }
+#endif
+ }
+
+ // Aborted due to thread limit being reached
+ if (state == ZOMBIE) {
+ thread->set_osthread(NULL);
+ delete osthread;
+ return false;
+ }
+
+ // The thread is returned suspended (in state INITIALIZED),
+ // and is started higher up in the call chain
+ assert(state == INITIALIZED, "race condition");
+ return true;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// attach existing thread
+
+// bootstrap the main thread
+bool os::create_main_thread(JavaThread* thread) {
+ assert(os::Bsd::_main_thread == pthread_self(), "should be called inside main thread");
+ return create_attached_thread(thread);
+}
+
+bool os::create_attached_thread(JavaThread* thread) {
+#ifdef ASSERT
+ thread->verify_not_published();
+#endif
+
+ // Allocate the OSThread object
+ OSThread* osthread = new OSThread(NULL, NULL);
+
+ if (osthread == NULL) {
+ return false;
+ }
+
+ // Store pthread info into the OSThread
+#ifdef _ALLBSD_SOURCE
+ osthread->set_thread_id(::pthread_self());
+#else
+ osthread->set_thread_id(os::Bsd::gettid());
+#endif
+ osthread->set_pthread_id(::pthread_self());
+
+ // initialize floating point control register
+ os::Bsd::init_thread_fpu_state();
+
+ // Initial thread state is RUNNABLE
+ osthread->set_state(RUNNABLE);
+
+ thread->set_osthread(osthread);
+
+#ifndef _ALLBSD_SOURCE
+ if (UseNUMA) {
+ int lgrp_id = os::numa_get_group_id();
+ if (lgrp_id != -1) {
+ thread->set_lgrp_id(lgrp_id);
+ }
+ }
+
+ if (os::Bsd::is_initial_thread()) {
+ // If current thread is initial thread, its stack is mapped on demand,
+ // see notes about MAP_GROWSDOWN. Here we try to force kernel to map
+ // the entire stack region to avoid SEGV in stack banging.
+ // It is also useful to get around the heap-stack-gap problem on SuSE
+ // kernel (see 4821821 for details). We first expand stack to the top
+ // of yellow zone, then enable stack yellow zone (order is significant,
+ // enabling yellow zone first will crash JVM on SuSE Bsd), so there
+ // is no gap between the last two virtual memory regions.
+
+ JavaThread *jt = (JavaThread *)thread;
+ address addr = jt->stack_yellow_zone_base();
+ assert(addr != NULL, "initialization problem?");
+ assert(jt->stack_available(addr) > 0, "stack guard should not be enabled");
+
+ osthread->set_expanding_stack();
+ os::Bsd::manually_expand_stack(jt, addr);
+ osthread->clear_expanding_stack();
+ }
+#endif
+
+ // initialize signal mask for this thread
+ // and save the caller's signal mask
+ os::Bsd::hotspot_sigmask(thread);
+
+ return true;
+}
+
+void os::pd_start_thread(Thread* thread) {
+ OSThread * osthread = thread->osthread();
+ assert(osthread->get_state() != INITIALIZED, "just checking");
+ Monitor* sync_with_child = osthread->startThread_lock();
+ MutexLockerEx ml(sync_with_child, Mutex::_no_safepoint_check_flag);
+ sync_with_child->notify();
+}
+
+// Free Bsd resources related to the OSThread
+void os::free_thread(OSThread* osthread) {
+ assert(osthread != NULL, "osthread not set");
+
+ if (Thread::current()->osthread() == osthread) {
+ // Restore caller's signal mask
+ sigset_t sigmask = osthread->caller_sigmask();
+ pthread_sigmask(SIG_SETMASK, &sigmask, NULL);
+ }
+
+ delete osthread;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// thread local storage
+
+int os::allocate_thread_local_storage() {
+ pthread_key_t key;
+ int rslt = pthread_key_create(&key, NULL);
+ assert(rslt == 0, "cannot allocate thread local storage");
+ return (int)key;
+}
+
+// Note: This is currently not used by VM, as we don't destroy TLS key
+// on VM exit.
+void os::free_thread_local_storage(int index) {
+ int rslt = pthread_key_delete((pthread_key_t)index);
+ assert(rslt == 0, "invalid index");
+}
+
+void os::thread_local_storage_at_put(int index, void* value) {
+ int rslt = pthread_setspecific((pthread_key_t)index, value);
+ assert(rslt == 0, "pthread_setspecific failed");
+}
+
+extern "C" Thread* get_thread() {
+ return ThreadLocalStorage::thread();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// initial thread
+
+#ifndef _ALLBSD_SOURCE
+// Check if current thread is the initial thread, similar to Solaris thr_main.
+bool os::Bsd::is_initial_thread(void) {
+ char dummy;
+ // If called before init complete, thread stack bottom will be null.
+ // Can be called if fatal error occurs before initialization.
+ if (initial_thread_stack_bottom() == NULL) return false;
+ assert(initial_thread_stack_bottom() != NULL &&
+ initial_thread_stack_size() != 0,
+ "os::init did not locate initial thread's stack region");
+ if ((address)&dummy >= initial_thread_stack_bottom() &&
+ (address)&dummy < initial_thread_stack_bottom() + initial_thread_stack_size())
+ return true;
+ else return false;
+}
+
+// Find the virtual memory area that contains addr
+static bool find_vma(address addr, address* vma_low, address* vma_high) {
+ FILE *fp = fopen("/proc/self/maps", "r");
+ if (fp) {
+ address low, high;
+ while (!feof(fp)) {
+ if (fscanf(fp, "%p-%p", &low, &high) == 2) {
+ if (low <= addr && addr < high) {
+ if (vma_low) *vma_low = low;
+ if (vma_high) *vma_high = high;
+ fclose (fp);
+ return true;
+ }
+ }
+ for (;;) {
+ int ch = fgetc(fp);
+ if (ch == EOF || ch == (int)'\n') break;
+ }
+ }
+ fclose(fp);
+ }
+ return false;
+}
+
+// Locate initial thread stack. This special handling of initial thread stack
+// is needed because pthread_getattr_np() on most (all?) Bsd distros returns
+// bogus value for initial thread.
+void os::Bsd::capture_initial_stack(size_t max_size) {
+ // stack size is the easy part, get it from RLIMIT_STACK
+ size_t stack_size;
+ struct rlimit rlim;
+ getrlimit(RLIMIT_STACK, &rlim);
+ stack_size = rlim.rlim_cur;
+
+ // 6308388: a bug in ld.so will relocate its own .data section to the
+ // lower end of primordial stack; reduce ulimit -s value a little bit
+ // so we won't install guard page on ld.so's data section.
+ stack_size -= 2 * page_size();
+
+ // 4441425: avoid crash with "unlimited" stack size on SuSE 7.1 or Redhat
+ // 7.1, in both cases we will get 2G in return value.
+ // 4466587: glibc 2.2.x compiled w/o "--enable-kernel=2.4.0" (RH 7.0,
+ // SuSE 7.2, Debian) can not handle alternate signal stack correctly
+ // for initial thread if its stack size exceeds 6M. Cap it at 2M,
+ // in case other parts in glibc still assumes 2M max stack size.
+ // FIXME: alt signal stack is gone, maybe we can relax this constraint?
+#ifndef IA64
+ if (stack_size > 2 * K * K) stack_size = 2 * K * K;
+#else
+ // Problem still exists RH7.2 (IA64 anyway) but 2MB is a little small
+ if (stack_size > 4 * K * K) stack_size = 4 * K * K;
+#endif
+
+ // Try to figure out where the stack base (top) is. This is harder.
+ //
+ // When an application is started, glibc saves the initial stack pointer in
+ // a global variable "__libc_stack_end", which is then used by system
+ // libraries. __libc_stack_end should be pretty close to stack top. The
+ // variable is available since the very early days. However, because it is
+ // a private interface, it could disappear in the future.
+ //
+ // Bsd kernel saves start_stack information in /proc/<pid>/stat. Similar
+ // to __libc_stack_end, it is very close to stack top, but isn't the real
+ // stack top. Note that /proc may not exist if VM is running as a chroot
+ // program, so reading /proc/<pid>/stat could fail. Also the contents of
+ // /proc/<pid>/stat could change in the future (though unlikely).
+ //
+ // We try __libc_stack_end first. If that doesn't work, look for
+ // /proc/<pid>/stat. If neither of them works, we use current stack pointer
+ // as a hint, which should work well in most cases.
+
+ uintptr_t stack_start;
+
+ // try __libc_stack_end first
+ uintptr_t *p = (uintptr_t *)dlsym(RTLD_DEFAULT, "__libc_stack_end");
+ if (p && *p) {
+ stack_start = *p;
+ } else {
+ // see if we can get the start_stack field from /proc/self/stat
+ FILE *fp;
+ int pid;
+ char state;
+ int ppid;
+ int pgrp;
+ int session;
+ int nr;
+ int tpgrp;
+ unsigned long flags;
+ unsigned long minflt;
+ unsigned long cminflt;
+ unsigned long majflt;
+ unsigned long cmajflt;
+ unsigned long utime;
+ unsigned long stime;
+ long cutime;
+ long cstime;
+ long prio;
+ long nice;
+ long junk;
+ long it_real;
+ uintptr_t start;
+ uintptr_t vsize;
+ intptr_t rss;
+ uintptr_t rsslim;
+ uintptr_t scodes;
+ uintptr_t ecode;
+ int i;
+
+ // Figure what the primordial thread stack base is. Code is inspired
+ // by email from Hans Boehm. /proc/self/stat begins with current pid,
+ // followed by command name surrounded by parentheses, state, etc.
+ char stat[2048];
+ int statlen;
+
+ fp = fopen("/proc/self/stat", "r");
+ if (fp) {
+ statlen = fread(stat, 1, 2047, fp);
+ stat[statlen] = '\0';
+ fclose(fp);
+
+ // Skip pid and the command string. Note that we could be dealing with
+ // weird command names, e.g. user could decide to rename java launcher
+ // to "java 1.4.2 :)", then the stat file would look like
+ // 1234 (java 1.4.2 :)) R ... ...
+ // We don't really need to know the command string, just find the last
+ // occurrence of ")" and then start parsing from there. See bug 4726580.
+ char * s = strrchr(stat, ')');
+
+ i = 0;
+ if (s) {
+ // Skip blank chars
+ do s++; while (isspace(*s));
+
+#define _UFM UINTX_FORMAT
+#define _DFM INTX_FORMAT
+
+ /* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 */
+ /* 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 */
+ i = sscanf(s, "%c %d %d %d %d %d %lu %lu %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld " _UFM _UFM _DFM _UFM _UFM _UFM _UFM,
+ &state, /* 3 %c */
+ &ppid, /* 4 %d */
+ &pgrp, /* 5 %d */
+ &session, /* 6 %d */
+ &nr, /* 7 %d */
+ &tpgrp, /* 8 %d */
+ &flags, /* 9 %lu */
+ &minflt, /* 10 %lu */
+ &cminflt, /* 11 %lu */
+ &majflt, /* 12 %lu */
+ &cmajflt, /* 13 %lu */
+ &utime, /* 14 %lu */
+ &stime, /* 15 %lu */
+ &cutime, /* 16 %ld */
+ &cstime, /* 17 %ld */
+ &prio, /* 18 %ld */
+ &nice, /* 19 %ld */
+ &junk, /* 20 %ld */
+ &it_real, /* 21 %ld */
+ &start, /* 22 UINTX_FORMAT */
+ &vsize, /* 23 UINTX_FORMAT */
+ &rss, /* 24 INTX_FORMAT */
+ &rsslim, /* 25 UINTX_FORMAT */
+ &scodes, /* 26 UINTX_FORMAT */
+ &ecode, /* 27 UINTX_FORMAT */
+ &stack_start); /* 28 UINTX_FORMAT */
+ }
+
+#undef _UFM
+#undef _DFM
+
+ if (i != 28 - 2) {
+ assert(false, "Bad conversion from /proc/self/stat");
+ // product mode - assume we are the initial thread, good luck in the
+ // embedded case.
+ warning("Can't detect initial thread stack location - bad conversion");
+ stack_start = (uintptr_t) &rlim;
+ }
+ } else {
+ // For some reason we can't open /proc/self/stat (for example, running on
+ // FreeBSD with a Bsd emulator, or inside chroot), this should work for
+ // most cases, so don't abort:
+ warning("Can't detect initial thread stack location - no /proc/self/stat");
+ stack_start = (uintptr_t) &rlim;
+ }
+ }
+
+ // Now we have a pointer (stack_start) very close to the stack top, the
+ // next thing to do is to figure out the exact location of stack top. We
+ // can find out the virtual memory area that contains stack_start by
+ // reading /proc/self/maps, it should be the last vma in /proc/self/maps,
+ // and its upper limit is the real stack top. (again, this would fail if
+ // running inside chroot, because /proc may not exist.)
+
+ uintptr_t stack_top;
+ address low, high;
+ if (find_vma((address)stack_start, &low, &high)) {
+ // success, "high" is the true stack top. (ignore "low", because initial
+ // thread stack grows on demand, its real bottom is high - RLIMIT_STACK.)
+ stack_top = (uintptr_t)high;
+ } else {
+ // failed, likely because /proc/self/maps does not exist
+ warning("Can't detect initial thread stack location - find_vma failed");
+ // best effort: stack_start is normally within a few pages below the real
+ // stack top, use it as stack top, and reduce stack size so we won't put
+ // guard page outside stack.
+ stack_top = stack_start;
+ stack_size -= 16 * page_size();
+ }
+
+ // stack_top could be partially down the page so align it
+ stack_top = align_size_up(stack_top, page_size());
+
+ if (max_size && stack_size > max_size) {
+ _initial_thread_stack_size = max_size;
+ } else {
+ _initial_thread_stack_size = stack_size;
+ }
+
+ _initial_thread_stack_size = align_size_down(_initial_thread_stack_size, page_size());
+ _initial_thread_stack_bottom = (address)stack_top - _initial_thread_stack_size;
+}
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// time support
+
+// Time since start-up in seconds to a fine granularity.
+// Used by VMSelfDestructTimer and the MemProfiler.
+double os::elapsedTime() {
+
+ return (double)(os::elapsed_counter()) * 0.000001;
+}
+
+jlong os::elapsed_counter() {
+ timeval time;
+ int status = gettimeofday(&time, NULL);
+ return jlong(time.tv_sec) * 1000 * 1000 + jlong(time.tv_usec) - initial_time_count;
+}
+
+jlong os::elapsed_frequency() {
+ return (1000 * 1000);
+}
+
+// XXX: For now, code this as if BSD does not support vtime.
+bool os::supports_vtime() { return false; }
+bool os::enable_vtime() { return false; }
+bool os::vtime_enabled() { return false; }
+double os::elapsedVTime() {
+ // better than nothing, but not much
+ return elapsedTime();
+}
+
+jlong os::javaTimeMillis() {
+ timeval time;
+ int status = gettimeofday(&time, NULL);
+ assert(status != -1, "bsd error");
+ return jlong(time.tv_sec) * 1000 + jlong(time.tv_usec / 1000);
+}
+
+#ifndef CLOCK_MONOTONIC
+#define CLOCK_MONOTONIC (1)
+#endif
+
+#ifdef __APPLE__
+void os::Bsd::clock_init() {
+ // XXXDARWIN: Investigate replacement monotonic clock
+}
+#elif defined(_ALLBSD_SOURCE)
+void os::Bsd::clock_init() {
+ struct timespec res;
+ struct timespec tp;
+ if (::clock_getres(CLOCK_MONOTONIC, &res) == 0 &&
+ ::clock_gettime(CLOCK_MONOTONIC, &tp) == 0) {
+ // yes, monotonic clock is supported
+ _clock_gettime = ::clock_gettime;
+ }
+}
+#else
+void os::Bsd::clock_init() {
+ // we do dlopen's in this particular order due to bug in bsd
+ // dynamical loader (see 6348968) leading to crash on exit
+ void* handle = dlopen("librt.so.1", RTLD_LAZY);
+ if (handle == NULL) {
+ handle = dlopen("librt.so", RTLD_LAZY);
+ }
+
+ if (handle) {
+ int (*clock_getres_func)(clockid_t, struct timespec*) =
+ (int(*)(clockid_t, struct timespec*))dlsym(handle, "clock_getres");
+ int (*clock_gettime_func)(clockid_t, struct timespec*) =
+ (int(*)(clockid_t, struct timespec*))dlsym(handle, "clock_gettime");
+ if (clock_getres_func && clock_gettime_func) {
+ // See if monotonic clock is supported by the kernel. Note that some
+ // early implementations simply return kernel jiffies (updated every
+ // 1/100 or 1/1000 second). It would be bad to use such a low res clock
+ // for nano time (though the monotonic property is still nice to have).
+ // It's fixed in newer kernels, however clock_getres() still returns
+ // 1/HZ. We check if clock_getres() works, but will ignore its reported
+ // resolution for now. Hopefully as people move to new kernels, this
+ // won't be a problem.
+ struct timespec res;
+ struct timespec tp;
+ if (clock_getres_func (CLOCK_MONOTONIC, &res) == 0 &&
+ clock_gettime_func(CLOCK_MONOTONIC, &tp) == 0) {
+ // yes, monotonic clock is supported
+ _clock_gettime = clock_gettime_func;
+ } else {
+ // close librt if there is no monotonic clock
+ dlclose(handle);
+ }
+ }
+ }
+}
+#endif
+
+#ifndef _ALLBSD_SOURCE
+#ifndef SYS_clock_getres
+
+#if defined(IA32) || defined(AMD64)
+#define SYS_clock_getres IA32_ONLY(266) AMD64_ONLY(229)
+#define sys_clock_getres(x,y) ::syscall(SYS_clock_getres, x, y)
+#else
+#warning "SYS_clock_getres not defined for this platform, disabling fast_thread_cpu_time"
+#define sys_clock_getres(x,y) -1
+#endif
+
+#else
+#define sys_clock_getres(x,y) ::syscall(SYS_clock_getres, x, y)
+#endif
+
+void os::Bsd::fast_thread_clock_init() {
+ if (!UseBsdPosixThreadCPUClocks) {
+ return;
+ }
+ clockid_t clockid;
+ struct timespec tp;
+ int (*pthread_getcpuclockid_func)(pthread_t, clockid_t *) =
+ (int(*)(pthread_t, clockid_t *)) dlsym(RTLD_DEFAULT, "pthread_getcpuclockid");
+
+ // Switch to using fast clocks for thread cpu time if
+ // the sys_clock_getres() returns 0 error code.
+ // Note, that some kernels may support the current thread
+ // clock (CLOCK_THREAD_CPUTIME_ID) but not the clocks
+ // returned by the pthread_getcpuclockid().
+ // If the fast Posix clocks are supported then the sys_clock_getres()
+ // must return at least tp.tv_sec == 0 which means a resolution
+ // better than 1 sec. This is extra check for reliability.
+
+ if(pthread_getcpuclockid_func &&
+ pthread_getcpuclockid_func(_main_thread, &clockid) == 0 &&
+ sys_clock_getres(clockid, &tp) == 0 && tp.tv_sec == 0) {
+
+ _supports_fast_thread_cpu_time = true;
+ _pthread_getcpuclockid = pthread_getcpuclockid_func;
+ }
+}
+#endif
+
+jlong os::javaTimeNanos() {
+ if (Bsd::supports_monotonic_clock()) {
+ struct timespec tp;
+ int status = Bsd::clock_gettime(CLOCK_MONOTONIC, &tp);
+ assert(status == 0, "gettime error");
+ jlong result = jlong(tp.tv_sec) * (1000 * 1000 * 1000) + jlong(tp.tv_nsec);
+ return result;
+ } else {
+ timeval time;
+ int status = gettimeofday(&time, NULL);
+ assert(status != -1, "bsd error");
+ jlong usecs = jlong(time.tv_sec) * (1000 * 1000) + jlong(time.tv_usec);
+ return 1000 * usecs;
+ }
+}
+
+void os::javaTimeNanos_info(jvmtiTimerInfo *info_ptr) {
+ if (Bsd::supports_monotonic_clock()) {
+ info_ptr->max_value = ALL_64_BITS;
+
+ // CLOCK_MONOTONIC - amount of time since some arbitrary point in the past
+ info_ptr->may_skip_backward = false; // not subject to resetting or drifting
+ info_ptr->may_skip_forward = false; // not subject to resetting or drifting
+ } else {
+ // gettimeofday - based on time in seconds since the Epoch thus does not wrap
+ info_ptr->max_value = ALL_64_BITS;
+
+ // gettimeofday is a real time clock so it skips
+ info_ptr->may_skip_backward = true;
+ info_ptr->may_skip_forward = true;
+ }
+
+ info_ptr->kind = JVMTI_TIMER_ELAPSED; // elapsed not CPU time
+}
+
+// Return the real, user, and system times in seconds from an
+// arbitrary fixed point in the past.
+bool os::getTimesSecs(double* process_real_time,
+ double* process_user_time,
+ double* process_system_time) {
+ struct tms ticks;
+ clock_t real_ticks = times(&ticks);
+
+ if (real_ticks == (clock_t) (-1)) {
+ return false;
+ } else {
+ double ticks_per_second = (double) clock_tics_per_sec;
+ *process_user_time = ((double) ticks.tms_utime) / ticks_per_second;
+ *process_system_time = ((double) ticks.tms_stime) / ticks_per_second;
+ *process_real_time = ((double) real_ticks) / ticks_per_second;
+
+ return true;
+ }
+}
+
+
+char * os::local_time_string(char *buf, size_t buflen) {
+ struct tm t;
+ time_t long_time;
+ time(&long_time);
+ localtime_r(&long_time, &t);
+ jio_snprintf(buf, buflen, "%d-%02d-%02d %02d:%02d:%02d",
+ t.tm_year + 1900, t.tm_mon + 1, t.tm_mday,
+ t.tm_hour, t.tm_min, t.tm_sec);
+ return buf;
+}
+
+struct tm* os::localtime_pd(const time_t* clock, struct tm* res) {
+ return localtime_r(clock, res);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// runtime exit support
+
+// Note: os::shutdown() might be called very early during initialization, or
+// called from signal handler. Before adding something to os::shutdown(), make
+// sure it is async-safe and can handle partially initialized VM.
+void os::shutdown() {
+
+ // allow PerfMemory to attempt cleanup of any persistent resources
+ perfMemory_exit();
+
+ // needs to remove object in file system
+ AttachListener::abort();
+
+ // flush buffered output, finish log files
+ ostream_abort();
+
+ // Check for abort hook
+ abort_hook_t abort_hook = Arguments::abort_hook();
+ if (abort_hook != NULL) {
+ abort_hook();
+ }
+
+}
+
+// Note: os::abort() might be called very early during initialization, or
+// called from signal handler. Before adding something to os::abort(), make
+// sure it is async-safe and can handle partially initialized VM.
+void os::abort(bool dump_core) {
+ os::shutdown();
+ if (dump_core) {
+#ifndef PRODUCT
+ fdStream out(defaultStream::output_fd());
+ out.print_raw("Current thread is ");
+ char buf[16];
+ jio_snprintf(buf, sizeof(buf), UINTX_FORMAT, os::current_thread_id());
+ out.print_raw_cr(buf);
+ out.print_raw_cr("Dumping core ...");
+#endif
+ ::abort(); // dump core
+ }
+
+ ::exit(1);
+}
+
+// Die immediately, no exit hook, no abort hook, no cleanup.
+void os::die() {
+ // _exit() on BsdThreads only kills current thread
+ ::abort();
+}
+
+// unused on bsd for now.
+void os::set_error_file(const char *logfile) {}
+
+
+// This method is a copy of JDK's sysGetLastErrorString
+// from src/solaris/hpi/src/system_md.c
+
+size_t os::lasterror(char *buf, size_t len) {
+
+ if (errno == 0) return 0;
+
+ const char *s = ::strerror(errno);
+ size_t n = ::strlen(s);
+ if (n >= len) {
+ n = len - 1;
+ }
+ ::strncpy(buf, s, n);
+ buf[n] = '\0';
+ return n;
+}
+
+intx os::current_thread_id() { return (intx)pthread_self(); }
+int os::current_process_id() {
+
+ // Under the old bsd thread library, bsd gives each thread
+ // its own process id. Because of this each thread will return
+ // a different pid if this method were to return the result
+ // of getpid(2). Bsd provides no api that returns the pid
+ // of the launcher thread for the vm. This implementation
+ // returns a unique pid, the pid of the launcher thread
+ // that starts the vm 'process'.
+
+ // Under the NPTL, getpid() returns the same pid as the
+ // launcher thread rather than a unique pid per thread.
+ // Use gettid() if you want the old pre NPTL behaviour.
+
+ // if you are looking for the result of a call to getpid() that
+ // returns a unique pid for the calling thread, then look at the
+ // OSThread::thread_id() method in osThread_bsd.hpp file
+
+ return (int)(_initial_pid ? _initial_pid : getpid());
+}
+
+// DLL functions
+
+#define JNI_LIB_PREFIX "lib"
+#ifdef __APPLE__
+#define JNI_LIB_SUFFIX ".dylib"
+#else
+#define JNI_LIB_SUFFIX ".so"
+#endif
+
+const char* os::dll_file_extension() { return JNI_LIB_SUFFIX; }
+
+// This must be hard coded because it's the system's temporary
+// directory not the java application's temp directory, ala java.io.tmpdir.
+const char* os::get_temp_directory() { return "/tmp"; }
+
+static bool file_exists(const char* filename) {
+ struct stat statbuf;
+ if (filename == NULL || strlen(filename) == 0) {
+ return false;
+ }
+ return os::stat(filename, &statbuf) == 0;
+}
+
+void os::dll_build_name(char* buffer, size_t buflen,
+ const char* pname, const char* fname) {
+ // Copied from libhpi
+ const size_t pnamelen = pname ? strlen(pname) : 0;
+
+ // Quietly truncate on buffer overflow. Should be an error.
+ if (pnamelen + strlen(fname) + strlen(JNI_LIB_PREFIX) + strlen(JNI_LIB_SUFFIX) + 2 > buflen) {
+ *buffer = '\0';
+ return;
+ }
+
+ if (pnamelen == 0) {
+ snprintf(buffer, buflen, JNI_LIB_PREFIX "%s" JNI_LIB_SUFFIX, fname);
+ } else if (strchr(pname, *os::path_separator()) != NULL) {
+ int n;
+ char** pelements = split_path(pname, &n);
+ for (int i = 0 ; i < n ; i++) {
+ // Really shouldn't be NULL, but check can't hurt
+ if (pelements[i] == NULL || strlen(pelements[i]) == 0) {
+ continue; // skip the empty path values
+ }
+ snprintf(buffer, buflen, "%s/" JNI_LIB_PREFIX "%s" JNI_LIB_SUFFIX,
+ pelements[i], fname);
+ if (file_exists(buffer)) {
+ break;
+ }
+ }
+ // release the storage
+ for (int i = 0 ; i < n ; i++) {
+ if (pelements[i] != NULL) {
+ FREE_C_HEAP_ARRAY(char, pelements[i]);
+ }
+ }
+ if (pelements != NULL) {
+ FREE_C_HEAP_ARRAY(char*, pelements);
+ }
+ } else {
+ snprintf(buffer, buflen, "%s/" JNI_LIB_PREFIX "%s" JNI_LIB_SUFFIX, pname, fname);
+ }
+}
+
+const char* os::get_current_directory(char *buf, int buflen) {
+ return getcwd(buf, buflen);
+}
+
+// check if addr is inside libjvm[_g].so
+bool os::address_is_in_vm(address addr) {
+ static address libjvm_base_addr;
+ Dl_info dlinfo;
+
+ if (libjvm_base_addr == NULL) {
+ dladdr(CAST_FROM_FN_PTR(void *, os::address_is_in_vm), &dlinfo);
+ libjvm_base_addr = (address)dlinfo.dli_fbase;
+ assert(libjvm_base_addr !=NULL, "Cannot obtain base address for libjvm");
+ }
+
+ if (dladdr((void *)addr, &dlinfo)) {
+ if (libjvm_base_addr == (address)dlinfo.dli_fbase) return true;
+ }
+
+ return false;
+}
+
+bool os::dll_address_to_function_name(address addr, char *buf,
+ int buflen, int *offset) {
+ Dl_info dlinfo;
+
+ if (dladdr((void*)addr, &dlinfo) && dlinfo.dli_sname != NULL) {
+ if (buf != NULL) {
+ if(!Decoder::demangle(dlinfo.dli_sname, buf, buflen)) {
+ jio_snprintf(buf, buflen, "%s", dlinfo.dli_sname);
+ }
+ }
+ if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr;
+ return true;
+ } else if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != 0) {
+ if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
+ dlinfo.dli_fname, buf, buflen, offset) == Decoder::no_error) {
+ return true;
+ }
+ }
+
+ if (buf != NULL) buf[0] = '\0';
+ if (offset != NULL) *offset = -1;
+ return false;
+}
+
+#ifdef _ALLBSD_SOURCE
+// ported from solaris version
+bool os::dll_address_to_library_name(address addr, char* buf,
+ int buflen, int* offset) {
+ Dl_info dlinfo;
+
+ if (dladdr((void*)addr, &dlinfo)){
+ if (buf) jio_snprintf(buf, buflen, "%s", dlinfo.dli_fname);
+ if (offset) *offset = addr - (address)dlinfo.dli_fbase;
+ return true;
+ } else {
+ if (buf) buf[0] = '\0';
+ if (offset) *offset = -1;
+ return false;
+ }
+}
+#else
+struct _address_to_library_name {
+ address addr; // input : memory address
+ size_t buflen; // size of fname
+ char* fname; // output: library name
+ address base; // library base addr
+};
+
+static int address_to_library_name_callback(struct dl_phdr_info *info,
+ size_t size, void *data) {
+ int i;
+ bool found = false;
+ address libbase = NULL;
+ struct _address_to_library_name * d = (struct _address_to_library_name *)data;
+
+ // iterate through all loadable segments
+ for (i = 0; i < info->dlpi_phnum; i++) {
+ address segbase = (address)(info->dlpi_addr + info->dlpi_phdr[i].p_vaddr);
+ if (info->dlpi_phdr[i].p_type == PT_LOAD) {
+ // base address of a library is the lowest address of its loaded
+ // segments.
+ if (libbase == NULL || libbase > segbase) {
+ libbase = segbase;
+ }
+ // see if 'addr' is within current segment
+ if (segbase <= d->addr &&
+ d->addr < segbase + info->dlpi_phdr[i].p_memsz) {
+ found = true;
+ }
+ }
+ }
+
+ // dlpi_name is NULL or empty if the ELF file is executable, return 0
+ // so dll_address_to_library_name() can fall through to use dladdr() which
+ // can figure out executable name from argv[0].
+ if (found && info->dlpi_name && info->dlpi_name[0]) {
+ d->base = libbase;
+ if (d->fname) {
+ jio_snprintf(d->fname, d->buflen, "%s", info->dlpi_name);
+ }
+ return 1;
+ }
+ return 0;
+}
+
+bool os::dll_address_to_library_name(address addr, char* buf,
+ int buflen, int* offset) {
+ Dl_info dlinfo;
+ struct _address_to_library_name data;
+
+ // There is a bug in old glibc dladdr() implementation that it could resolve
+ // to wrong library name if the .so file has a base address != NULL. Here
+ // we iterate through the program headers of all loaded libraries to find
+ // out which library 'addr' really belongs to. This workaround can be
+ // removed once the minimum requirement for glibc is moved to 2.3.x.
+ data.addr = addr;
+ data.fname = buf;
+ data.buflen = buflen;
+ data.base = NULL;
+ int rslt = dl_iterate_phdr(address_to_library_name_callback, (void *)&data);
+
+ if (rslt) {
+ // buf already contains library name
+ if (offset) *offset = addr - data.base;
+ return true;
+ } else if (dladdr((void*)addr, &dlinfo)){
+ if (buf) jio_snprintf(buf, buflen, "%s", dlinfo.dli_fname);
+ if (offset) *offset = addr - (address)dlinfo.dli_fbase;
+ return true;
+ } else {
+ if (buf) buf[0] = '\0';
+ if (offset) *offset = -1;
+ return false;
+ }
+}
+#endif
+
+ // Loads .dll/.so and
+ // in case of error it checks if .dll/.so was built for the
+ // same architecture as Hotspot is running on
+
+#ifdef __APPLE__
+void * os::dll_load(const char *filename, char *ebuf, int ebuflen) {
+ void * result= ::dlopen(filename, RTLD_LAZY);
+ if (result != NULL) {
+ // Successful loading
+ return result;
+ }
+
+ // Read system error message into ebuf
+ ::strncpy(ebuf, ::dlerror(), ebuflen-1);
+ ebuf[ebuflen-1]='\0';
+
+ return NULL;
+}
+#else
+void * os::dll_load(const char *filename, char *ebuf, int ebuflen)
+{
+ void * result= ::dlopen(filename, RTLD_LAZY);
+ if (result != NULL) {
+ // Successful loading
+ return result;
+ }
+
+ Elf32_Ehdr elf_head;
+
+ // Read system error message into ebuf
+ // It may or may not be overwritten below
+ ::strncpy(ebuf, ::dlerror(), ebuflen-1);
+ ebuf[ebuflen-1]='\0';
+ int diag_msg_max_length=ebuflen-strlen(ebuf);
+ char* diag_msg_buf=ebuf+strlen(ebuf);
+
+ if (diag_msg_max_length==0) {
+ // No more space in ebuf for additional diagnostics message
+ return NULL;
+ }
+
+
+ int file_descriptor= ::open(filename, O_RDONLY | O_NONBLOCK);
+
+ if (file_descriptor < 0) {
+ // Can't open library, report dlerror() message
+ return NULL;
+ }
+
+ bool failed_to_read_elf_head=
+ (sizeof(elf_head)!=
+ (::read(file_descriptor, &elf_head,sizeof(elf_head)))) ;
+
+ ::close(file_descriptor);
+ if (failed_to_read_elf_head) {
+ // file i/o error - report dlerror() msg
+ return NULL;
+ }
+
+ typedef struct {
+ Elf32_Half code; // Actual value as defined in elf.h
+ Elf32_Half compat_class; // Compatibility of archs at VM's sense
+ char elf_class; // 32 or 64 bit
+ char endianess; // MSB or LSB
+ char* name; // String representation
+ } arch_t;
+
+ #ifndef EM_486
+ #define EM_486 6 /* Intel 80486 */
+ #endif
+
+ #ifndef EM_MIPS_RS3_LE
+ #define EM_MIPS_RS3_LE 10 /* MIPS */
+ #endif
+
+ #ifndef EM_PPC64
+ #define EM_PPC64 21 /* PowerPC64 */
+ #endif
+
+ #ifndef EM_S390
+ #define EM_S390 22 /* IBM System/390 */
+ #endif
+
+ #ifndef EM_IA_64
+ #define EM_IA_64 50 /* HP/Intel IA-64 */
+ #endif
+
+ #ifndef EM_X86_64
+ #define EM_X86_64 62 /* AMD x86-64 */
+ #endif
+
+ static const arch_t arch_array[]={
+ {EM_386, EM_386, ELFCLASS32, ELFDATA2LSB, (char*)"IA 32"},
+ {EM_486, EM_386, ELFCLASS32, ELFDATA2LSB, (char*)"IA 32"},
+ {EM_IA_64, EM_IA_64, ELFCLASS64, ELFDATA2LSB, (char*)"IA 64"},
+ {EM_X86_64, EM_X86_64, ELFCLASS64, ELFDATA2LSB, (char*)"AMD 64"},
+ {EM_SPARC, EM_SPARC, ELFCLASS32, ELFDATA2MSB, (char*)"Sparc 32"},
+ {EM_SPARC32PLUS, EM_SPARC, ELFCLASS32, ELFDATA2MSB, (char*)"Sparc 32"},
+ {EM_SPARCV9, EM_SPARCV9, ELFCLASS64, ELFDATA2MSB, (char*)"Sparc v9 64"},
+ {EM_PPC, EM_PPC, ELFCLASS32, ELFDATA2MSB, (char*)"Power PC 32"},
+ {EM_PPC64, EM_PPC64, ELFCLASS64, ELFDATA2MSB, (char*)"Power PC 64"},
+ {EM_ARM, EM_ARM, ELFCLASS32, ELFDATA2LSB, (char*)"ARM"},
+ {EM_S390, EM_S390, ELFCLASSNONE, ELFDATA2MSB, (char*)"IBM System/390"},
+ {EM_ALPHA, EM_ALPHA, ELFCLASS64, ELFDATA2LSB, (char*)"Alpha"},
+ {EM_MIPS_RS3_LE, EM_MIPS_RS3_LE, ELFCLASS32, ELFDATA2LSB, (char*)"MIPSel"},
+ {EM_MIPS, EM_MIPS, ELFCLASS32, ELFDATA2MSB, (char*)"MIPS"},
+ {EM_PARISC, EM_PARISC, ELFCLASS32, ELFDATA2MSB, (char*)"PARISC"},
+ {EM_68K, EM_68K, ELFCLASS32, ELFDATA2MSB, (char*)"M68k"}
+ };
+
+ #if (defined IA32)
+ static Elf32_Half running_arch_code=EM_386;
+ #elif (defined AMD64)
+ static Elf32_Half running_arch_code=EM_X86_64;
+ #elif (defined IA64)
+ static Elf32_Half running_arch_code=EM_IA_64;
+ #elif (defined __sparc) && (defined _LP64)
+ static Elf32_Half running_arch_code=EM_SPARCV9;
+ #elif (defined __sparc) && (!defined _LP64)
+ static Elf32_Half running_arch_code=EM_SPARC;
+ #elif (defined __powerpc64__)
+ static Elf32_Half running_arch_code=EM_PPC64;
+ #elif (defined __powerpc__)
+ static Elf32_Half running_arch_code=EM_PPC;
+ #elif (defined ARM)
+ static Elf32_Half running_arch_code=EM_ARM;
+ #elif (defined S390)
+ static Elf32_Half running_arch_code=EM_S390;
+ #elif (defined ALPHA)
+ static Elf32_Half running_arch_code=EM_ALPHA;
+ #elif (defined MIPSEL)
+ static Elf32_Half running_arch_code=EM_MIPS_RS3_LE;
+ #elif (defined PARISC)
+ static Elf32_Half running_arch_code=EM_PARISC;
+ #elif (defined MIPS)
+ static Elf32_Half running_arch_code=EM_MIPS;
+ #elif (defined M68K)
+ static Elf32_Half running_arch_code=EM_68K;
+ #else
+ #error Method os::dll_load requires that one of following is defined:\
+ IA32, AMD64, IA64, __sparc, __powerpc__, ARM, S390, ALPHA, MIPS, MIPSEL, PARISC, M68K
+ #endif
+
+ // Identify compatability class for VM's architecture and library's architecture
+ // Obtain string descriptions for architectures
+
+ arch_t lib_arch={elf_head.e_machine,0,elf_head.e_ident[EI_CLASS], elf_head.e_ident[EI_DATA], NULL};
+ int running_arch_index=-1;
+
+ for (unsigned int i=0 ; i < ARRAY_SIZE(arch_array) ; i++ ) {
+ if (running_arch_code == arch_array[i].code) {
+ running_arch_index = i;
+ }
+ if (lib_arch.code == arch_array[i].code) {
+ lib_arch.compat_class = arch_array[i].compat_class;
+ lib_arch.name = arch_array[i].name;
+ }
+ }
+
+ assert(running_arch_index != -1,
+ "Didn't find running architecture code (running_arch_code) in arch_array");
+ if (running_arch_index == -1) {
+ // Even though running architecture detection failed
+ // we may still continue with reporting dlerror() message
+ return NULL;
+ }
+
+ if (lib_arch.endianess != arch_array[running_arch_index].endianess) {
+ ::snprintf(diag_msg_buf, diag_msg_max_length-1," (Possible cause: endianness mismatch)");
+ return NULL;
+ }
+
+#ifndef S390
+ if (lib_arch.elf_class != arch_array[running_arch_index].elf_class) {
+ ::snprintf(diag_msg_buf, diag_msg_max_length-1," (Possible cause: architecture word width mismatch)");
+ return NULL;
+ }
+#endif // !S390
+
+ if (lib_arch.compat_class != arch_array[running_arch_index].compat_class) {
+ if ( lib_arch.name!=NULL ) {
+ ::snprintf(diag_msg_buf, diag_msg_max_length-1,
+ " (Possible cause: can't load %s-bit .so on a %s-bit platform)",
+ lib_arch.name, arch_array[running_arch_index].name);
+ } else {
+ ::snprintf(diag_msg_buf, diag_msg_max_length-1,
+ " (Possible cause: can't load this .so (machine code=0x%x) on a %s-bit platform)",
+ lib_arch.code,
+ arch_array[running_arch_index].name);
+ }
+ }
+
+ return NULL;
+}
+#endif /* !__APPLE__ */
+
+// XXX: Do we need a lock around this as per Linux?
+void* os::dll_lookup(void* handle, const char* name) {
+ return dlsym(handle, name);
+}
+
+
+static bool _print_ascii_file(const char* filename, outputStream* st) {
+ int fd = ::open(filename, O_RDONLY);
+ if (fd == -1) {
+ return false;
+ }
+
+ char buf[32];
+ int bytes;
+ while ((bytes = ::read(fd, buf, sizeof(buf))) > 0) {
+ st->print_raw(buf, bytes);
+ }
+
+ ::close(fd);
+
+ return true;
+}
+
+void os::print_dll_info(outputStream *st) {
+ st->print_cr("Dynamic libraries:");
+#ifdef _ALLBSD_SOURCE
+#ifdef RTLD_DI_LINKMAP
+ Dl_info dli;
+ void *handle;
+ Link_map *map;
+ Link_map *p;
+
+ if (!dladdr(CAST_FROM_FN_PTR(void *, os::print_dll_info), &dli)) {
+ st->print_cr("Error: Cannot print dynamic libraries.");
+ return;
+ }
+ handle = dlopen(dli.dli_fname, RTLD_LAZY);
+ if (handle == NULL) {
+ st->print_cr("Error: Cannot print dynamic libraries.");
+ return;
+ }
+ dlinfo(handle, RTLD_DI_LINKMAP, &map);
+ if (map == NULL) {
+ st->print_cr("Error: Cannot print dynamic libraries.");
+ return;
+ }
+
+ while (map->l_prev != NULL)
+ map = map->l_prev;
+
+ while (map != NULL) {
+ st->print_cr(PTR_FORMAT " \t%s", map->l_addr, map->l_name);
+ map = map->l_next;
+ }
+
+ dlclose(handle);
+#elif defined(__APPLE__)
+ uint32_t count;
+ uint32_t i;
+
+ count = _dyld_image_count();
+ for (i = 1; i < count; i++) {
+ const char *name = _dyld_get_image_name(i);
+ intptr_t slide = _dyld_get_image_vmaddr_slide(i);
+ st->print_cr(PTR_FORMAT " \t%s", slide, name);
+ }
+#else
+ st->print_cr("Error: Cannot print dynamic libraries.");
+#endif
+#else
+ char fname[32];
+ pid_t pid = os::Bsd::gettid();
+
+ jio_snprintf(fname, sizeof(fname), "/proc/%d/maps", pid);
+
+ if (!_print_ascii_file(fname, st)) {
+ st->print("Can not get library information for pid = %d\n", pid);
+ }
+#endif
+}
+
+
+void os::print_os_info(outputStream* st) {
+ st->print("OS:");
+
+ // Try to identify popular distros.
+ // Most Bsd distributions have /etc/XXX-release file, which contains
+ // the OS version string. Some have more than one /etc/XXX-release file
+ // (e.g. Mandrake has both /etc/mandrake-release and /etc/redhat-release.),
+ // so the order is important.
+ if (!_print_ascii_file("/etc/mandrake-release", st) &&
+ !_print_ascii_file("/etc/sun-release", st) &&
+ !_print_ascii_file("/etc/redhat-release", st) &&
+ !_print_ascii_file("/etc/SuSE-release", st) &&
+ !_print_ascii_file("/etc/turbobsd-release", st) &&
+ !_print_ascii_file("/etc/gentoo-release", st) &&
+ !_print_ascii_file("/etc/debian_version", st) &&
+ !_print_ascii_file("/etc/ltib-release", st) &&
+ !_print_ascii_file("/etc/angstrom-version", st)) {
+ st->print("Bsd");
+ }
+ st->cr();
+
+ // kernel
+ st->print("uname:");
+ struct utsname name;
+ uname(&name);
+ st->print(name.sysname); st->print(" ");
+ st->print(name.release); st->print(" ");
+ st->print(name.version); st->print(" ");
+ st->print(name.machine);
+ st->cr();
+
+#ifndef _ALLBSD_SOURCE
+ // Print warning if unsafe chroot environment detected
+ if (unsafe_chroot_detected) {
+ st->print("WARNING!! ");
+ st->print_cr(unstable_chroot_error);
+ }
+
+ // libc, pthread
+ st->print("libc:");
+ st->print(os::Bsd::glibc_version()); st->print(" ");
+ st->print(os::Bsd::libpthread_version()); st->print(" ");
+ if (os::Bsd::is_BsdThreads()) {
+ st->print("(%s stack)", os::Bsd::is_floating_stack() ? "floating" : "fixed");
+ }
+ st->cr();
+#endif
+
+ // rlimit
+ st->print("rlimit:");
+ struct rlimit rlim;
+
+ st->print(" STACK ");
+ getrlimit(RLIMIT_STACK, &rlim);
+ if (rlim.rlim_cur == RLIM_INFINITY) st->print("infinity");
+ else st->print("%uk", rlim.rlim_cur >> 10);
+
+ st->print(", CORE ");
+ getrlimit(RLIMIT_CORE, &rlim);
+ if (rlim.rlim_cur == RLIM_INFINITY) st->print("infinity");
+ else st->print("%uk", rlim.rlim_cur >> 10);
+
+ st->print(", NPROC ");
+ getrlimit(RLIMIT_NPROC, &rlim);
+ if (rlim.rlim_cur == RLIM_INFINITY) st->print("infinity");
+ else st->print("%d", rlim.rlim_cur);
+
+ st->print(", NOFILE ");
+ getrlimit(RLIMIT_NOFILE, &rlim);
+ if (rlim.rlim_cur == RLIM_INFINITY) st->print("infinity");
+ else st->print("%d", rlim.rlim_cur);
+
+#ifndef _ALLBSD_SOURCE
+ st->print(", AS ");
+ getrlimit(RLIMIT_AS, &rlim);
+ if (rlim.rlim_cur == RLIM_INFINITY) st->print("infinity");
+ else st->print("%uk", rlim.rlim_cur >> 10);
+ st->cr();
+
+ // load average
+ st->print("load average:");
+ double loadavg[3];
+ os::loadavg(loadavg, 3);
+ st->print("%0.02f %0.02f %0.02f", loadavg[0], loadavg[1], loadavg[2]);
+ st->cr();
+#endif
+}
+
+void os::pd_print_cpu_info(outputStream* st) {
+ // Nothing to do for now.
+}
+
+void os::print_memory_info(outputStream* st) {
+
+ st->print("Memory:");
+ st->print(" %dk page", os::vm_page_size()>>10);
+
+#ifndef _ALLBSD_SOURCE
+ // values in struct sysinfo are "unsigned long"
+ struct sysinfo si;
+ sysinfo(&si);
+#endif
+
+ st->print(", physical " UINT64_FORMAT "k",
+ os::physical_memory() >> 10);
+ st->print("(" UINT64_FORMAT "k free)",
+ os::available_memory() >> 10);
+#ifndef _ALLBSD_SOURCE
+ st->print(", swap " UINT64_FORMAT "k",
+ ((jlong)si.totalswap * si.mem_unit) >> 10);
+ st->print("(" UINT64_FORMAT "k free)",
+ ((jlong)si.freeswap * si.mem_unit) >> 10);
+#endif
+ st->cr();
+
+ // meminfo
+ st->print("\n/proc/meminfo:\n");
+ _print_ascii_file("/proc/meminfo", st);
+ st->cr();
+}
+
+// Taken from /usr/include/bits/siginfo.h Supposed to be architecture specific
+// but they're the same for all the bsd arch that we support
+// and they're the same for solaris but there's no common place to put this.
+const char *ill_names[] = { "ILL0", "ILL_ILLOPC", "ILL_ILLOPN", "ILL_ILLADR",
+ "ILL_ILLTRP", "ILL_PRVOPC", "ILL_PRVREG",
+ "ILL_COPROC", "ILL_BADSTK" };
+
+const char *fpe_names[] = { "FPE0", "FPE_INTDIV", "FPE_INTOVF", "FPE_FLTDIV",
+ "FPE_FLTOVF", "FPE_FLTUND", "FPE_FLTRES",
+ "FPE_FLTINV", "FPE_FLTSUB", "FPE_FLTDEN" };
+
+const char *segv_names[] = { "SEGV0", "SEGV_MAPERR", "SEGV_ACCERR" };
+
+const char *bus_names[] = { "BUS0", "BUS_ADRALN", "BUS_ADRERR", "BUS_OBJERR" };
+
+void os::print_siginfo(outputStream* st, void* siginfo) {
+ st->print("siginfo:");
+
+ const int buflen = 100;
+ char buf[buflen];
+ siginfo_t *si = (siginfo_t*)siginfo;
+ st->print("si_signo=%s: ", os::exception_name(si->si_signo, buf, buflen));
+ if (si->si_errno != 0 && strerror_r(si->si_errno, buf, buflen) == 0) {
+ st->print("si_errno=%s", buf);
+ } else {
+ st->print("si_errno=%d", si->si_errno);
+ }
+ const int c = si->si_code;
+ assert(c > 0, "unexpected si_code");
+ switch (si->si_signo) {
+ case SIGILL:
+ st->print(", si_code=%d (%s)", c, c > 8 ? "" : ill_names[c]);
+ st->print(", si_addr=" PTR_FORMAT, si->si_addr);
+ break;
+ case SIGFPE:
+ st->print(", si_code=%d (%s)", c, c > 9 ? "" : fpe_names[c]);
+ st->print(", si_addr=" PTR_FORMAT, si->si_addr);
+ break;
+ case SIGSEGV:
+ st->print(", si_code=%d (%s)", c, c > 2 ? "" : segv_names[c]);
+ st->print(", si_addr=" PTR_FORMAT, si->si_addr);
+ break;
+ case SIGBUS:
+ st->print(", si_code=%d (%s)", c, c > 3 ? "" : bus_names[c]);
+ st->print(", si_addr=" PTR_FORMAT, si->si_addr);
+ break;
+ default:
+ st->print(", si_code=%d", si->si_code);
+ // no si_addr
+ }
+
+ if ((si->si_signo == SIGBUS || si->si_signo == SIGSEGV) &&
+ UseSharedSpaces) {
+ FileMapInfo* mapinfo = FileMapInfo::current_info();
+ if (mapinfo->is_in_shared_space(si->si_addr)) {
+ st->print("\n\nError accessing class data sharing archive." \
+ " Mapped file inaccessible during execution, " \
+ " possible disk/network problem.");
+ }
+ }
+ st->cr();
+}
+
+
+static void print_signal_handler(outputStream* st, int sig,
+ char* buf, size_t buflen);
+
+void os::print_signal_handlers(outputStream* st, char* buf, size_t buflen) {
+ st->print_cr("Signal Handlers:");
+ print_signal_handler(st, SIGSEGV, buf, buflen);
+ print_signal_handler(st, SIGBUS , buf, buflen);
+ print_signal_handler(st, SIGFPE , buf, buflen);
+ print_signal_handler(st, SIGPIPE, buf, buflen);
+ print_signal_handler(st, SIGXFSZ, buf, buflen);
+ print_signal_handler(st, SIGILL , buf, buflen);
+ print_signal_handler(st, INTERRUPT_SIGNAL, buf, buflen);
+ print_signal_handler(st, SR_signum, buf, buflen);
+ print_signal_handler(st, SHUTDOWN1_SIGNAL, buf, buflen);
+ print_signal_handler(st, SHUTDOWN2_SIGNAL , buf, buflen);
+ print_signal_handler(st, SHUTDOWN3_SIGNAL , buf, buflen);
+ print_signal_handler(st, BREAK_SIGNAL, buf, buflen);
+}
+
+static char saved_jvm_path[MAXPATHLEN] = {0};
+
+// Find the full path to the current module, libjvm.so or libjvm_g.so
+void os::jvm_path(char *buf, jint buflen) {
+ // Error checking.
+ if (buflen < MAXPATHLEN) {
+ assert(false, "must use a large-enough buffer");
+ buf[0] = '\0';
+ return;
+ }
+ // Lazy resolve the path to current module.
+ if (saved_jvm_path[0] != 0) {
+ strcpy(buf, saved_jvm_path);
+ return;
+ }
+
+ char dli_fname[MAXPATHLEN];
+ bool ret = dll_address_to_library_name(
+ CAST_FROM_FN_PTR(address, os::jvm_path),
+ dli_fname, sizeof(dli_fname), NULL);
+ assert(ret != 0, "cannot locate libjvm");
+ char *rp = realpath(dli_fname, buf);
+ if (rp == NULL)
+ return;
+
+ if (Arguments::created_by_gamma_launcher()) {
+ // Support for the gamma launcher. Typical value for buf is
+ // "<JAVA_HOME>/jre/lib/<arch>/<vmtype>/libjvm.so". If "/jre/lib/" appears at
+ // the right place in the string, then assume we are installed in a JDK and
+ // we're done. Otherwise, check for a JAVA_HOME environment variable and fix
+ // up the path so it looks like libjvm.so is installed there (append a
+ // fake suffix hotspot/libjvm.so).
+ const char *p = buf + strlen(buf) - 1;
+ for (int count = 0; p > buf && count < 5; ++count) {
+ for (--p; p > buf && *p != '/'; --p)
+ /* empty */ ;
+ }
+
+ if (strncmp(p, "/jre/lib/", 9) != 0) {
+ // Look for JAVA_HOME in the environment.
+ char* java_home_var = ::getenv("JAVA_HOME");
+ if (java_home_var != NULL && java_home_var[0] != 0) {
+ char* jrelib_p;
+ int len;
+
+ // Check the current module name "libjvm.so" or "libjvm_g.so".
+ p = strrchr(buf, '/');
+ assert(strstr(p, "/libjvm") == p, "invalid library name");
+ p = strstr(p, "_g") ? "_g" : "";
+
+ rp = realpath(java_home_var, buf);
+ if (rp == NULL)
+ return;
+
+ // determine if this is a legacy image or modules image
+ // modules image doesn't have "jre" subdirectory
+ len = strlen(buf);
+ jrelib_p = buf + len;
+ snprintf(jrelib_p, buflen-len, "/jre/lib/%s", cpu_arch);
+ if (0 != access(buf, F_OK)) {
+ snprintf(jrelib_p, buflen-len, "/lib/%s", cpu_arch);
+ }
+
+ if (0 == access(buf, F_OK)) {
+ // Use current module name "libjvm[_g].so" instead of
+ // "libjvm"debug_only("_g")".so" since for fastdebug version
+ // we should have "libjvm.so" but debug_only("_g") adds "_g"!
+ len = strlen(buf);
+ snprintf(buf + len, buflen-len, "/hotspot/libjvm%s.so", p);
+ } else {
+ // Go back to path of .so
+ rp = realpath(dli_fname, buf);
+ if (rp == NULL)
+ return;
+ }
+ }
+ }
+ }
+
+ strcpy(saved_jvm_path, buf);
+}
+
+void os::print_jni_name_prefix_on(outputStream* st, int args_size) {
+ // no prefix required, not even "_"
+}
+
+void os::print_jni_name_suffix_on(outputStream* st, int args_size) {
+ // no suffix required
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// sun.misc.Signal support
+
+static volatile jint sigint_count = 0;
+
+static void
+UserHandler(int sig, void *siginfo, void *context) {
+ // 4511530 - sem_post is serialized and handled by the manager thread. When
+ // the program is interrupted by Ctrl-C, SIGINT is sent to every thread. We
+ // don't want to flood the manager thread with sem_post requests.
+ if (sig == SIGINT && Atomic::add(1, &sigint_count) > 1)
+ return;
+
+ // Ctrl-C is pressed during error reporting, likely because the error
+ // handler fails to abort. Let VM die immediately.
+ if (sig == SIGINT && is_error_reported()) {
+ os::die();
+ }
+
+ os::signal_notify(sig);
+}
+
+void* os::user_handler() {
+ return CAST_FROM_FN_PTR(void*, UserHandler);
+}
+
+extern "C" {
+ typedef void (*sa_handler_t)(int);
+ typedef void (*sa_sigaction_t)(int, siginfo_t *, void *);
+}
+
+void* os::signal(int signal_number, void* handler) {
+ struct sigaction sigAct, oldSigAct;
+
+ sigfillset(&(sigAct.sa_mask));
+ sigAct.sa_flags = SA_RESTART|SA_SIGINFO;
+ sigAct.sa_handler = CAST_TO_FN_PTR(sa_handler_t, handler);
+
+ if (sigaction(signal_number, &sigAct, &oldSigAct)) {
+ // -1 means registration failed
+ return (void *)-1;
+ }
+
+ return CAST_FROM_FN_PTR(void*, oldSigAct.sa_handler);
+}
+
+void os::signal_raise(int signal_number) {
+ ::raise(signal_number);
+}
+
+/*
+ * The following code is moved from os.cpp for making this
+ * code platform specific, which it is by its very nature.
+ */
+
+// Will be modified when max signal is changed to be dynamic
+int os::sigexitnum_pd() {
+ return NSIG;
+}
+
+// a counter for each possible signal value
+static volatile jint pending_signals[NSIG+1] = { 0 };
+
+// Bsd(POSIX) specific hand shaking semaphore.
+#ifdef __APPLE__
+static semaphore_t sig_sem;
+#define SEM_INIT(sem, value) semaphore_create(mach_task_self(), &sem, SYNC_POLICY_FIFO, value)
+#define SEM_WAIT(sem) semaphore_wait(sem);
+#define SEM_POST(sem) semaphore_signal(sem);
+#else
+static sem_t sig_sem;
+#define SEM_INIT(sem, value) sem_init(&sem, 0, value)
+#define SEM_WAIT(sem) sem_wait(&sem);
+#define SEM_POST(sem) sem_post(&sem);
+#endif
+
+void os::signal_init_pd() {
+ // Initialize signal structures
+ ::memset((void*)pending_signals, 0, sizeof(pending_signals));
+
+ // Initialize signal semaphore
+ ::SEM_INIT(sig_sem, 0);
+}
+
+void os::signal_notify(int sig) {
+ Atomic::inc(&pending_signals[sig]);
+ ::SEM_POST(sig_sem);
+}
+
+static int check_pending_signals(bool wait) {
+ Atomic::store(0, &sigint_count);
+ for (;;) {
+ for (int i = 0; i < NSIG + 1; i++) {
+ jint n = pending_signals[i];
+ if (n > 0 && n == Atomic::cmpxchg(n - 1, &pending_signals[i], n)) {
+ return i;
+ }
+ }
+ if (!wait) {
+ return -1;
+ }
+ JavaThread *thread = JavaThread::current();
+ ThreadBlockInVM tbivm(thread);
+
+ bool threadIsSuspended;
+ do {
+ thread->set_suspend_equivalent();
+ // cleared by handle_special_suspend_equivalent_condition() or java_suspend_self()
+ ::SEM_WAIT(sig_sem);
+
+ // were we externally suspended while we were waiting?
+ threadIsSuspended = thread->handle_special_suspend_equivalent_condition();
+ if (threadIsSuspended) {
+ //
+ // The semaphore has been incremented, but while we were waiting
+ // another thread suspended us. We don't want to continue running
+ // while suspended because that would surprise the thread that
+ // suspended us.
+ //
+ ::SEM_POST(sig_sem);
+
+ thread->java_suspend_self();
+ }
+ } while (threadIsSuspended);
+ }
+}
+
+int os::signal_lookup() {
+ return check_pending_signals(false);
+}
+
+int os::signal_wait() {
+ return check_pending_signals(true);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Virtual Memory
+
+int os::vm_page_size() {
+ // Seems redundant as all get out
+ assert(os::Bsd::page_size() != -1, "must call os::init");
+ return os::Bsd::page_size();
+}
+
+// Solaris allocates memory by pages.
+int os::vm_allocation_granularity() {
+ assert(os::Bsd::page_size() != -1, "must call os::init");
+ return os::Bsd::page_size();
+}
+
+// Rationale behind this function:
+// current (Mon Apr 25 20:12:18 MSD 2005) oprofile drops samples without executable
+// mapping for address (see lookup_dcookie() in the kernel module), thus we cannot get
+// samples for JITted code. Here we create private executable mapping over the code cache
+// and then we can use standard (well, almost, as mapping can change) way to provide
+// info for the reporting script by storing timestamp and location of symbol
+void bsd_wrap_code(char* base, size_t size) {
+ static volatile jint cnt = 0;
+
+ if (!UseOprofile) {
+ return;
+ }
+
+ char buf[PATH_MAX + 1];
+ int num = Atomic::add(1, &cnt);
+
+ snprintf(buf, PATH_MAX + 1, "%s/hs-vm-%d-%d",
+ os::get_temp_directory(), os::current_process_id(), num);
+ unlink(buf);
+
+ int fd = ::open(buf, O_CREAT | O_RDWR, S_IRWXU);
+
+ if (fd != -1) {
+ off_t rv = ::lseek(fd, size-2, SEEK_SET);
+ if (rv != (off_t)-1) {
+ if (::write(fd, "", 1) == 1) {
+ mmap(base, size,
+ PROT_READ|PROT_WRITE|PROT_EXEC,
+ MAP_PRIVATE|MAP_FIXED|MAP_NORESERVE, fd, 0);
+ }
+ }
+ ::close(fd);
+ unlink(buf);
+ }
+}
+
+// NOTE: Bsd kernel does not really reserve the pages for us.
+// All it does is to check if there are enough free pages
+// left at the time of mmap(). This could be a potential
+// problem.
+bool os::commit_memory(char* addr, size_t size, bool exec) {
+ int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE;
+#ifdef __OpenBSD__
+ // XXX: Work-around mmap/MAP_FIXED bug temporarily on OpenBSD
+ return ::mprotect(addr, size, prot) == 0;
+#else
+ uintptr_t res = (uintptr_t) ::mmap(addr, size, prot,
+ MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0);
+ return res != (uintptr_t) MAP_FAILED;
+#endif
+}
+
+#ifndef _ALLBSD_SOURCE
+// Define MAP_HUGETLB here so we can build HotSpot on old systems.
+#ifndef MAP_HUGETLB
+#define MAP_HUGETLB 0x40000
+#endif
+
+// Define MADV_HUGEPAGE here so we can build HotSpot on old systems.
+#ifndef MADV_HUGEPAGE
+#define MADV_HUGEPAGE 14
+#endif
+#endif
+
+bool os::commit_memory(char* addr, size_t size, size_t alignment_hint,
+ bool exec) {
+#ifndef _ALLBSD_SOURCE
+ if (UseHugeTLBFS && alignment_hint > (size_t)vm_page_size()) {
+ int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE;
+ uintptr_t res =
+ (uintptr_t) ::mmap(addr, size, prot,
+ MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS|MAP_HUGETLB,
+ -1, 0);
+ return res != (uintptr_t) MAP_FAILED;
+ }
+#endif
+
+ return commit_memory(addr, size, exec);
+}
+
+void os::realign_memory(char *addr, size_t bytes, size_t alignment_hint) {
+#ifndef _ALLBSD_SOURCE
+ if (UseHugeTLBFS && alignment_hint > (size_t)vm_page_size()) {
+ // We don't check the return value: madvise(MADV_HUGEPAGE) may not
+ // be supported or the memory may already be backed by huge pages.
+ ::madvise(addr, bytes, MADV_HUGEPAGE);
+ }
+#endif
+}
+
+void os::free_memory(char *addr, size_t bytes) {
+ ::madvise(addr, bytes, MADV_DONTNEED);
+}
+
+void os::numa_make_global(char *addr, size_t bytes) {
+}
+
+void os::numa_make_local(char *addr, size_t bytes, int lgrp_hint) {
+}
+
+bool os::numa_topology_changed() { return false; }
+
+size_t os::numa_get_groups_num() {
+ return 1;
+}
+
+int os::numa_get_group_id() {
+ return 0;
+}
+
+size_t os::numa_get_leaf_groups(int *ids, size_t size) {
+ if (size > 0) {
+ ids[0] = 0;
+ return 1;
+ }
+ return 0;
+}
+
+bool os::get_page_info(char *start, page_info* info) {
+ return false;
+}
+
+char *os::scan_pages(char *start, char* end, page_info* page_expected, page_info* page_found) {
+ return end;
+}
+
+#ifndef _ALLBSD_SOURCE
+// Something to do with the numa-aware allocator needs these symbols
+extern "C" JNIEXPORT void numa_warn(int number, char *where, ...) { }
+extern "C" JNIEXPORT void numa_error(char *where) { }
+extern "C" JNIEXPORT int fork1() { return fork(); }
+
+
+// If we are running with libnuma version > 2, then we should
+// be trying to use symbols with versions 1.1
+// If we are running with earlier version, which did not have symbol versions,
+// we should use the base version.
+void* os::Bsd::libnuma_dlsym(void* handle, const char *name) {
+ void *f = dlvsym(handle, name, "libnuma_1.1");
+ if (f == NULL) {
+ f = dlsym(handle, name);
+ }
+ return f;
+}
+
+bool os::Bsd::libnuma_init() {
+ // sched_getcpu() should be in libc.
+ set_sched_getcpu(CAST_TO_FN_PTR(sched_getcpu_func_t,
+ dlsym(RTLD_DEFAULT, "sched_getcpu")));
+
+ if (sched_getcpu() != -1) { // Does it work?
+ void *handle = dlopen("libnuma.so.1", RTLD_LAZY);
+ if (handle != NULL) {
+ set_numa_node_to_cpus(CAST_TO_FN_PTR(numa_node_to_cpus_func_t,
+ libnuma_dlsym(handle, "numa_node_to_cpus")));
+ set_numa_max_node(CAST_TO_FN_PTR(numa_max_node_func_t,
+ libnuma_dlsym(handle, "numa_max_node")));
+ set_numa_available(CAST_TO_FN_PTR(numa_available_func_t,
+ libnuma_dlsym(handle, "numa_available")));
+ set_numa_tonode_memory(CAST_TO_FN_PTR(numa_tonode_memory_func_t,
+ libnuma_dlsym(handle, "numa_tonode_memory")));
+ set_numa_interleave_memory(CAST_TO_FN_PTR(numa_interleave_memory_func_t,
+ libnuma_dlsym(handle, "numa_interleave_memory")));
+
+
+ if (numa_available() != -1) {
+ set_numa_all_nodes((unsigned long*)libnuma_dlsym(handle, "numa_all_nodes"));
+ // Create a cpu -> node mapping
+ _cpu_to_node = new (ResourceObj::C_HEAP) GrowableArray<int>(0, true);
+ rebuild_cpu_to_node_map();
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+// rebuild_cpu_to_node_map() constructs a table mapping cpud id to node id.
+// The table is later used in get_node_by_cpu().
+void os::Bsd::rebuild_cpu_to_node_map() {
+ const size_t NCPUS = 32768; // Since the buffer size computation is very obscure
+ // in libnuma (possible values are starting from 16,
+ // and continuing up with every other power of 2, but less
+ // than the maximum number of CPUs supported by kernel), and
+ // is a subject to change (in libnuma version 2 the requirements
+ // are more reasonable) we'll just hardcode the number they use
+ // in the library.
+ const size_t BitsPerCLong = sizeof(long) * CHAR_BIT;
+
+ size_t cpu_num = os::active_processor_count();
+ size_t cpu_map_size = NCPUS / BitsPerCLong;
+ size_t cpu_map_valid_size =
+ MIN2((cpu_num + BitsPerCLong - 1) / BitsPerCLong, cpu_map_size);
+
+ cpu_to_node()->clear();
+ cpu_to_node()->at_grow(cpu_num - 1);
+ size_t node_num = numa_get_groups_num();
+
+ unsigned long *cpu_map = NEW_C_HEAP_ARRAY(unsigned long, cpu_map_size);
+ for (size_t i = 0; i < node_num; i++) {
+ if (numa_node_to_cpus(i, cpu_map, cpu_map_size * sizeof(unsigned long)) != -1) {
+ for (size_t j = 0; j < cpu_map_valid_size; j++) {
+ if (cpu_map[j] != 0) {
+ for (size_t k = 0; k < BitsPerCLong; k++) {
+ if (cpu_map[j] & (1UL << k)) {
+ cpu_to_node()->at_put(j * BitsPerCLong + k, i);
+ }
+ }
+ }
+ }
+ }
+ }
+ FREE_C_HEAP_ARRAY(unsigned long, cpu_map);
+}
+
+int os::Bsd::get_node_by_cpu(int cpu_id) {
+ if (cpu_to_node() != NULL && cpu_id >= 0 && cpu_id < cpu_to_node()->length()) {
+ return cpu_to_node()->at(cpu_id);
+ }
+ return -1;
+}
+
+GrowableArray<int>* os::Bsd::_cpu_to_node;
+os::Bsd::sched_getcpu_func_t os::Bsd::_sched_getcpu;
+os::Bsd::numa_node_to_cpus_func_t os::Bsd::_numa_node_to_cpus;
+os::Bsd::numa_max_node_func_t os::Bsd::_numa_max_node;
+os::Bsd::numa_available_func_t os::Bsd::_numa_available;
+os::Bsd::numa_tonode_memory_func_t os::Bsd::_numa_tonode_memory;
+os::Bsd::numa_interleave_memory_func_t os::Bsd::_numa_interleave_memory;
+unsigned long* os::Bsd::_numa_all_nodes;
+#endif
+
+bool os::uncommit_memory(char* addr, size_t size) {
+#ifdef __OpenBSD__
+ // XXX: Work-around mmap/MAP_FIXED bug temporarily on OpenBSD
+ return ::mprotect(addr, size, PROT_NONE) == 0;
+#else
+ uintptr_t res = (uintptr_t) ::mmap(addr, size, PROT_NONE,
+ MAP_PRIVATE|MAP_FIXED|MAP_NORESERVE|MAP_ANONYMOUS, -1, 0);
+ return res != (uintptr_t) MAP_FAILED;
+#endif
+}
+
+bool os::create_stack_guard_pages(char* addr, size_t size) {
+ return os::commit_memory(addr, size);
+}
+
+// If this is a growable mapping, remove the guard pages entirely by
+// munmap()ping them. If not, just call uncommit_memory().
+bool os::remove_stack_guard_pages(char* addr, size_t size) {
+ return os::uncommit_memory(addr, size);
+}
+
+static address _highest_vm_reserved_address = NULL;
+
+// If 'fixed' is true, anon_mmap() will attempt to reserve anonymous memory
+// at 'requested_addr'. If there are existing memory mappings at the same
+// location, however, they will be overwritten. If 'fixed' is false,
+// 'requested_addr' is only treated as a hint, the return value may or
+// may not start from the requested address. Unlike Bsd mmap(), this
+// function returns NULL to indicate failure.
+static char* anon_mmap(char* requested_addr, size_t bytes, bool fixed) {
+ char * addr;
+ int flags;
+
+ flags = MAP_PRIVATE | MAP_NORESERVE | MAP_ANONYMOUS;
+ if (fixed) {
+ assert((uintptr_t)requested_addr % os::Bsd::page_size() == 0, "unaligned address");
+ flags |= MAP_FIXED;
+ }
+
+ // Map uncommitted pages PROT_READ and PROT_WRITE, change access
+ // to PROT_EXEC if executable when we commit the page.
+ addr = (char*)::mmap(requested_addr, bytes, PROT_READ|PROT_WRITE,
+ flags, -1, 0);
+
+ if (addr != MAP_FAILED) {
+ // anon_mmap() should only get called during VM initialization,
+ // don't need lock (actually we can skip locking even it can be called
+ // from multiple threads, because _highest_vm_reserved_address is just a
+ // hint about the upper limit of non-stack memory regions.)
+ if ((address)addr + bytes > _highest_vm_reserved_address) {
+ _highest_vm_reserved_address = (address)addr + bytes;
+ }
+ }
+
+ return addr == MAP_FAILED ? NULL : addr;
+}
+
+// Don't update _highest_vm_reserved_address, because there might be memory
+// regions above addr + size. If so, releasing a memory region only creates
+// a hole in the address space, it doesn't help prevent heap-stack collision.
+//
+static int anon_munmap(char * addr, size_t size) {
+ return ::munmap(addr, size) == 0;
+}
+
+char* os::reserve_memory(size_t bytes, char* requested_addr,
+ size_t alignment_hint) {
+ return anon_mmap(requested_addr, bytes, (requested_addr != NULL));
+}
+
+bool os::release_memory(char* addr, size_t size) {
+ return anon_munmap(addr, size);
+}
+
+static address highest_vm_reserved_address() {
+ return _highest_vm_reserved_address;
+}
+
+static bool bsd_mprotect(char* addr, size_t size, int prot) {
+ // Bsd wants the mprotect address argument to be page aligned.
+ char* bottom = (char*)align_size_down((intptr_t)addr, os::Bsd::page_size());
+
+ // According to SUSv3, mprotect() should only be used with mappings
+ // established by mmap(), and mmap() always maps whole pages. Unaligned
+ // 'addr' likely indicates problem in the VM (e.g. trying to change
+ // protection of malloc'ed or statically allocated memory). Check the
+ // caller if you hit this assert.
+ assert(addr == bottom, "sanity check");
+
+ size = align_size_up(pointer_delta(addr, bottom, 1) + size, os::Bsd::page_size());
+ return ::mprotect(bottom, size, prot) == 0;
+}
+
+// Set protections specified
+bool os::protect_memory(char* addr, size_t bytes, ProtType prot,
+ bool is_committed) {
+ unsigned int p = 0;
+ switch (prot) {
+ case MEM_PROT_NONE: p = PROT_NONE; break;
+ case MEM_PROT_READ: p = PROT_READ; break;
+ case MEM_PROT_RW: p = PROT_READ|PROT_WRITE; break;
+ case MEM_PROT_RWX: p = PROT_READ|PROT_WRITE|PROT_EXEC; break;
+ default:
+ ShouldNotReachHere();
+ }
+ // is_committed is unused.
+ return bsd_mprotect(addr, bytes, p);
+}
+
+bool os::guard_memory(char* addr, size_t size) {
+ return bsd_mprotect(addr, size, PROT_NONE);
+}
+
+bool os::unguard_memory(char* addr, size_t size) {
+ return bsd_mprotect(addr, size, PROT_READ|PROT_WRITE);
+}
+
+bool os::Bsd::hugetlbfs_sanity_check(bool warn, size_t page_size) {
+ bool result = false;
+#ifndef _ALLBSD_SOURCE
+ void *p = mmap (NULL, page_size, PROT_READ|PROT_WRITE,
+ MAP_ANONYMOUS|MAP_PRIVATE|MAP_HUGETLB,
+ -1, 0);
+
+ if (p != (void *) -1) {
+ // We don't know if this really is a huge page or not.
+ FILE *fp = fopen("/proc/self/maps", "r");
+ if (fp) {
+ while (!feof(fp)) {
+ char chars[257];
+ long x = 0;
+ if (fgets(chars, sizeof(chars), fp)) {
+ if (sscanf(chars, "%lx-%*x", &x) == 1
+ && x == (long)p) {
+ if (strstr (chars, "hugepage")) {
+ result = true;
+ break;
+ }
+ }
+ }
+ }
+ fclose(fp);
+ }
+ munmap (p, page_size);
+ if (result)
+ return true;
+ }
+
+ if (warn) {
+ warning("HugeTLBFS is not supported by the operating system.");
+ }
+#endif
+
+ return result;
+}
+
+/*
+* Set the coredump_filter bits to include largepages in core dump (bit 6)
+*
+* From the coredump_filter documentation:
+*
+* - (bit 0) anonymous private memory
+* - (bit 1) anonymous shared memory
+* - (bit 2) file-backed private memory
+* - (bit 3) file-backed shared memory
+* - (bit 4) ELF header pages in file-backed private memory areas (it is
+* effective only if the bit 2 is cleared)
+* - (bit 5) hugetlb private memory
+* - (bit 6) hugetlb shared memory
+*/
+static void set_coredump_filter(void) {
+ FILE *f;
+ long cdm;
+
+ if ((f = fopen("/proc/self/coredump_filter", "r+")) == NULL) {
+ return;
+ }
+
+ if (fscanf(f, "%lx", &cdm) != 1) {
+ fclose(f);
+ return;
+ }
+
+ rewind(f);
+
+ if ((cdm & LARGEPAGES_BIT) == 0) {
+ cdm |= LARGEPAGES_BIT;
+ fprintf(f, "%#lx", cdm);
+ }
+
+ fclose(f);
+}
+
+// Large page support
+
+static size_t _large_page_size = 0;
+
+void os::large_page_init() {
+#ifndef _ALLBSD_SOURCE
+ if (!UseLargePages) {
+ UseHugeTLBFS = false;
+ UseSHM = false;
+ return;
+ }
+
+ if (FLAG_IS_DEFAULT(UseHugeTLBFS) && FLAG_IS_DEFAULT(UseSHM)) {
+ // If UseLargePages is specified on the command line try both methods,
+ // if it's default, then try only HugeTLBFS.
+ if (FLAG_IS_DEFAULT(UseLargePages)) {
+ UseHugeTLBFS = true;
+ } else {
+ UseHugeTLBFS = UseSHM = true;
+ }
+ }
+
+ if (LargePageSizeInBytes) {
+ _large_page_size = LargePageSizeInBytes;
+ } else {
+ // large_page_size on Bsd is used to round up heap size. x86 uses either
+ // 2M or 4M page, depending on whether PAE (Physical Address Extensions)
+ // mode is enabled. AMD64/EM64T uses 2M page in 64bit mode. IA64 can use
+ // page as large as 256M.
+ //
+ // Here we try to figure out page size by parsing /proc/meminfo and looking
+ // for a line with the following format:
+ // Hugepagesize: 2048 kB
+ //
+ // If we can't determine the value (e.g. /proc is not mounted, or the text
+ // format has been changed), we'll use the largest page size supported by
+ // the processor.
+
+#ifndef ZERO
+ _large_page_size = IA32_ONLY(4 * M) AMD64_ONLY(2 * M) IA64_ONLY(256 * M) SPARC_ONLY(4 * M)
+ ARM_ONLY(2 * M) PPC_ONLY(4 * M);
+#endif // ZERO
+
+ FILE *fp = fopen("/proc/meminfo", "r");
+ if (fp) {
+ while (!feof(fp)) {
+ int x = 0;
+ char buf[16];
+ if (fscanf(fp, "Hugepagesize: %d", &x) == 1) {
+ if (x && fgets(buf, sizeof(buf), fp) && strcmp(buf, " kB\n") == 0) {
+ _large_page_size = x * K;
+ break;
+ }
+ } else {
+ // skip to next line
+ for (;;) {
+ int ch = fgetc(fp);
+ if (ch == EOF || ch == (int)'\n') break;
+ }
+ }
+ }
+ fclose(fp);
+ }
+ }
+
+ // print a warning if any large page related flag is specified on command line
+ bool warn_on_failure = !FLAG_IS_DEFAULT(UseHugeTLBFS);
+
+ const size_t default_page_size = (size_t)Bsd::page_size();
+ if (_large_page_size > default_page_size) {
+ _page_sizes[0] = _large_page_size;
+ _page_sizes[1] = default_page_size;
+ _page_sizes[2] = 0;
+ }
+ UseHugeTLBFS = UseHugeTLBFS &&
+ Bsd::hugetlbfs_sanity_check(warn_on_failure, _large_page_size);
+
+ if (UseHugeTLBFS)
+ UseSHM = false;
+
+ UseLargePages = UseHugeTLBFS || UseSHM;
+
+ set_coredump_filter();
+#endif
+}
+
+#ifndef _ALLBSD_SOURCE
+#ifndef SHM_HUGETLB
+#define SHM_HUGETLB 04000
+#endif
+#endif
+
+char* os::reserve_memory_special(size_t bytes, char* req_addr, bool exec) {
+ // "exec" is passed in but not used. Creating the shared image for
+ // the code cache doesn't have an SHM_X executable permission to check.
+ assert(UseLargePages && UseSHM, "only for SHM large pages");
+
+ key_t key = IPC_PRIVATE;
+ char *addr;
+
+ bool warn_on_failure = UseLargePages &&
+ (!FLAG_IS_DEFAULT(UseLargePages) ||
+ !FLAG_IS_DEFAULT(LargePageSizeInBytes)
+ );
+ char msg[128];
+
+ // Create a large shared memory region to attach to based on size.
+ // Currently, size is the total size of the heap
+#ifndef _ALLBSD_SOURCE
+ int shmid = shmget(key, bytes, SHM_HUGETLB|IPC_CREAT|SHM_R|SHM_W);
+#else
+ int shmid = shmget(key, bytes, IPC_CREAT|SHM_R|SHM_W);
+#endif
+ if (shmid == -1) {
+ // Possible reasons for shmget failure:
+ // 1. shmmax is too small for Java heap.
+ // > check shmmax value: cat /proc/sys/kernel/shmmax
+ // > increase shmmax value: echo "0xffffffff" > /proc/sys/kernel/shmmax
+ // 2. not enough large page memory.
+ // > check available large pages: cat /proc/meminfo
+ // > increase amount of large pages:
+ // echo new_value > /proc/sys/vm/nr_hugepages
+ // Note 1: different Bsd may use different name for this property,
+ // e.g. on Redhat AS-3 it is "hugetlb_pool".
+ // Note 2: it's possible there's enough physical memory available but
+ // they are so fragmented after a long run that they can't
+ // coalesce into large pages. Try to reserve large pages when
+ // the system is still "fresh".
+ if (warn_on_failure) {
+ jio_snprintf(msg, sizeof(msg), "Failed to reserve shared memory (errno = %d).", errno);
+ warning(msg);
+ }
+ return NULL;
+ }
+
+ // attach to the region
+ addr = (char*)shmat(shmid, req_addr, 0);
+ int err = errno;
+
+ // Remove shmid. If shmat() is successful, the actual shared memory segment
+ // will be deleted when it's detached by shmdt() or when the process
+ // terminates. If shmat() is not successful this will remove the shared
+ // segment immediately.
+ shmctl(shmid, IPC_RMID, NULL);
+
+ if ((intptr_t)addr == -1) {
+ if (warn_on_failure) {
+ jio_snprintf(msg, sizeof(msg), "Failed to attach shared memory (errno = %d).", err);
+ warning(msg);
+ }
+ return NULL;
+ }
+
+ return addr;
+}
+
+bool os::release_memory_special(char* base, size_t bytes) {
+ // detaching the SHM segment will also delete it, see reserve_memory_special()
+ int rslt = shmdt(base);
+ return rslt == 0;
+}
+
+size_t os::large_page_size() {
+ return _large_page_size;
+}
+
+// HugeTLBFS allows application to commit large page memory on demand;
+// with SysV SHM the entire memory region must be allocated as shared
+// memory.
+bool os::can_commit_large_page_memory() {
+ return UseHugeTLBFS;
+}
+
+bool os::can_execute_large_page_memory() {
+ return UseHugeTLBFS;
+}
+
+// Reserve memory at an arbitrary address, only if that area is
+// available (and not reserved for something else).
+
+char* os::attempt_reserve_memory_at(size_t bytes, char* requested_addr) {
+ const int max_tries = 10;
+ char* base[max_tries];
+ size_t size[max_tries];
+ const size_t gap = 0x000000;
+
+ // Assert only that the size is a multiple of the page size, since
+ // that's all that mmap requires, and since that's all we really know
+ // about at this low abstraction level. If we need higher alignment,
+ // we can either pass an alignment to this method or verify alignment
+ // in one of the methods further up the call chain. See bug 5044738.
+ assert(bytes % os::vm_page_size() == 0, "reserving unexpected size block");
+
+ // Repeatedly allocate blocks until the block is allocated at the
+ // right spot. Give up after max_tries. Note that reserve_memory() will
+ // automatically update _highest_vm_reserved_address if the call is
+ // successful. The variable tracks the highest memory address every reserved
+ // by JVM. It is used to detect heap-stack collision if running with
+ // fixed-stack BsdThreads. Because here we may attempt to reserve more
+ // space than needed, it could confuse the collision detecting code. To
+ // solve the problem, save current _highest_vm_reserved_address and
+ // calculate the correct value before return.
+ address old_highest = _highest_vm_reserved_address;
+
+ // Bsd mmap allows caller to pass an address as hint; give it a try first,
+ // if kernel honors the hint then we can return immediately.
+ char * addr = anon_mmap(requested_addr, bytes, false);
+ if (addr == requested_addr) {
+ return requested_addr;
+ }
+
+ if (addr != NULL) {
+ // mmap() is successful but it fails to reserve at the requested address
+ anon_munmap(addr, bytes);
+ }
+
+ int i;
+ for (i = 0; i < max_tries; ++i) {
+ base[i] = reserve_memory(bytes);
+
+ if (base[i] != NULL) {
+ // Is this the block we wanted?
+ if (base[i] == requested_addr) {
+ size[i] = bytes;
+ break;
+ }
+
+ // Does this overlap the block we wanted? Give back the overlapped
+ // parts and try again.
+
+ size_t top_overlap = requested_addr + (bytes + gap) - base[i];
+ if (top_overlap >= 0 && top_overlap < bytes) {
+ unmap_memory(base[i], top_overlap);
+ base[i] += top_overlap;
+ size[i] = bytes - top_overlap;
+ } else {
+ size_t bottom_overlap = base[i] + bytes - requested_addr;
+ if (bottom_overlap >= 0 && bottom_overlap < bytes) {
+ unmap_memory(requested_addr, bottom_overlap);
+ size[i] = bytes - bottom_overlap;
+ } else {
+ size[i] = bytes;
+ }
+ }
+ }
+ }
+
+ // Give back the unused reserved pieces.
+
+ for (int j = 0; j < i; ++j) {
+ if (base[j] != NULL) {
+ unmap_memory(base[j], size[j]);
+ }
+ }
+
+ if (i < max_tries) {
+ _highest_vm_reserved_address = MAX2(old_highest, (address)requested_addr + bytes);
+ return requested_addr;
+ } else {
+ _highest_vm_reserved_address = old_highest;
+ return NULL;
+ }
+}
+
+size_t os::read(int fd, void *buf, unsigned int nBytes) {
+ RESTARTABLE_RETURN_INT(::read(fd, buf, nBytes));
+}
+
+// TODO-FIXME: reconcile Solaris' os::sleep with the bsd variation.
+// Solaris uses poll(), bsd uses park().
+// Poll() is likely a better choice, assuming that Thread.interrupt()
+// generates a SIGUSRx signal. Note that SIGUSR1 can interfere with
+// SIGSEGV, see 4355769.
+
+const int NANOSECS_PER_MILLISECS = 1000000;
+
+int os::sleep(Thread* thread, jlong millis, bool interruptible) {
+ assert(thread == Thread::current(), "thread consistency check");
+
+ ParkEvent * const slp = thread->_SleepEvent ;
+ slp->reset() ;
+ OrderAccess::fence() ;
+
+ if (interruptible) {
+ jlong prevtime = javaTimeNanos();
+
+ for (;;) {
+ if (os::is_interrupted(thread, true)) {
+ return OS_INTRPT;
+ }
+
+ jlong newtime = javaTimeNanos();
+
+ if (newtime - prevtime < 0) {
+ // time moving backwards, should only happen if no monotonic clock
+ // not a guarantee() because JVM should not abort on kernel/glibc bugs
+ assert(!Bsd::supports_monotonic_clock(), "time moving backwards");
+ } else {
+ millis -= (newtime - prevtime) / NANOSECS_PER_MILLISECS;
+ }
+
+ if(millis <= 0) {
+ return OS_OK;
+ }
+
+ prevtime = newtime;
+
+ {
+ assert(thread->is_Java_thread(), "sanity check");
+ JavaThread *jt = (JavaThread *) thread;
+ ThreadBlockInVM tbivm(jt);
+ OSThreadWaitState osts(jt->osthread(), false /* not Object.wait() */);
+
+ jt->set_suspend_equivalent();
+ // cleared by handle_special_suspend_equivalent_condition() or
+ // java_suspend_self() via check_and_wait_while_suspended()
+
+ slp->park(millis);
+
+ // were we externally suspended while we were waiting?
+ jt->check_and_wait_while_suspended();
+ }
+ }
+ } else {
+ OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */);
+ jlong prevtime = javaTimeNanos();
+
+ for (;;) {
+ // It'd be nice to avoid the back-to-back javaTimeNanos() calls on
+ // the 1st iteration ...
+ jlong newtime = javaTimeNanos();
+
+ if (newtime - prevtime < 0) {
+ // time moving backwards, should only happen if no monotonic clock
+ // not a guarantee() because JVM should not abort on kernel/glibc bugs
+ assert(!Bsd::supports_monotonic_clock(), "time moving backwards");
+ } else {
+ millis -= (newtime - prevtime) / NANOSECS_PER_MILLISECS;
+ }
+
+ if(millis <= 0) break ;
+
+ prevtime = newtime;
+ slp->park(millis);
+ }
+ return OS_OK ;
+ }
+}
+
+int os::naked_sleep() {
+ // %% make the sleep time an integer flag. for now use 1 millisec.
+ return os::sleep(Thread::current(), 1, false);
+}
+
+// Sleep forever; naked call to OS-specific sleep; use with CAUTION
+void os::infinite_sleep() {
+ while (true) { // sleep forever ...
+ ::sleep(100); // ... 100 seconds at a time
+ }
+}
+
+// Used to convert frequent JVM_Yield() to nops
+bool os::dont_yield() {
+ return DontYieldALot;
+}
+
+void os::yield() {
+ sched_yield();
+}
+
+os::YieldResult os::NakedYield() { sched_yield(); return os::YIELD_UNKNOWN ;}
+
+void os::yield_all(int attempts) {
+ // Yields to all threads, including threads with lower priorities
+ // Threads on Bsd are all with same priority. The Solaris style
+ // os::yield_all() with nanosleep(1ms) is not necessary.
+ sched_yield();
+}
+
+// Called from the tight loops to possibly influence time-sharing heuristics
+void os::loop_breaker(int attempts) {
+ os::yield_all(attempts);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// thread priority support
+
+// Note: Normal Bsd applications are run with SCHED_OTHER policy. SCHED_OTHER
+// only supports dynamic priority, static priority must be zero. For real-time
+// applications, Bsd supports SCHED_RR which allows static priority (1-99).
+// However, for large multi-threaded applications, SCHED_RR is not only slower
+// than SCHED_OTHER, but also very unstable (my volano tests hang hard 4 out
+// of 5 runs - Sep 2005).
+//
+// The following code actually changes the niceness of kernel-thread/LWP. It
+// has an assumption that setpriority() only modifies one kernel-thread/LWP,
+// not the entire user process, and user level threads are 1:1 mapped to kernel
+// threads. It has always been the case, but could change in the future. For
+// this reason, the code should not be used as default (ThreadPriorityPolicy=0).
+// It is only used when ThreadPriorityPolicy=1 and requires root privilege.
+
+#if defined(_ALLBSD_SOURCE) && !defined(__APPLE__)
+int os::java_to_os_priority[MaxPriority + 1] = {
+ 19, // 0 Entry should never be used
+
+ 0, // 1 MinPriority
+ 3, // 2
+ 6, // 3
+
+ 10, // 4
+ 15, // 5 NormPriority
+ 18, // 6
+
+ 21, // 7
+ 25, // 8
+ 28, // 9 NearMaxPriority
+
+ 31 // 10 MaxPriority
+};
+#elif defined(__APPLE__)
+/* Using Mach high-level priority assignments */
+int os::java_to_os_priority[MaxPriority + 1] = {
+ 0, // 0 Entry should never be used (MINPRI_USER)
+
+ 27, // 1 MinPriority
+ 28, // 2
+ 29, // 3
+
+ 30, // 4
+ 31, // 5 NormPriority (BASEPRI_DEFAULT)
+ 32, // 6
+
+ 33, // 7
+ 34, // 8
+ 35, // 9 NearMaxPriority
+
+ 36 // 10 MaxPriority
+};
+#else
+int os::java_to_os_priority[MaxPriority + 1] = {
+ 19, // 0 Entry should never be used
+
+ 4, // 1 MinPriority
+ 3, // 2
+ 2, // 3
+
+ 1, // 4
+ 0, // 5 NormPriority
+ -1, // 6
+
+ -2, // 7
+ -3, // 8
+ -4, // 9 NearMaxPriority
+
+ -5 // 10 MaxPriority
+};
+#endif
+
+static int prio_init() {
+ if (ThreadPriorityPolicy == 1) {
+ // Only root can raise thread priority. Don't allow ThreadPriorityPolicy=1
+ // if effective uid is not root. Perhaps, a more elegant way of doing
+ // this is to test CAP_SYS_NICE capability, but that will require libcap.so
+ if (geteuid() != 0) {
+ if (!FLAG_IS_DEFAULT(ThreadPriorityPolicy)) {
+ warning("-XX:ThreadPriorityPolicy requires root privilege on Bsd");
+ }
+ ThreadPriorityPolicy = 0;
+ }
+ }
+ return 0;
+}
+
+OSReturn os::set_native_priority(Thread* thread, int newpri) {
+ if ( !UseThreadPriorities || ThreadPriorityPolicy == 0 ) return OS_OK;
+
+#ifdef __OpenBSD__
+ // OpenBSD pthread_setprio starves low priority threads
+ return OS_OK;
+#elif defined(__FreeBSD__)
+ int ret = pthread_setprio(thread->osthread()->pthread_id(), newpri);
+#elif defined(__APPLE__) || defined(__NetBSD__)
+ struct sched_param sp;
+ int policy;
+ pthread_t self = pthread_self();
+
+ if (pthread_getschedparam(self, &policy, &sp) != 0)
+ return OS_ERR;
+
+ sp.sched_priority = newpri;
+ if (pthread_setschedparam(self, policy, &sp) != 0)
+ return OS_ERR;
+
+ return OS_OK;
+#else
+ int ret = setpriority(PRIO_PROCESS, thread->osthread()->thread_id(), newpri);
+ return (ret == 0) ? OS_OK : OS_ERR;
+#endif
+}
+
+OSReturn os::get_native_priority(const Thread* const thread, int *priority_ptr) {
+ if ( !UseThreadPriorities || ThreadPriorityPolicy == 0 ) {
+ *priority_ptr = java_to_os_priority[NormPriority];
+ return OS_OK;
+ }
+
+ errno = 0;
+#if defined(__OpenBSD__) || defined(__FreeBSD__)
+ *priority_ptr = pthread_getprio(thread->osthread()->pthread_id());
+#elif defined(__APPLE__) || defined(__NetBSD__)
+ int policy;
+ struct sched_param sp;
+
+ pthread_getschedparam(pthread_self(), &policy, &sp);
+ *priority_ptr = sp.sched_priority;
+#else
+ *priority_ptr = getpriority(PRIO_PROCESS, thread->osthread()->thread_id());
+#endif
+ return (*priority_ptr != -1 || errno == 0 ? OS_OK : OS_ERR);
+}
+
+// Hint to the underlying OS that a task switch would not be good.
+// Void return because it's a hint and can fail.
+void os::hint_no_preempt() {}
+
+////////////////////////////////////////////////////////////////////////////////
+// suspend/resume support
+
+// the low-level signal-based suspend/resume support is a remnant from the
+// old VM-suspension that used to be for java-suspension, safepoints etc,
+// within hotspot. Now there is a single use-case for this:
+// - calling get_thread_pc() on the VMThread by the flat-profiler task
+// that runs in the watcher thread.
+// The remaining code is greatly simplified from the more general suspension
+// code that used to be used.
+//
+// The protocol is quite simple:
+// - suspend:
+// - sends a signal to the target thread
+// - polls the suspend state of the osthread using a yield loop
+// - target thread signal handler (SR_handler) sets suspend state
+// and blocks in sigsuspend until continued
+// - resume:
+// - sets target osthread state to continue
+// - sends signal to end the sigsuspend loop in the SR_handler
+//
+// Note that the SR_lock plays no role in this suspend/resume protocol.
+//
+
+static void resume_clear_context(OSThread *osthread) {
+ osthread->set_ucontext(NULL);
+ osthread->set_siginfo(NULL);
+
+ // notify the suspend action is completed, we have now resumed
+ osthread->sr.clear_suspended();
+}
+
+static void suspend_save_context(OSThread *osthread, siginfo_t* siginfo, ucontext_t* context) {
+ osthread->set_ucontext(context);
+ osthread->set_siginfo(siginfo);
+}
+
+//
+// Handler function invoked when a thread's execution is suspended or
+// resumed. We have to be careful that only async-safe functions are
+// called here (Note: most pthread functions are not async safe and
+// should be avoided.)
+//
+// Note: sigwait() is a more natural fit than sigsuspend() from an
+// interface point of view, but sigwait() prevents the signal hander
+// from being run. libpthread would get very confused by not having
+// its signal handlers run and prevents sigwait()'s use with the
+// mutex granting granting signal.
+//
+// Currently only ever called on the VMThread
+//
+static void SR_handler(int sig, siginfo_t* siginfo, ucontext_t* context) {
+ // Save and restore errno to avoid confusing native code with EINTR
+ // after sigsuspend.
+ int old_errno = errno;
+
+ Thread* thread = Thread::current();
+ OSThread* osthread = thread->osthread();
+ assert(thread->is_VM_thread(), "Must be VMThread");
+ // read current suspend action
+ int action = osthread->sr.suspend_action();
+ if (action == SR_SUSPEND) {
+ suspend_save_context(osthread, siginfo, context);
+
+ // Notify the suspend action is about to be completed. do_suspend()
+ // waits until SR_SUSPENDED is set and then returns. We will wait
+ // here for a resume signal and that completes the suspend-other
+ // action. do_suspend/do_resume is always called as a pair from
+ // the same thread - so there are no races
+
+ // notify the caller
+ osthread->sr.set_suspended();
+
+ sigset_t suspend_set; // signals for sigsuspend()
+
+ // get current set of blocked signals and unblock resume signal
+ pthread_sigmask(SIG_BLOCK, NULL, &suspend_set);
+ sigdelset(&suspend_set, SR_signum);
+
+ // wait here until we are resumed
+ do {
+ sigsuspend(&suspend_set);
+ // ignore all returns until we get a resume signal
+ } while (osthread->sr.suspend_action() != SR_CONTINUE);
+
+ resume_clear_context(osthread);
+
+ } else {
+ assert(action == SR_CONTINUE, "unexpected sr action");
+ // nothing special to do - just leave the handler
+ }
+
+ errno = old_errno;
+}
+
+
+static int SR_initialize() {
+ struct sigaction act;
+ char *s;
+ /* Get signal number to use for suspend/resume */
+ if ((s = ::getenv("_JAVA_SR_SIGNUM")) != 0) {
+ int sig = ::strtol(s, 0, 10);
+ if (sig > 0 || sig < NSIG) {
+ SR_signum = sig;
+ }
+ }
+
+ assert(SR_signum > SIGSEGV && SR_signum > SIGBUS,
+ "SR_signum must be greater than max(SIGSEGV, SIGBUS), see 4355769");
+
+ sigemptyset(&SR_sigset);
+ sigaddset(&SR_sigset, SR_signum);
+
+ /* Set up signal handler for suspend/resume */
+ act.sa_flags = SA_RESTART|SA_SIGINFO;
+ act.sa_handler = (void (*)(int)) SR_handler;
+
+ // SR_signum is blocked by default.
+ // 4528190 - We also need to block pthread restart signal (32 on all
+ // supported Bsd platforms). Note that BsdThreads need to block
+ // this signal for all threads to work properly. So we don't have
+ // to use hard-coded signal number when setting up the mask.
+ pthread_sigmask(SIG_BLOCK, NULL, &act.sa_mask);
+
+ if (sigaction(SR_signum, &act, 0) == -1) {
+ return -1;
+ }
+
+ // Save signal flag
+ os::Bsd::set_our_sigflags(SR_signum, act.sa_flags);
+ return 0;
+}
+
+static int SR_finalize() {
+ return 0;
+}
+
+
+// returns true on success and false on error - really an error is fatal
+// but this seems the normal response to library errors
+static bool do_suspend(OSThread* osthread) {
+ // mark as suspended and send signal
+ osthread->sr.set_suspend_action(SR_SUSPEND);
+ int status = pthread_kill(osthread->pthread_id(), SR_signum);
+ assert_status(status == 0, status, "pthread_kill");
+
+ // check status and wait until notified of suspension
+ if (status == 0) {
+ for (int i = 0; !osthread->sr.is_suspended(); i++) {
+ os::yield_all(i);
+ }
+ osthread->sr.set_suspend_action(SR_NONE);
+ return true;
+ }
+ else {
+ osthread->sr.set_suspend_action(SR_NONE);
+ return false;
+ }
+}
+
+static void do_resume(OSThread* osthread) {
+ assert(osthread->sr.is_suspended(), "thread should be suspended");
+ osthread->sr.set_suspend_action(SR_CONTINUE);
+
+ int status = pthread_kill(osthread->pthread_id(), SR_signum);
+ assert_status(status == 0, status, "pthread_kill");
+ // check status and wait unit notified of resumption
+ if (status == 0) {
+ for (int i = 0; osthread->sr.is_suspended(); i++) {
+ os::yield_all(i);
+ }
+ }
+ osthread->sr.set_suspend_action(SR_NONE);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// interrupt support
+
+void os::interrupt(Thread* thread) {
+ assert(Thread::current() == thread || Threads_lock->owned_by_self(),
+ "possibility of dangling Thread pointer");
+
+ OSThread* osthread = thread->osthread();
+
+ if (!osthread->interrupted()) {
+ osthread->set_interrupted(true);
+ // More than one thread can get here with the same value of osthread,
+ // resulting in multiple notifications. We do, however, want the store
+ // to interrupted() to be visible to other threads before we execute unpark().
+ OrderAccess::fence();
+ ParkEvent * const slp = thread->_SleepEvent ;
+ if (slp != NULL) slp->unpark() ;
+ }
+
+ // For JSR166. Unpark even if interrupt status already was set
+ if (thread->is_Java_thread())
+ ((JavaThread*)thread)->parker()->unpark();
+
+ ParkEvent * ev = thread->_ParkEvent ;
+ if (ev != NULL) ev->unpark() ;
+
+}
+
+bool os::is_interrupted(Thread* thread, bool clear_interrupted) {
+ assert(Thread::current() == thread || Threads_lock->owned_by_self(),
+ "possibility of dangling Thread pointer");
+
+ OSThread* osthread = thread->osthread();
+
+ bool interrupted = osthread->interrupted();
+
+ if (interrupted && clear_interrupted) {
+ osthread->set_interrupted(false);
+ // consider thread->_SleepEvent->reset() ... optional optimization
+ }
+
+ return interrupted;
+}
+
+///////////////////////////////////////////////////////////////////////////////////
+// signal handling (except suspend/resume)
+
+// This routine may be used by user applications as a "hook" to catch signals.
+// The user-defined signal handler must pass unrecognized signals to this
+// routine, and if it returns true (non-zero), then the signal handler must
+// return immediately. If the flag "abort_if_unrecognized" is true, then this
+// routine will never retun false (zero), but instead will execute a VM panic
+// routine kill the process.
+//
+// If this routine returns false, it is OK to call it again. This allows
+// the user-defined signal handler to perform checks either before or after
+// the VM performs its own checks. Naturally, the user code would be making
+// a serious error if it tried to handle an exception (such as a null check
+// or breakpoint) that the VM was generating for its own correct operation.
+//
+// This routine may recognize any of the following kinds of signals:
+// SIGBUS, SIGSEGV, SIGILL, SIGFPE, SIGQUIT, SIGPIPE, SIGXFSZ, SIGUSR1.
+// It should be consulted by handlers for any of those signals.
+//
+// The caller of this routine must pass in the three arguments supplied
+// to the function referred to in the "sa_sigaction" (not the "sa_handler")
+// field of the structure passed to sigaction(). This routine assumes that
+// the sa_flags field passed to sigaction() includes SA_SIGINFO and SA_RESTART.
+//
+// Note that the VM will print warnings if it detects conflicting signal
+// handlers, unless invoked with the option "-XX:+AllowUserSignalHandlers".
+//
+extern "C" JNIEXPORT int
+JVM_handle_bsd_signal(int signo, siginfo_t* siginfo,
+ void* ucontext, int abort_if_unrecognized);
+
+void signalHandler(int sig, siginfo_t* info, void* uc) {
+ assert(info != NULL && uc != NULL, "it must be old kernel");
+ JVM_handle_bsd_signal(sig, info, uc, true);
+}
+
+
+// This boolean allows users to forward their own non-matching signals
+// to JVM_handle_bsd_signal, harmlessly.
+bool os::Bsd::signal_handlers_are_installed = false;
+
+// For signal-chaining
+struct sigaction os::Bsd::sigact[MAXSIGNUM];
+unsigned int os::Bsd::sigs = 0;
+bool os::Bsd::libjsig_is_loaded = false;
+typedef struct sigaction *(*get_signal_t)(int);
+get_signal_t os::Bsd::get_signal_action = NULL;
+
+struct sigaction* os::Bsd::get_chained_signal_action(int sig) {
+ struct sigaction *actp = NULL;
+
+ if (libjsig_is_loaded) {
+ // Retrieve the old signal handler from libjsig
+ actp = (*get_signal_action)(sig);
+ }
+ if (actp == NULL) {
+ // Retrieve the preinstalled signal handler from jvm
+ actp = get_preinstalled_handler(sig);
+ }
+
+ return actp;
+}
+
+static bool call_chained_handler(struct sigaction *actp, int sig,
+ siginfo_t *siginfo, void *context) {
+ // Call the old signal handler
+ if (actp->sa_handler == SIG_DFL) {
+ // It's more reasonable to let jvm treat it as an unexpected exception
+ // instead of taking the default action.
+ return false;
+ } else if (actp->sa_handler != SIG_IGN) {
+ if ((actp->sa_flags & SA_NODEFER) == 0) {
+ // automaticlly block the signal
+ sigaddset(&(actp->sa_mask), sig);
+ }
+
+ sa_handler_t hand;
+ sa_sigaction_t sa;
+ bool siginfo_flag_set = (actp->sa_flags & SA_SIGINFO) != 0;
+ // retrieve the chained handler
+ if (siginfo_flag_set) {
+ sa = actp->sa_sigaction;
+ } else {
+ hand = actp->sa_handler;
+ }
+
+ if ((actp->sa_flags & SA_RESETHAND) != 0) {
+ actp->sa_handler = SIG_DFL;
+ }
+
+ // try to honor the signal mask
+ sigset_t oset;
+ pthread_sigmask(SIG_SETMASK, &(actp->sa_mask), &oset);
+
+ // call into the chained handler
+ if (siginfo_flag_set) {
+ (*sa)(sig, siginfo, context);
+ } else {
+ (*hand)(sig);
+ }
+
+ // restore the signal mask
+ pthread_sigmask(SIG_SETMASK, &oset, 0);
+ }
+ // Tell jvm's signal handler the signal is taken care of.
+ return true;
+}
+
+bool os::Bsd::chained_handler(int sig, siginfo_t* siginfo, void* context) {
+ bool chained = false;
+ // signal-chaining
+ if (UseSignalChaining) {
+ struct sigaction *actp = get_chained_signal_action(sig);
+ if (actp != NULL) {
+ chained = call_chained_handler(actp, sig, siginfo, context);
+ }
+ }
+ return chained;
+}
+
+struct sigaction* os::Bsd::get_preinstalled_handler(int sig) {
+ if ((( (unsigned int)1 << sig ) & sigs) != 0) {
+ return &sigact[sig];
+ }
+ return NULL;
+}
+
+void os::Bsd::save_preinstalled_handler(int sig, struct sigaction& oldAct) {
+ assert(sig > 0 && sig < MAXSIGNUM, "vm signal out of expected range");
+ sigact[sig] = oldAct;
+ sigs |= (unsigned int)1 << sig;
+}
+
+// for diagnostic
+int os::Bsd::sigflags[MAXSIGNUM];
+
+int os::Bsd::get_our_sigflags(int sig) {
+ assert(sig > 0 && sig < MAXSIGNUM, "vm signal out of expected range");
+ return sigflags[sig];
+}
+
+void os::Bsd::set_our_sigflags(int sig, int flags) {
+ assert(sig > 0 && sig < MAXSIGNUM, "vm signal out of expected range");
+ sigflags[sig] = flags;
+}
+
+void os::Bsd::set_signal_handler(int sig, bool set_installed) {
+ // Check for overwrite.
+ struct sigaction oldAct;
+ sigaction(sig, (struct sigaction*)NULL, &oldAct);
+
+ void* oldhand = oldAct.sa_sigaction
+ ? CAST_FROM_FN_PTR(void*, oldAct.sa_sigaction)
+ : CAST_FROM_FN_PTR(void*, oldAct.sa_handler);
+ if (oldhand != CAST_FROM_FN_PTR(void*, SIG_DFL) &&
+ oldhand != CAST_FROM_FN_PTR(void*, SIG_IGN) &&
+ oldhand != CAST_FROM_FN_PTR(void*, (sa_sigaction_t)signalHandler)) {
+ if (AllowUserSignalHandlers || !set_installed) {
+ // Do not overwrite; user takes responsibility to forward to us.
+ return;
+ } else if (UseSignalChaining) {
+ // save the old handler in jvm
+ save_preinstalled_handler(sig, oldAct);
+ // libjsig also interposes the sigaction() call below and saves the
+ // old sigaction on it own.
+ } else {
+ fatal(err_msg("Encountered unexpected pre-existing sigaction handler "
+ "%#lx for signal %d.", (long)oldhand, sig));
+ }
+ }
+
+ struct sigaction sigAct;
+ sigfillset(&(sigAct.sa_mask));
+ sigAct.sa_handler = SIG_DFL;
+ if (!set_installed) {
+ sigAct.sa_flags = SA_SIGINFO|SA_RESTART;
+ } else {
+ sigAct.sa_sigaction = signalHandler;
+ sigAct.sa_flags = SA_SIGINFO|SA_RESTART;
+ }
+ // Save flags, which are set by ours
+ assert(sig > 0 && sig < MAXSIGNUM, "vm signal out of expected range");
+ sigflags[sig] = sigAct.sa_flags;
+
+ int ret = sigaction(sig, &sigAct, &oldAct);
+ assert(ret == 0, "check");
+
+ void* oldhand2 = oldAct.sa_sigaction
+ ? CAST_FROM_FN_PTR(void*, oldAct.sa_sigaction)
+ : CAST_FROM_FN_PTR(void*, oldAct.sa_handler);
+ assert(oldhand2 == oldhand, "no concurrent signal handler installation");
+}
+
+// install signal handlers for signals that HotSpot needs to
+// handle in order to support Java-level exception handling.
+
+void os::Bsd::install_signal_handlers() {
+ if (!signal_handlers_are_installed) {
+ signal_handlers_are_installed = true;
+
+ // signal-chaining
+ typedef void (*signal_setting_t)();
+ signal_setting_t begin_signal_setting = NULL;
+ signal_setting_t end_signal_setting = NULL;
+ begin_signal_setting = CAST_TO_FN_PTR(signal_setting_t,
+ dlsym(RTLD_DEFAULT, "JVM_begin_signal_setting"));
+ if (begin_signal_setting != NULL) {
+ end_signal_setting = CAST_TO_FN_PTR(signal_setting_t,
+ dlsym(RTLD_DEFAULT, "JVM_end_signal_setting"));
+ get_signal_action = CAST_TO_FN_PTR(get_signal_t,
+ dlsym(RTLD_DEFAULT, "JVM_get_signal_action"));
+ libjsig_is_loaded = true;
+ assert(UseSignalChaining, "should enable signal-chaining");
+ }
+ if (libjsig_is_loaded) {
+ // Tell libjsig jvm is setting signal handlers
+ (*begin_signal_setting)();
+ }
+
+ set_signal_handler(SIGSEGV, true);
+ set_signal_handler(SIGPIPE, true);
+ set_signal_handler(SIGBUS, true);
+ set_signal_handler(SIGILL, true);
+ set_signal_handler(SIGFPE, true);
+ set_signal_handler(SIGXFSZ, true);
+
+#if defined(__APPLE__)
+ // In Mac OS X 10.4, CrashReporter will write a crash log for all 'fatal' signals, including
+ // signals caught and handled by the JVM. To work around this, we reset the mach task
+ // signal handler that's placed on our process by CrashReporter. This disables
+ // CrashReporter-based reporting.
+ //
+ // This work-around is not necessary for 10.5+, as CrashReporter no longer intercedes
+ // on caught fatal signals.
+ //
+ // Additionally, gdb installs both standard BSD signal handlers, and mach exception
+ // handlers. By replacing the existing task exception handler, we disable gdb's mach
+ // exception handling, while leaving the standard BSD signal handlers functional.
+ kern_return_t kr;
+ kr = task_set_exception_ports(mach_task_self(),
+ EXC_MASK_BAD_ACCESS | EXC_MASK_ARITHMETIC,
+ MACH_PORT_NULL,
+ EXCEPTION_STATE_IDENTITY,
+ MACHINE_THREAD_STATE);
+
+ assert(kr == KERN_SUCCESS, "could not set mach task signal handler");
+#endif
+
+ if (libjsig_is_loaded) {
+ // Tell libjsig jvm finishes setting signal handlers
+ (*end_signal_setting)();
+ }
+
+ // We don't activate signal checker if libjsig is in place, we trust ourselves
+ // and if UserSignalHandler is installed all bets are off
+ if (CheckJNICalls) {
+ if (libjsig_is_loaded) {
+ tty->print_cr("Info: libjsig is activated, all active signal checking is disabled");
+ check_signals = false;
+ }
+ if (AllowUserSignalHandlers) {
+ tty->print_cr("Info: AllowUserSignalHandlers is activated, all active signal checking is disabled");
+ check_signals = false;
+ }
+ }
+ }
+}
+
+#ifndef _ALLBSD_SOURCE
+// This is the fastest way to get thread cpu time on Bsd.
+// Returns cpu time (user+sys) for any thread, not only for current.
+// POSIX compliant clocks are implemented in the kernels 2.6.16+.
+// It might work on 2.6.10+ with a special kernel/glibc patch.
+// For reference, please, see IEEE Std 1003.1-2004:
+// http://www.unix.org/single_unix_specification
+
+jlong os::Bsd::fast_thread_cpu_time(clockid_t clockid) {
+ struct timespec tp;
+ int rc = os::Bsd::clock_gettime(clockid, &tp);
+ assert(rc == 0, "clock_gettime is expected to return 0 code");
+
+ return (tp.tv_sec * SEC_IN_NANOSECS) + tp.tv_nsec;
+}
+#endif
+
+/////
+// glibc on Bsd platform uses non-documented flag
+// to indicate, that some special sort of signal
+// trampoline is used.
+// We will never set this flag, and we should
+// ignore this flag in our diagnostic
+#ifdef SIGNIFICANT_SIGNAL_MASK
+#undef SIGNIFICANT_SIGNAL_MASK
+#endif
+#define SIGNIFICANT_SIGNAL_MASK (~0x04000000)
+
+static const char* get_signal_handler_name(address handler,
+ char* buf, int buflen) {
+ int offset;
+ bool found = os::dll_address_to_library_name(handler, buf, buflen, &offset);
+ if (found) {
+ // skip directory names
+ const char *p1, *p2;
+ p1 = buf;
+ size_t len = strlen(os::file_separator());
+ while ((p2 = strstr(p1, os::file_separator())) != NULL) p1 = p2 + len;
+ jio_snprintf(buf, buflen, "%s+0x%x", p1, offset);
+ } else {
+ jio_snprintf(buf, buflen, PTR_FORMAT, handler);
+ }
+ return buf;
+}
+
+static void print_signal_handler(outputStream* st, int sig,
+ char* buf, size_t buflen) {
+ struct sigaction sa;
+
+ sigaction(sig, NULL, &sa);
+
+ // See comment for SIGNIFICANT_SIGNAL_MASK define
+ sa.sa_flags &= SIGNIFICANT_SIGNAL_MASK;
+
+ st->print("%s: ", os::exception_name(sig, buf, buflen));
+
+ address handler = (sa.sa_flags & SA_SIGINFO)
+ ? CAST_FROM_FN_PTR(address, sa.sa_sigaction)
+ : CAST_FROM_FN_PTR(address, sa.sa_handler);
+
+ if (handler == CAST_FROM_FN_PTR(address, SIG_DFL)) {
+ st->print("SIG_DFL");
+ } else if (handler == CAST_FROM_FN_PTR(address, SIG_IGN)) {
+ st->print("SIG_IGN");
+ } else {
+ st->print("[%s]", get_signal_handler_name(handler, buf, buflen));
+ }
+
+ st->print(", sa_mask[0]=" PTR32_FORMAT, *(uint32_t*)&sa.sa_mask);
+
+ address rh = VMError::get_resetted_sighandler(sig);
+ // May be, handler was resetted by VMError?
+ if(rh != NULL) {
+ handler = rh;
+ sa.sa_flags = VMError::get_resetted_sigflags(sig) & SIGNIFICANT_SIGNAL_MASK;
+ }
+
+ st->print(", sa_flags=" PTR32_FORMAT, sa.sa_flags);
+
+ // Check: is it our handler?
+ if(handler == CAST_FROM_FN_PTR(address, (sa_sigaction_t)signalHandler) ||
+ handler == CAST_FROM_FN_PTR(address, (sa_sigaction_t)SR_handler)) {
+ // It is our signal handler
+ // check for flags, reset system-used one!
+ if((int)sa.sa_flags != os::Bsd::get_our_sigflags(sig)) {
+ st->print(
+ ", flags was changed from " PTR32_FORMAT ", consider using jsig library",
+ os::Bsd::get_our_sigflags(sig));
+ }
+ }
+ st->cr();
+}
+
+
+#define DO_SIGNAL_CHECK(sig) \
+ if (!sigismember(&check_signal_done, sig)) \
+ os::Bsd::check_signal_handler(sig)
+
+// This method is a periodic task to check for misbehaving JNI applications
+// under CheckJNI, we can add any periodic checks here
+
+void os::run_periodic_checks() {
+
+ if (check_signals == false) return;
+
+ // SEGV and BUS if overridden could potentially prevent
+ // generation of hs*.log in the event of a crash, debugging
+ // such a case can be very challenging, so we absolutely
+ // check the following for a good measure:
+ DO_SIGNAL_CHECK(SIGSEGV);
+ DO_SIGNAL_CHECK(SIGILL);
+ DO_SIGNAL_CHECK(SIGFPE);
+ DO_SIGNAL_CHECK(SIGBUS);
+ DO_SIGNAL_CHECK(SIGPIPE);
+ DO_SIGNAL_CHECK(SIGXFSZ);
+
+
+ // ReduceSignalUsage allows the user to override these handlers
+ // see comments at the very top and jvm_solaris.h
+ if (!ReduceSignalUsage) {
+ DO_SIGNAL_CHECK(SHUTDOWN1_SIGNAL);
+ DO_SIGNAL_CHECK(SHUTDOWN2_SIGNAL);
+ DO_SIGNAL_CHECK(SHUTDOWN3_SIGNAL);
+ DO_SIGNAL_CHECK(BREAK_SIGNAL);
+ }
+
+ DO_SIGNAL_CHECK(SR_signum);
+ DO_SIGNAL_CHECK(INTERRUPT_SIGNAL);
+}
+
+typedef int (*os_sigaction_t)(int, const struct sigaction *, struct sigaction *);
+
+static os_sigaction_t os_sigaction = NULL;
+
+void os::Bsd::check_signal_handler(int sig) {
+ char buf[O_BUFLEN];
+ address jvmHandler = NULL;
+
+
+ struct sigaction act;
+ if (os_sigaction == NULL) {
+ // only trust the default sigaction, in case it has been interposed
+ os_sigaction = (os_sigaction_t)dlsym(RTLD_DEFAULT, "sigaction");
+ if (os_sigaction == NULL) return;
+ }
+
+ os_sigaction(sig, (struct sigaction*)NULL, &act);
+
+
+ act.sa_flags &= SIGNIFICANT_SIGNAL_MASK;
+
+ address thisHandler = (act.sa_flags & SA_SIGINFO)
+ ? CAST_FROM_FN_PTR(address, act.sa_sigaction)
+ : CAST_FROM_FN_PTR(address, act.sa_handler) ;
+
+
+ switch(sig) {
+ case SIGSEGV:
+ case SIGBUS:
+ case SIGFPE:
+ case SIGPIPE:
+ case SIGILL:
+ case SIGXFSZ:
+ jvmHandler = CAST_FROM_FN_PTR(address, (sa_sigaction_t)signalHandler);
+ break;
+
+ case SHUTDOWN1_SIGNAL:
+ case SHUTDOWN2_SIGNAL:
+ case SHUTDOWN3_SIGNAL:
+ case BREAK_SIGNAL:
+ jvmHandler = (address)user_handler();
+ break;
+
+ case INTERRUPT_SIGNAL:
+ jvmHandler = CAST_FROM_FN_PTR(address, SIG_DFL);
+ break;
+
+ default:
+ if (sig == SR_signum) {
+ jvmHandler = CAST_FROM_FN_PTR(address, (sa_sigaction_t)SR_handler);
+ } else {
+ return;
+ }
+ break;
+ }
+
+ if (thisHandler != jvmHandler) {
+ tty->print("Warning: %s handler ", exception_name(sig, buf, O_BUFLEN));
+ tty->print("expected:%s", get_signal_handler_name(jvmHandler, buf, O_BUFLEN));
+ tty->print_cr(" found:%s", get_signal_handler_name(thisHandler, buf, O_BUFLEN));
+ // No need to check this sig any longer
+ sigaddset(&check_signal_done, sig);
+ } else if(os::Bsd::get_our_sigflags(sig) != 0 && (int)act.sa_flags != os::Bsd::get_our_sigflags(sig)) {
+ tty->print("Warning: %s handler flags ", exception_name(sig, buf, O_BUFLEN));
+ tty->print("expected:" PTR32_FORMAT, os::Bsd::get_our_sigflags(sig));
+ tty->print_cr(" found:" PTR32_FORMAT, act.sa_flags);
+ // No need to check this sig any longer
+ sigaddset(&check_signal_done, sig);
+ }
+
+ // Dump all the signal
+ if (sigismember(&check_signal_done, sig)) {
+ print_signal_handlers(tty, buf, O_BUFLEN);
+ }
+}
+
+extern void report_error(char* file_name, int line_no, char* title, char* format, ...);
+
+extern bool signal_name(int signo, char* buf, size_t len);
+
+const char* os::exception_name(int exception_code, char* buf, size_t size) {
+ if (0 < exception_code && exception_code <= SIGRTMAX) {
+ // signal
+ if (!signal_name(exception_code, buf, size)) {
+ jio_snprintf(buf, size, "SIG%d", exception_code);
+ }
+ return buf;
+ } else {
+ return NULL;
+ }
+}
+
+// this is called _before_ the most of global arguments have been parsed
+void os::init(void) {
+ char dummy; /* used to get a guess on initial stack address */
+// first_hrtime = gethrtime();
+
+ // With BsdThreads the JavaMain thread pid (primordial thread)
+ // is different than the pid of the java launcher thread.
+ // So, on Bsd, the launcher thread pid is passed to the VM
+ // via the sun.java.launcher.pid property.
+ // Use this property instead of getpid() if it was correctly passed.
+ // See bug 6351349.
+ pid_t java_launcher_pid = (pid_t) Arguments::sun_java_launcher_pid();
+
+ _initial_pid = (java_launcher_pid > 0) ? java_launcher_pid : getpid();
+
+ clock_tics_per_sec = CLK_TCK;
+
+ init_random(1234567);
+
+ ThreadCritical::initialize();
+
+ Bsd::set_page_size(getpagesize());
+ if (Bsd::page_size() == -1) {
+ fatal(err_msg("os_bsd.cpp: os::init: sysconf failed (%s)",
+ strerror(errno)));
+ }
+ init_page_sizes((size_t) Bsd::page_size());
+
+ Bsd::initialize_system_info();
+
+ // main_thread points to the aboriginal thread
+ Bsd::_main_thread = pthread_self();
+
+ Bsd::clock_init();
+ initial_time_count = os::elapsed_counter();
+
+#ifdef __APPLE__
+ // XXXDARWIN
+ // Work around the unaligned VM callbacks in hotspot's
+ // sharedRuntime. The callbacks don't use SSE2 instructions, and work on
+ // Linux, Solaris, and FreeBSD. On Mac OS X, dyld (rightly so) enforces
+ // alignment when doing symbol lookup. To work around this, we force early
+ // binding of all symbols now, thus binding when alignment is known-good.
+ _dyld_bind_fully_image_containing_address((const void *) &os::init);
+#endif
+}
+
+// To install functions for atexit system call
+extern "C" {
+ static void perfMemory_exit_helper() {
+ perfMemory_exit();
+ }
+}
+
+// this is called _after_ the global arguments have been parsed
+jint os::init_2(void)
+{
+#ifndef _ALLBSD_SOURCE
+ Bsd::fast_thread_clock_init();
+#endif
+
+ // Allocate a single page and mark it as readable for safepoint polling
+ address polling_page = (address) ::mmap(NULL, Bsd::page_size(), PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+ guarantee( polling_page != MAP_FAILED, "os::init_2: failed to allocate polling page" );
+
+ os::set_polling_page( polling_page );
+
+#ifndef PRODUCT
+ if(Verbose && PrintMiscellaneous)
+ tty->print("[SafePoint Polling address: " INTPTR_FORMAT "]\n", (intptr_t)polling_page);
+#endif
+
+ if (!UseMembar) {
+ address mem_serialize_page = (address) ::mmap(NULL, Bsd::page_size(), PROT_READ | PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+ guarantee( mem_serialize_page != NULL, "mmap Failed for memory serialize page");
+ os::set_memory_serialize_page( mem_serialize_page );
+
+#ifndef PRODUCT
+ if(Verbose && PrintMiscellaneous)
+ tty->print("[Memory Serialize Page address: " INTPTR_FORMAT "]\n", (intptr_t)mem_serialize_page);
+#endif
+ }
+
+ os::large_page_init();
+
+ // initialize suspend/resume support - must do this before signal_sets_init()
+ if (SR_initialize() != 0) {
+ perror("SR_initialize failed");
+ return JNI_ERR;
+ }
+
+ Bsd::signal_sets_init();
+ Bsd::install_signal_handlers();
+
+ // Check minimum allowable stack size for thread creation and to initialize
+ // the java system classes, including StackOverflowError - depends on page
+ // size. Add a page for compiler2 recursion in main thread.
+ // Add in 2*BytesPerWord times page size to account for VM stack during
+ // class initialization depending on 32 or 64 bit VM.
+ os::Bsd::min_stack_allowed = MAX2(os::Bsd::min_stack_allowed,
+ (size_t)(StackYellowPages+StackRedPages+StackShadowPages+
+ 2*BytesPerWord COMPILER2_PRESENT(+1)) * Bsd::page_size());
+
+ size_t threadStackSizeInBytes = ThreadStackSize * K;
+ if (threadStackSizeInBytes != 0 &&
+ threadStackSizeInBytes < os::Bsd::min_stack_allowed) {
+ tty->print_cr("\nThe stack size specified is too small, "
+ "Specify at least %dk",
+ os::Bsd::min_stack_allowed/ K);
+ return JNI_ERR;
+ }
+
+ // Make the stack size a multiple of the page size so that
+ // the yellow/red zones can be guarded.
+ JavaThread::set_stack_size_at_create(round_to(threadStackSizeInBytes,
+ vm_page_size()));
+
+#ifndef _ALLBSD_SOURCE
+ Bsd::capture_initial_stack(JavaThread::stack_size_at_create());
+
+ Bsd::libpthread_init();
+ if (PrintMiscellaneous && (Verbose || WizardMode)) {
+ tty->print_cr("[HotSpot is running with %s, %s(%s)]\n",
+ Bsd::glibc_version(), Bsd::libpthread_version(),
+ Bsd::is_floating_stack() ? "floating stack" : "fixed stack");
+ }
+
+ if (UseNUMA) {
+ if (!Bsd::libnuma_init()) {
+ UseNUMA = false;
+ } else {
+ if ((Bsd::numa_max_node() < 1)) {
+ // There's only one node(they start from 0), disable NUMA.
+ UseNUMA = false;
+ }
+ }
+ // With SHM large pages we cannot uncommit a page, so there's not way
+ // we can make the adaptive lgrp chunk resizing work. If the user specified
+ // both UseNUMA and UseLargePages (or UseSHM) on the command line - warn and
+ // disable adaptive resizing.
+ if (UseNUMA && UseLargePages && UseSHM) {
+ if (!FLAG_IS_DEFAULT(UseNUMA)) {
+ if (FLAG_IS_DEFAULT(UseLargePages) && FLAG_IS_DEFAULT(UseSHM)) {
+ UseLargePages = false;
+ } else {
+ warning("UseNUMA is not fully compatible with SHM large pages, disabling adaptive resizing");
+ UseAdaptiveSizePolicy = false;
+ UseAdaptiveNUMAChunkSizing = false;
+ }
+ } else {
+ UseNUMA = false;
+ }
+ }
+ if (!UseNUMA && ForceNUMA) {
+ UseNUMA = true;
+ }
+ }
+#endif
+
+ if (MaxFDLimit) {
+ // set the number of file descriptors to max. print out error
+ // if getrlimit/setrlimit fails but continue regardless.
+ struct rlimit nbr_files;
+ int status = getrlimit(RLIMIT_NOFILE, &nbr_files);
+ if (status != 0) {
+ if (PrintMiscellaneous && (Verbose || WizardMode))
+ perror("os::init_2 getrlimit failed");
+ } else {
+ nbr_files.rlim_cur = nbr_files.rlim_max;
+
+#ifdef __APPLE__
+ // Darwin returns RLIM_INFINITY for rlim_max, but fails with EINVAL if
+ // you attempt to use RLIM_INFINITY. As per setrlimit(2), OPEN_MAX must
+ // be used instead
+ nbr_files.rlim_cur = MIN(OPEN_MAX, nbr_files.rlim_cur);
+#endif
+
+ status = setrlimit(RLIMIT_NOFILE, &nbr_files);
+ if (status != 0) {
+ if (PrintMiscellaneous && (Verbose || WizardMode))
+ perror("os::init_2 setrlimit failed");
+ }
+ }
+ }
+
+#ifndef _ALLBSD_SOURCE
+ // Initialize lock used to serialize thread creation (see os::create_thread)
+ Bsd::set_createThread_lock(new Mutex(Mutex::leaf, "createThread_lock", false));
+#endif
+
+ // at-exit methods are called in the reverse order of their registration.
+ // atexit functions are called on return from main or as a result of a
+ // call to exit(3C). There can be only 32 of these functions registered
+ // and atexit() does not set errno.
+
+ if (PerfAllowAtExitRegistration) {
+ // only register atexit functions if PerfAllowAtExitRegistration is set.
+ // atexit functions can be delayed until process exit time, which
+ // can be problematic for embedded VM situations. Embedded VMs should
+ // call DestroyJavaVM() to assure that VM resources are released.
+
+ // note: perfMemory_exit_helper atexit function may be removed in
+ // the future if the appropriate cleanup code can be added to the
+ // VM_Exit VMOperation's doit method.
+ if (atexit(perfMemory_exit_helper) != 0) {
+ warning("os::init2 atexit(perfMemory_exit_helper) failed");
+ }
+ }
+
+ // initialize thread priority policy
+ prio_init();
+
+ return JNI_OK;
+}
+
+// this is called at the end of vm_initialization
+void os::init_3(void) { }
+
+// Mark the polling page as unreadable
+void os::make_polling_page_unreadable(void) {
+ if( !guard_memory((char*)_polling_page, Bsd::page_size()) )
+ fatal("Could not disable polling page");
+};
+
+// Mark the polling page as readable
+void os::make_polling_page_readable(void) {
+ if( !bsd_mprotect((char *)_polling_page, Bsd::page_size(), PROT_READ)) {
+ fatal("Could not enable polling page");
+ }
+};
+
+int os::active_processor_count() {
+#ifdef _ALLBSD_SOURCE
+ return _processor_count;
+#else
+ // Bsd doesn't yet have a (official) notion of processor sets,
+ // so just return the number of online processors.
+ int online_cpus = ::sysconf(_SC_NPROCESSORS_ONLN);
+ assert(online_cpus > 0 && online_cpus <= processor_count(), "sanity check");
+ return online_cpus;
+#endif
+}
+
+bool os::distribute_processes(uint length, uint* distribution) {
+ // Not yet implemented.
+ return false;
+}
+
+bool os::bind_to_processor(uint processor_id) {
+ // Not yet implemented.
+ return false;
+}
+
+///
+
+// Suspends the target using the signal mechanism and then grabs the PC before
+// resuming the target. Used by the flat-profiler only
+ExtendedPC os::get_thread_pc(Thread* thread) {
+ // Make sure that it is called by the watcher for the VMThread
+ assert(Thread::current()->is_Watcher_thread(), "Must be watcher");
+ assert(thread->is_VM_thread(), "Can only be called for VMThread");
+
+ ExtendedPC epc;
+
+ OSThread* osthread = thread->osthread();
+ if (do_suspend(osthread)) {
+ if (osthread->ucontext() != NULL) {
+ epc = os::Bsd::ucontext_get_pc(osthread->ucontext());
+ } else {
+ // NULL context is unexpected, double-check this is the VMThread
+ guarantee(thread->is_VM_thread(), "can only be called for VMThread");
+ }
+ do_resume(osthread);
+ }
+ // failure means pthread_kill failed for some reason - arguably this is
+ // a fatal problem, but such problems are ignored elsewhere
+
+ return epc;
+}
+
+int os::Bsd::safe_cond_timedwait(pthread_cond_t *_cond, pthread_mutex_t *_mutex, const struct timespec *_abstime)
+{
+#ifdef _ALLBSD_SOURCE
+ return pthread_cond_timedwait(_cond, _mutex, _abstime);
+#else
+ if (is_NPTL()) {
+ return pthread_cond_timedwait(_cond, _mutex, _abstime);
+ } else {
+#ifndef IA64
+ // 6292965: BsdThreads pthread_cond_timedwait() resets FPU control
+ // word back to default 64bit precision if condvar is signaled. Java
+ // wants 53bit precision. Save and restore current value.
+ int fpu = get_fpu_control_word();
+#endif // IA64
+ int status = pthread_cond_timedwait(_cond, _mutex, _abstime);
+#ifndef IA64
+ set_fpu_control_word(fpu);
+#endif // IA64
+ return status;
+ }
+#endif
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// debug support
+
+static address same_page(address x, address y) {
+ int page_bits = -os::vm_page_size();
+ if ((intptr_t(x) & page_bits) == (intptr_t(y) & page_bits))
+ return x;
+ else if (x > y)
+ return (address)(intptr_t(y) | ~page_bits) + 1;
+ else
+ return (address)(intptr_t(y) & page_bits);
+}
+
+bool os::find(address addr, outputStream* st) {
+ Dl_info dlinfo;
+ memset(&dlinfo, 0, sizeof(dlinfo));
+ if (dladdr(addr, &dlinfo)) {
+ st->print(PTR_FORMAT ": ", addr);
+ if (dlinfo.dli_sname != NULL) {
+ st->print("%s+%#x", dlinfo.dli_sname,
+ addr - (intptr_t)dlinfo.dli_saddr);
+ } else if (dlinfo.dli_fname) {
+ st->print("<offset %#x>", addr - (intptr_t)dlinfo.dli_fbase);
+ } else {
+ st->print("<absolute address>");
+ }
+ if (dlinfo.dli_fname) {
+ st->print(" in %s", dlinfo.dli_fname);
+ }
+ if (dlinfo.dli_fbase) {
+ st->print(" at " PTR_FORMAT, dlinfo.dli_fbase);
+ }
+ st->cr();
+
+ if (Verbose) {
+ // decode some bytes around the PC
+ address begin = same_page(addr-40, addr);
+ address end = same_page(addr+40, addr);
+ address lowest = (address) dlinfo.dli_sname;
+ if (!lowest) lowest = (address) dlinfo.dli_fbase;
+ if (begin < lowest) begin = lowest;
+ Dl_info dlinfo2;
+ if (dladdr(end, &dlinfo2) && dlinfo2.dli_saddr != dlinfo.dli_saddr
+ && end > dlinfo2.dli_saddr && dlinfo2.dli_saddr > begin)
+ end = (address) dlinfo2.dli_saddr;
+ Disassembler::decode(begin, end, st);
+ }
+ return true;
+ }
+ return false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// misc
+
+// This does not do anything on Bsd. This is basically a hook for being
+// able to use structured exception handling (thread-local exception filters)
+// on, e.g., Win32.
+void
+os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method,
+ JavaCallArguments* args, Thread* thread) {
+ f(value, method, args, thread);
+}
+
+void os::print_statistics() {
+}
+
+int os::message_box(const char* title, const char* message) {
+ int i;
+ fdStream err(defaultStream::error_fd());
+ for (i = 0; i < 78; i++) err.print_raw("=");
+ err.cr();
+ err.print_raw_cr(title);
+ for (i = 0; i < 78; i++) err.print_raw("-");
+ err.cr();
+ err.print_raw_cr(message);
+ for (i = 0; i < 78; i++) err.print_raw("=");
+ err.cr();
+
+ char buf[16];
+ // Prevent process from exiting upon "read error" without consuming all CPU
+ while (::read(0, buf, sizeof(buf)) <= 0) { ::sleep(100); }
+
+ return buf[0] == 'y' || buf[0] == 'Y';
+}
+
+int os::stat(const char *path, struct stat *sbuf) {
+ char pathbuf[MAX_PATH];
+ if (strlen(path) > MAX_PATH - 1) {
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+ os::native_path(strcpy(pathbuf, path));
+ return ::stat(pathbuf, sbuf);
+}
+
+bool os::check_heap(bool force) {
+ return true;
+}
+
+int local_vsnprintf(char* buf, size_t count, const char* format, va_list args) {
+ return ::vsnprintf(buf, count, format, args);
+}
+
+// Is a (classpath) directory empty?
+bool os::dir_is_empty(const char* path) {
+ DIR *dir = NULL;
+ struct dirent *ptr;
+
+ dir = opendir(path);
+ if (dir == NULL) return true;
+
+ /* Scan the directory */
+ bool result = true;
+ char buf[sizeof(struct dirent) + MAX_PATH];
+ while (result && (ptr = ::readdir(dir)) != NULL) {
+ if (strcmp(ptr->d_name, ".") != 0 && strcmp(ptr->d_name, "..") != 0) {
+ result = false;
+ }
+ }
+ closedir(dir);
+ return result;
+}
+
+// This code originates from JDK's sysOpen and open64_w
+// from src/solaris/hpi/src/system_md.c
+
+#ifndef O_DELETE
+#define O_DELETE 0x10000
+#endif
+
+// Open a file. Unlink the file immediately after open returns
+// if the specified oflag has the O_DELETE flag set.
+// O_DELETE is used only in j2se/src/share/native/java/util/zip/ZipFile.c
+
+int os::open(const char *path, int oflag, int mode) {
+
+ if (strlen(path) > MAX_PATH - 1) {
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+ int fd;
+ int o_delete = (oflag & O_DELETE);
+ oflag = oflag & ~O_DELETE;
+
+ fd = ::open(path, oflag, mode);
+ if (fd == -1) return -1;
+
+ //If the open succeeded, the file might still be a directory
+ {
+ struct stat buf;
+ int ret = ::fstat(fd, &buf);
+ int st_mode = buf.st_mode;
+
+ if (ret != -1) {
+ if ((st_mode & S_IFMT) == S_IFDIR) {
+ errno = EISDIR;
+ ::close(fd);
+ return -1;
+ }
+ } else {
+ ::close(fd);
+ return -1;
+ }
+ }
+
+ /*
+ * 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
+
+ if (o_delete != 0) {
+ ::unlink(path);
+ }
+ return fd;
+}
+
+
+// create binary file, rewriting existing file if required
+int os::create_binary_file(const char* path, bool rewrite_existing) {
+ int oflags = O_WRONLY | O_CREAT;
+ if (!rewrite_existing) {
+ oflags |= O_EXCL;
+ }
+ return ::open(path, oflags, S_IREAD | S_IWRITE);
+}
+
+// return current position of file pointer
+jlong os::current_file_offset(int fd) {
+ return (jlong)::lseek(fd, (off_t)0, SEEK_CUR);
+}
+
+// move file pointer to the specified offset
+jlong os::seek_to_file_offset(int fd, jlong offset) {
+ return (jlong)::lseek(fd, (off_t)offset, SEEK_SET);
+}
+
+// This code originates from JDK's sysAvailable
+// from src/solaris/hpi/src/native_threads/src/sys_api_td.c
+
+int os::available(int fd, jlong *bytes) {
+ jlong cur, end;
+ int mode;
+ struct stat buf;
+
+ if (::fstat(fd, &buf) >= 0) {
+ mode = buf.st_mode;
+ 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) {
+ *bytes = n;
+ return 1;
+ }
+ }
+ }
+ if ((cur = ::lseek(fd, 0L, SEEK_CUR)) == -1) {
+ return 0;
+ } else if ((end = ::lseek(fd, 0L, SEEK_END)) == -1) {
+ return 0;
+ } else if (::lseek(fd, cur, SEEK_SET) == -1) {
+ return 0;
+ }
+ *bytes = end - cur;
+ return 1;
+}
+
+int os::socket_available(int fd, jint *pbytes) {
+ if (fd < 0)
+ return OS_OK;
+
+ int ret;
+
+ RESTARTABLE(::ioctl(fd, FIONREAD, pbytes), ret);
+
+ //%% note ioctl can return 0 when successful, JVM_SocketAvailable
+ // is expected to return 0 on failure and 1 on success to the jdk.
+
+ return (ret == OS_ERR) ? 0 : 1;
+}
+
+// Map a block of memory.
+char* os::map_memory(int fd, const char* file_name, size_t file_offset,
+ char *addr, size_t bytes, bool read_only,
+ bool allow_exec) {
+ int prot;
+ int flags;
+
+ if (read_only) {
+ prot = PROT_READ;
+ flags = MAP_SHARED;
+ } else {
+ prot = PROT_READ | PROT_WRITE;
+ flags = MAP_PRIVATE;
+ }
+
+ if (allow_exec) {
+ prot |= PROT_EXEC;
+ }
+
+ if (addr != NULL) {
+ flags |= MAP_FIXED;
+ }
+
+ char* mapped_address = (char*)mmap(addr, (size_t)bytes, prot, flags,
+ fd, file_offset);
+ if (mapped_address == MAP_FAILED) {
+ return NULL;
+ }
+ return mapped_address;
+}
+
+
+// Remap a block of memory.
+char* os::remap_memory(int fd, const char* file_name, size_t file_offset,
+ char *addr, size_t bytes, bool read_only,
+ bool allow_exec) {
+ // same as map_memory() on this OS
+ return os::map_memory(fd, file_name, file_offset, addr, bytes, read_only,
+ allow_exec);
+}
+
+
+// Unmap a block of memory.
+bool os::unmap_memory(char* addr, size_t bytes) {
+ return munmap(addr, bytes) == 0;
+}
+
+#ifndef _ALLBSD_SOURCE
+static jlong slow_thread_cpu_time(Thread *thread, bool user_sys_cpu_time);
+
+static clockid_t thread_cpu_clockid(Thread* thread) {
+ pthread_t tid = thread->osthread()->pthread_id();
+ clockid_t clockid;
+
+ // Get thread clockid
+ int rc = os::Bsd::pthread_getcpuclockid(tid, &clockid);
+ assert(rc == 0, "pthread_getcpuclockid is expected to return 0 code");
+ return clockid;
+}
+#endif
+
+// current_thread_cpu_time(bool) and thread_cpu_time(Thread*, bool)
+// are used by JVM M&M and JVMTI to get user+sys or user CPU time
+// of a thread.
+//
+// current_thread_cpu_time() and thread_cpu_time(Thread*) returns
+// the fast estimate available on the platform.
+
+jlong os::current_thread_cpu_time() {
+#ifdef __APPLE__
+ return os::thread_cpu_time(Thread::current(), true /* user + sys */);
+#elif !defined(_ALLBSD_SOURCE)
+ if (os::Bsd::supports_fast_thread_cpu_time()) {
+ return os::Bsd::fast_thread_cpu_time(CLOCK_THREAD_CPUTIME_ID);
+ } else {
+ // return user + sys since the cost is the same
+ return slow_thread_cpu_time(Thread::current(), true /* user + sys */);
+ }
+#endif
+}
+
+jlong os::thread_cpu_time(Thread* thread) {
+#ifndef _ALLBSD_SOURCE
+ // consistent with what current_thread_cpu_time() returns
+ if (os::Bsd::supports_fast_thread_cpu_time()) {
+ return os::Bsd::fast_thread_cpu_time(thread_cpu_clockid(thread));
+ } else {
+ return slow_thread_cpu_time(thread, true /* user + sys */);
+ }
+#endif
+}
+
+jlong os::current_thread_cpu_time(bool user_sys_cpu_time) {
+#ifdef __APPLE__
+ return os::thread_cpu_time(Thread::current(), user_sys_cpu_time);
+#elif !defined(_ALLBSD_SOURCE)
+ if (user_sys_cpu_time && os::Bsd::supports_fast_thread_cpu_time()) {
+ return os::Bsd::fast_thread_cpu_time(CLOCK_THREAD_CPUTIME_ID);
+ } else {
+ return slow_thread_cpu_time(Thread::current(), user_sys_cpu_time);
+ }
+#endif
+}
+
+jlong os::thread_cpu_time(Thread *thread, bool user_sys_cpu_time) {
+#ifdef __APPLE__
+ struct thread_basic_info tinfo;
+ mach_msg_type_number_t tcount = THREAD_INFO_MAX;
+ kern_return_t kr;
+ mach_port_t mach_thread;
+
+ mach_thread = pthread_mach_thread_np(thread->osthread()->thread_id());
+ kr = thread_info(mach_thread, THREAD_BASIC_INFO, (thread_info_t)&tinfo, &tcount);
+ if (kr != KERN_SUCCESS)
+ return -1;
+
+ if (user_sys_cpu_time) {
+ jlong nanos;
+ nanos = ((jlong) tinfo.system_time.seconds + tinfo.user_time.seconds) * (jlong)1000000000;
+ nanos += ((jlong) tinfo.system_time.microseconds + (jlong) tinfo.user_time.microseconds) * (jlong)1000;
+ return nanos;
+ } else {
+ return ((jlong)tinfo.user_time.seconds * 1000000000) + ((jlong)tinfo.user_time.microseconds * (jlong)1000);
+ }
+#elif !defined(_ALLBSD_SOURCE)
+ if (user_sys_cpu_time && os::Bsd::supports_fast_thread_cpu_time()) {
+ return os::Bsd::fast_thread_cpu_time(thread_cpu_clockid(thread));
+ } else {
+ return slow_thread_cpu_time(thread, user_sys_cpu_time);
+ }
+#endif
+}
+
+#ifndef _ALLBSD_SOURCE
+//
+// -1 on error.
+//
+
+static jlong slow_thread_cpu_time(Thread *thread, bool user_sys_cpu_time) {
+ static bool proc_pid_cpu_avail = true;
+ static bool proc_task_unchecked = true;
+ static const char *proc_stat_path = "/proc/%d/stat";
+ pid_t tid = thread->osthread()->thread_id();
+ int i;
+ char *s;
+ char stat[2048];
+ int statlen;
+ char proc_name[64];
+ int count;
+ long sys_time, user_time;
+ char string[64];
+ char cdummy;
+ int idummy;
+ long ldummy;
+ FILE *fp;
+
+ // We first try accessing /proc/<pid>/cpu since this is faster to
+ // process. If this file is not present (bsd kernels 2.5 and above)
+ // then we open /proc/<pid>/stat.
+ if ( proc_pid_cpu_avail ) {
+ sprintf(proc_name, "/proc/%d/cpu", tid);
+ fp = fopen(proc_name, "r");
+ if ( fp != NULL ) {
+ count = fscanf( fp, "%s %lu %lu\n", string, &user_time, &sys_time);
+ fclose(fp);
+ if ( count != 3 ) return -1;
+
+ if (user_sys_cpu_time) {
+ return ((jlong)sys_time + (jlong)user_time) * (1000000000 / clock_tics_per_sec);
+ } else {
+ return (jlong)user_time * (1000000000 / clock_tics_per_sec);
+ }
+ }
+ else proc_pid_cpu_avail = false;
+ }
+
+ // The /proc/<tid>/stat aggregates per-process usage on
+ // new Bsd kernels 2.6+ where NPTL is supported.
+ // The /proc/self/task/<tid>/stat still has the per-thread usage.
+ // See bug 6328462.
+ // There can be no directory /proc/self/task on kernels 2.4 with NPTL
+ // and possibly in some other cases, so we check its availability.
+ if (proc_task_unchecked && os::Bsd::is_NPTL()) {
+ // This is executed only once
+ proc_task_unchecked = false;
+ fp = fopen("/proc/self/task", "r");
+ if (fp != NULL) {
+ proc_stat_path = "/proc/self/task/%d/stat";
+ fclose(fp);
+ }
+ }
+
+ sprintf(proc_name, proc_stat_path, tid);
+ fp = fopen(proc_name, "r");
+ if ( fp == NULL ) return -1;
+ statlen = fread(stat, 1, 2047, fp);
+ stat[statlen] = '\0';
+ fclose(fp);
+
+ // Skip pid and the command string. Note that we could be dealing with
+ // weird command names, e.g. user could decide to rename java launcher
+ // to "java 1.4.2 :)", then the stat file would look like
+ // 1234 (java 1.4.2 :)) R ... ...
+ // We don't really need to know the command string, just find the last
+ // occurrence of ")" and then start parsing from there. See bug 4726580.
+ s = strrchr(stat, ')');
+ i = 0;
+ if (s == NULL ) return -1;
+
+ // Skip blank chars
+ do s++; while (isspace(*s));
+
+ count = sscanf(s,"%c %d %d %d %d %d %lu %lu %lu %lu %lu %lu %lu",
+ &cdummy, &idummy, &idummy, &idummy, &idummy, &idummy,
+ &ldummy, &ldummy, &ldummy, &ldummy, &ldummy,
+ &user_time, &sys_time);
+ if ( count != 13 ) return -1;
+ if (user_sys_cpu_time) {
+ return ((jlong)sys_time + (jlong)user_time) * (1000000000 / clock_tics_per_sec);
+ } else {
+ return (jlong)user_time * (1000000000 / clock_tics_per_sec);
+ }
+}
+#endif
+
+void os::current_thread_cpu_time_info(jvmtiTimerInfo *info_ptr) {
+ info_ptr->max_value = ALL_64_BITS; // will not wrap in less than 64 bits
+ info_ptr->may_skip_backward = false; // elapsed time not wall time
+ info_ptr->may_skip_forward = false; // elapsed time not wall time
+ info_ptr->kind = JVMTI_TIMER_TOTAL_CPU; // user+system time is returned
+}
+
+void os::thread_cpu_time_info(jvmtiTimerInfo *info_ptr) {
+ info_ptr->max_value = ALL_64_BITS; // will not wrap in less than 64 bits
+ info_ptr->may_skip_backward = false; // elapsed time not wall time
+ info_ptr->may_skip_forward = false; // elapsed time not wall time
+ info_ptr->kind = JVMTI_TIMER_TOTAL_CPU; // user+system time is returned
+}
+
+bool os::is_thread_cpu_time_supported() {
+#ifdef __APPLE__
+ return true;
+#elif defined(_ALLBSD_SOURCE)
+ return false;
+#else
+ return true;
+#endif
+}
+
+// System loadavg support. Returns -1 if load average cannot be obtained.
+// Bsd doesn't yet have a (official) notion of processor sets,
+// so just return the system wide load average.
+int os::loadavg(double loadavg[], int nelem) {
+ return ::getloadavg(loadavg, nelem);
+}
+
+void os::pause() {
+ char filename[MAX_PATH];
+ if (PauseAtStartupFile && PauseAtStartupFile[0]) {
+ jio_snprintf(filename, MAX_PATH, PauseAtStartupFile);
+ } else {
+ jio_snprintf(filename, MAX_PATH, "./vm.paused.%d", current_process_id());
+ }
+
+ int fd = ::open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+ if (fd != -1) {
+ struct stat buf;
+ ::close(fd);
+ while (::stat(filename, &buf) == 0) {
+ (void)::poll(NULL, 0, 100);
+ }
+ } else {
+ jio_fprintf(stderr,
+ "Could not open pause file '%s', continuing immediately.\n", filename);
+ }
+}
+
+
+// Refer to the comments in os_solaris.cpp park-unpark.
+//
+// Beware -- Some versions of NPTL embody a flaw where pthread_cond_timedwait() can
+// hang indefinitely. For instance NPTL 0.60 on 2.4.21-4ELsmp is vulnerable.
+// For specifics regarding the bug see GLIBC BUGID 261237 :
+// http://www.mail-archive.com/debian-glibc@lists.debian.org/msg10837.html.
+// Briefly, pthread_cond_timedwait() calls with an expiry time that's not in the future
+// will either hang or corrupt the condvar, resulting in subsequent hangs if the condvar
+// is used. (The simple C test-case provided in the GLIBC bug report manifests the
+// hang). The JVM is vulernable via sleep(), Object.wait(timo), LockSupport.parkNanos()
+// and monitorenter when we're using 1-0 locking. All those operations may result in
+// calls to pthread_cond_timedwait(). Using LD_ASSUME_KERNEL to use an older version
+// of libpthread avoids the problem, but isn't practical.
+//
+// Possible remedies:
+//
+// 1. Establish a minimum relative wait time. 50 to 100 msecs seems to work.
+// This is palliative and probabilistic, however. If the thread is preempted
+// between the call to compute_abstime() and pthread_cond_timedwait(), more
+// than the minimum period may have passed, and the abstime may be stale (in the
+// past) resultin in a hang. Using this technique reduces the odds of a hang
+// but the JVM is still vulnerable, particularly on heavily loaded systems.
+//
+// 2. Modify park-unpark to use per-thread (per ParkEvent) pipe-pairs instead
+// of the usual flag-condvar-mutex idiom. The write side of the pipe is set
+// NDELAY. unpark() reduces to write(), park() reduces to read() and park(timo)
+// reduces to poll()+read(). This works well, but consumes 2 FDs per extant
+// thread.
+//
+// 3. Embargo pthread_cond_timedwait() and implement a native "chron" thread
+// that manages timeouts. We'd emulate pthread_cond_timedwait() by enqueuing
+// a timeout request to the chron thread and then blocking via pthread_cond_wait().
+// This also works well. In fact it avoids kernel-level scalability impediments
+// on certain platforms that don't handle lots of active pthread_cond_timedwait()
+// timers in a graceful fashion.
+//
+// 4. When the abstime value is in the past it appears that control returns
+// correctly from pthread_cond_timedwait(), but the condvar is left corrupt.
+// Subsequent timedwait/wait calls may hang indefinitely. Given that, we
+// can avoid the problem by reinitializing the condvar -- by cond_destroy()
+// followed by cond_init() -- after all calls to pthread_cond_timedwait().
+// It may be possible to avoid reinitialization by checking the return
+// value from pthread_cond_timedwait(). In addition to reinitializing the
+// condvar we must establish the invariant that cond_signal() is only called
+// within critical sections protected by the adjunct mutex. This prevents
+// cond_signal() from "seeing" a condvar that's in the midst of being
+// reinitialized or that is corrupt. Sadly, this invariant obviates the
+// desirable signal-after-unlock optimization that avoids futile context switching.
+//
+// I'm also concerned that some versions of NTPL might allocate an auxilliary
+// structure when a condvar is used or initialized. cond_destroy() would
+// release the helper structure. Our reinitialize-after-timedwait fix
+// put excessive stress on malloc/free and locks protecting the c-heap.
+//
+// We currently use (4). See the WorkAroundNTPLTimedWaitHang flag.
+// It may be possible to refine (4) by checking the kernel and NTPL verisons
+// and only enabling the work-around for vulnerable environments.
+
+// utility to compute the abstime argument to timedwait:
+// millis is the relative timeout time
+// abstime will be the absolute timeout time
+// TODO: replace compute_abstime() with unpackTime()
+
+static struct timespec* compute_abstime(struct timespec* abstime, jlong millis) {
+ if (millis < 0) millis = 0;
+ struct timeval now;
+ int status = gettimeofday(&now, NULL);
+ assert(status == 0, "gettimeofday");
+ jlong seconds = millis / 1000;
+ millis %= 1000;
+ if (seconds > 50000000) { // see man cond_timedwait(3T)
+ seconds = 50000000;
+ }
+ abstime->tv_sec = now.tv_sec + seconds;
+ long usec = now.tv_usec + millis * 1000;
+ if (usec >= 1000000) {
+ abstime->tv_sec += 1;
+ usec -= 1000000;
+ }
+ abstime->tv_nsec = usec * 1000;
+ return abstime;
+}
+
+
+// Test-and-clear _Event, always leaves _Event set to 0, returns immediately.
+// Conceptually TryPark() should be equivalent to park(0).
+
+int os::PlatformEvent::TryPark() {
+ for (;;) {
+ const int v = _Event ;
+ guarantee ((v == 0) || (v == 1), "invariant") ;
+ if (Atomic::cmpxchg (0, &_Event, v) == v) return v ;
+ }
+}
+
+void os::PlatformEvent::park() { // AKA "down()"
+ // Invariant: Only the thread associated with the Event/PlatformEvent
+ // may call park().
+ // TODO: assert that _Assoc != NULL or _Assoc == Self
+ int v ;
+ for (;;) {
+ v = _Event ;
+ if (Atomic::cmpxchg (v-1, &_Event, v) == v) break ;
+ }
+ guarantee (v >= 0, "invariant") ;
+ if (v == 0) {
+ // Do this the hard way by blocking ...
+ int status = pthread_mutex_lock(_mutex);
+ assert_status(status == 0, status, "mutex_lock");
+ guarantee (_nParked == 0, "invariant") ;
+ ++ _nParked ;
+ while (_Event < 0) {
+ status = pthread_cond_wait(_cond, _mutex);
+ // for some reason, under 2.7 lwp_cond_wait() may return ETIME ...
+ // Treat this the same as if the wait was interrupted
+ if (status == ETIMEDOUT) { status = EINTR; }
+ assert_status(status == 0 || status == EINTR, status, "cond_wait");
+ }
+ -- _nParked ;
+
+ // In theory we could move the ST of 0 into _Event past the unlock(),
+ // but then we'd need a MEMBAR after the ST.
+ _Event = 0 ;
+ status = pthread_mutex_unlock(_mutex);
+ assert_status(status == 0, status, "mutex_unlock");
+ }
+ guarantee (_Event >= 0, "invariant") ;
+}
+
+int os::PlatformEvent::park(jlong millis) {
+ guarantee (_nParked == 0, "invariant") ;
+
+ int v ;
+ for (;;) {
+ v = _Event ;
+ if (Atomic::cmpxchg (v-1, &_Event, v) == v) break ;
+ }
+ guarantee (v >= 0, "invariant") ;
+ if (v != 0) return OS_OK ;
+
+ // We do this the hard way, by blocking the thread.
+ // Consider enforcing a minimum timeout value.
+ struct timespec abst;
+ compute_abstime(&abst, millis);
+
+ int ret = OS_TIMEOUT;
+ int status = pthread_mutex_lock(_mutex);
+ assert_status(status == 0, status, "mutex_lock");
+ guarantee (_nParked == 0, "invariant") ;
+ ++_nParked ;
+
+ // Object.wait(timo) will return because of
+ // (a) notification
+ // (b) timeout
+ // (c) thread.interrupt
+ //
+ // Thread.interrupt and object.notify{All} both call Event::set.
+ // That is, we treat thread.interrupt as a special case of notification.
+ // The underlying Solaris implementation, cond_timedwait, admits
+ // spurious/premature wakeups, but the JLS/JVM spec prevents the
+ // JVM from making those visible to Java code. As such, we must
+ // filter out spurious wakeups. We assume all ETIME returns are valid.
+ //
+ // TODO: properly differentiate simultaneous notify+interrupt.
+ // In that case, we should propagate the notify to another waiter.
+
+ while (_Event < 0) {
+ status = os::Bsd::safe_cond_timedwait(_cond, _mutex, &abst);
+ if (status != 0 && WorkAroundNPTLTimedWaitHang) {
+ pthread_cond_destroy (_cond);
+ pthread_cond_init (_cond, NULL) ;
+ }
+ assert_status(status == 0 || status == EINTR ||
+ status == ETIMEDOUT,
+ status, "cond_timedwait");
+ if (!FilterSpuriousWakeups) break ; // previous semantics
+ if (status == ETIMEDOUT) break ;
+ // We consume and ignore EINTR and spurious wakeups.
+ }
+ --_nParked ;
+ if (_Event >= 0) {
+ ret = OS_OK;
+ }
+ _Event = 0 ;
+ status = pthread_mutex_unlock(_mutex);
+ assert_status(status == 0, status, "mutex_unlock");
+ assert (_nParked == 0, "invariant") ;
+ return ret;
+}
+
+void os::PlatformEvent::unpark() {
+ int v, AnyWaiters ;
+ for (;;) {
+ v = _Event ;
+ if (v > 0) {
+ // The LD of _Event could have reordered or be satisfied
+ // by a read-aside from this processor's write buffer.
+ // To avoid problems execute a barrier and then
+ // ratify the value.
+ OrderAccess::fence() ;
+ if (_Event == v) return ;
+ continue ;
+ }
+ if (Atomic::cmpxchg (v+1, &_Event, v) == v) break ;
+ }
+ if (v < 0) {
+ // Wait for the thread associated with the event to vacate
+ int status = pthread_mutex_lock(_mutex);
+ assert_status(status == 0, status, "mutex_lock");
+ AnyWaiters = _nParked ;
+ assert (AnyWaiters == 0 || AnyWaiters == 1, "invariant") ;
+ if (AnyWaiters != 0 && WorkAroundNPTLTimedWaitHang) {
+ AnyWaiters = 0 ;
+ pthread_cond_signal (_cond);
+ }
+ status = pthread_mutex_unlock(_mutex);
+ assert_status(status == 0, status, "mutex_unlock");
+ if (AnyWaiters != 0) {
+ status = pthread_cond_signal(_cond);
+ assert_status(status == 0, status, "cond_signal");
+ }
+ }
+
+ // Note that we signal() _after dropping the lock for "immortal" Events.
+ // This is safe and avoids a common class of futile wakeups. In rare
+ // circumstances this can cause a thread to return prematurely from
+ // cond_{timed}wait() but the spurious wakeup is benign and the victim will
+ // simply re-test the condition and re-park itself.
+}
+
+
+// JSR166
+// -------------------------------------------------------
+
+/*
+ * The solaris and bsd implementations of park/unpark are fairly
+ * conservative for now, but can be improved. They currently use a
+ * mutex/condvar pair, plus a a count.
+ * Park decrements count if > 0, else does a condvar wait. Unpark
+ * sets count to 1 and signals condvar. Only one thread ever waits
+ * on the condvar. Contention seen when trying to park implies that someone
+ * is unparking you, so don't wait. And spurious returns are fine, so there
+ * is no need to track notifications.
+ */
+
+
+#define NANOSECS_PER_SEC 1000000000
+#define NANOSECS_PER_MILLISEC 1000000
+#define MAX_SECS 100000000
+/*
+ * This code is common to bsd and solaris and will be moved to a
+ * common place in dolphin.
+ *
+ * The passed in time value is either a relative time in nanoseconds
+ * or an absolute time in milliseconds. Either way it has to be unpacked
+ * into suitable seconds and nanoseconds components and stored in the
+ * given timespec structure.
+ * Given time is a 64-bit value and the time_t used in the timespec is only
+ * a signed-32-bit value (except on 64-bit Bsd) we have to watch for
+ * overflow if times way in the future are given. Further on Solaris versions
+ * prior to 10 there is a restriction (see cond_timedwait) that the specified
+ * number of seconds, in abstime, is less than current_time + 100,000,000.
+ * As it will be 28 years before "now + 100000000" will overflow we can
+ * ignore overflow and just impose a hard-limit on seconds using the value
+ * of "now + 100,000,000". This places a limit on the timeout of about 3.17
+ * years from "now".
+ */
+
+static void unpackTime(struct timespec* absTime, bool isAbsolute, jlong time) {
+ assert (time > 0, "convertTime");
+
+ struct timeval now;
+ int status = gettimeofday(&now, NULL);
+ assert(status == 0, "gettimeofday");
+
+ time_t max_secs = now.tv_sec + MAX_SECS;
+
+ if (isAbsolute) {
+ jlong secs = time / 1000;
+ if (secs > max_secs) {
+ absTime->tv_sec = max_secs;
+ }
+ else {
+ absTime->tv_sec = secs;
+ }
+ absTime->tv_nsec = (time % 1000) * NANOSECS_PER_MILLISEC;
+ }
+ else {
+ jlong secs = time / NANOSECS_PER_SEC;
+ if (secs >= MAX_SECS) {
+ absTime->tv_sec = max_secs;
+ absTime->tv_nsec = 0;
+ }
+ else {
+ absTime->tv_sec = now.tv_sec + secs;
+ absTime->tv_nsec = (time % NANOSECS_PER_SEC) + now.tv_usec*1000;
+ if (absTime->tv_nsec >= NANOSECS_PER_SEC) {
+ absTime->tv_nsec -= NANOSECS_PER_SEC;
+ ++absTime->tv_sec; // note: this must be <= max_secs
+ }
+ }
+ }
+ assert(absTime->tv_sec >= 0, "tv_sec < 0");
+ assert(absTime->tv_sec <= max_secs, "tv_sec > max_secs");
+ assert(absTime->tv_nsec >= 0, "tv_nsec < 0");
+ assert(absTime->tv_nsec < NANOSECS_PER_SEC, "tv_nsec >= nanos_per_sec");
+}
+
+void Parker::park(bool isAbsolute, jlong time) {
+ // Optional fast-path check:
+ // Return immediately if a permit is available.
+ if (_counter > 0) {
+ _counter = 0 ;
+ OrderAccess::fence();
+ return ;
+ }
+
+ Thread* thread = Thread::current();
+ assert(thread->is_Java_thread(), "Must be JavaThread");
+ JavaThread *jt = (JavaThread *)thread;
+
+ // Optional optimization -- avoid state transitions if there's an interrupt pending.
+ // Check interrupt before trying to wait
+ if (Thread::is_interrupted(thread, false)) {
+ return;
+ }
+
+ // Next, demultiplex/decode time arguments
+ struct timespec absTime;
+ if (time < 0 || (isAbsolute && time == 0) ) { // don't wait at all
+ return;
+ }
+ if (time > 0) {
+ unpackTime(&absTime, isAbsolute, time);
+ }
+
+
+ // Enter safepoint region
+ // Beware of deadlocks such as 6317397.
+ // The per-thread Parker:: mutex is a classic leaf-lock.
+ // In particular a thread must never block on the Threads_lock while
+ // holding the Parker:: mutex. If safepoints are pending both the
+ // the ThreadBlockInVM() CTOR and DTOR may grab Threads_lock.
+ ThreadBlockInVM tbivm(jt);
+
+ // Don't wait if cannot get lock since interference arises from
+ // unblocking. Also. check interrupt before trying wait
+ if (Thread::is_interrupted(thread, false) || pthread_mutex_trylock(_mutex) != 0) {
+ return;
+ }
+
+ int status ;
+ if (_counter > 0) { // no wait needed
+ _counter = 0;
+ status = pthread_mutex_unlock(_mutex);
+ assert (status == 0, "invariant") ;
+ OrderAccess::fence();
+ return;
+ }
+
+#ifdef ASSERT
+ // Don't catch signals while blocked; let the running threads have the signals.
+ // (This allows a debugger to break into the running thread.)
+ sigset_t oldsigs;
+ sigset_t* allowdebug_blocked = os::Bsd::allowdebug_blocked_signals();
+ pthread_sigmask(SIG_BLOCK, allowdebug_blocked, &oldsigs);
+#endif
+
+ OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */);
+ jt->set_suspend_equivalent();
+ // cleared by handle_special_suspend_equivalent_condition() or java_suspend_self()
+
+ if (time == 0) {
+ status = pthread_cond_wait (_cond, _mutex) ;
+ } else {
+ status = os::Bsd::safe_cond_timedwait (_cond, _mutex, &absTime) ;
+ if (status != 0 && WorkAroundNPTLTimedWaitHang) {
+ pthread_cond_destroy (_cond) ;
+ pthread_cond_init (_cond, NULL);
+ }
+ }
+ assert_status(status == 0 || status == EINTR ||
+ status == ETIMEDOUT,
+ status, "cond_timedwait");
+
+#ifdef ASSERT
+ pthread_sigmask(SIG_SETMASK, &oldsigs, NULL);
+#endif
+
+ _counter = 0 ;
+ status = pthread_mutex_unlock(_mutex) ;
+ assert_status(status == 0, status, "invariant") ;
+ // If externally suspended while waiting, re-suspend
+ if (jt->handle_special_suspend_equivalent_condition()) {
+ jt->java_suspend_self();
+ }
+
+ OrderAccess::fence();
+}
+
+void Parker::unpark() {
+ int s, status ;
+ status = pthread_mutex_lock(_mutex);
+ assert (status == 0, "invariant") ;
+ s = _counter;
+ _counter = 1;
+ if (s < 1) {
+ if (WorkAroundNPTLTimedWaitHang) {
+ status = pthread_cond_signal (_cond) ;
+ assert (status == 0, "invariant") ;
+ status = pthread_mutex_unlock(_mutex);
+ assert (status == 0, "invariant") ;
+ } else {
+ status = pthread_mutex_unlock(_mutex);
+ assert (status == 0, "invariant") ;
+ status = pthread_cond_signal (_cond) ;
+ assert (status == 0, "invariant") ;
+ }
+ } else {
+ pthread_mutex_unlock(_mutex);
+ assert (status == 0, "invariant") ;
+ }
+}
+
+
+/* Darwin has no "environ" in a dynamic library. */
+#ifdef __APPLE__
+#include <crt_externs.h>
+#define environ (*_NSGetEnviron())
+#else
+extern char** environ;
+#endif
+
+// Run the specified command in a separate process. Return its exit value,
+// or -1 on failure (e.g. can't fork a new process).
+// Unlike system(), this function can be called from signal handler. It
+// doesn't block SIGINT et al.
+int os::fork_and_exec(char* cmd) {
+ const char * argv[4] = {"sh", "-c", cmd, NULL};
+
+ // fork() in BsdThreads/NPTL is not async-safe. It needs to run
+ // pthread_atfork handlers and reset pthread library. All we need is a
+ // separate process to execve. Make a direct syscall to fork process.
+ // On IA64 there's no fork syscall, we have to use fork() and hope for
+ // the best...
+ pid_t pid = fork();
+
+ if (pid < 0) {
+ // fork failed
+ return -1;
+
+ } else if (pid == 0) {
+ // child process
+
+ // execve() in BsdThreads will call pthread_kill_other_threads_np()
+ // first to kill every thread on the thread list. Because this list is
+ // not reset by fork() (see notes above), execve() will instead kill
+ // every thread in the parent process. We know this is the only thread
+ // in the new process, so make a system call directly.
+ // IA64 should use normal execve() from glibc to match the glibc fork()
+ // above.
+ execve("/bin/sh", (char* const*)argv, environ);
+
+ // execve failed
+ _exit(-1);
+
+ } else {
+ // copied from J2SE ..._waitForProcessExit() in UNIXProcess_md.c; we don't
+ // care about the actual exit code, for now.
+
+ int status;
+
+ // Wait for the child process to exit. This returns immediately if
+ // the child has already exited. */
+ while (waitpid(pid, &status, 0) < 0) {
+ switch (errno) {
+ case ECHILD: return 0;
+ case EINTR: break;
+ default: return -1;
+ }
+ }
+
+ if (WIFEXITED(status)) {
+ // The child exited normally; get its exit code.
+ return WEXITSTATUS(status);
+ } else if (WIFSIGNALED(status)) {
+ // The child exited because of a signal
+ // The best value to return is 0x80 + signal number,
+ // because that is what all Unix shells do, and because
+ // it allows callers to distinguish between process exit and
+ // process death by signal.
+ return 0x80 + WTERMSIG(status);
+ } else {
+ // Unknown exit code; pass it through
+ return status;
+ }
+ }
+}
+
+// is_headless_jre()
+//
+// Test for the existence of libmawt in motif21 or xawt directories
+// in order to report if we are running in a headless jre
+//
+bool os::is_headless_jre() {
+ struct stat statbuf;
+ char buf[MAXPATHLEN];
+ char libmawtpath[MAXPATHLEN];
+ const char *xawtstr = "/xawt/libmawt.so";
+ const char *motifstr = "/motif21/libmawt.so";
+ char *p;
+
+ // Get path to libjvm.so
+ os::jvm_path(buf, sizeof(buf));
+
+ // Get rid of libjvm.so
+ p = strrchr(buf, '/');
+ if (p == NULL) return false;
+ else *p = '\0';
+
+ // Get rid of client or server
+ p = strrchr(buf, '/');
+ if (p == NULL) return false;
+ else *p = '\0';
+
+ // check xawt/libmawt.so
+ strcpy(libmawtpath, buf);
+ strcat(libmawtpath, xawtstr);
+ if (::stat(libmawtpath, &statbuf) == 0) return false;
+
+ // check motif21/libmawt.so
+ strcpy(libmawtpath, buf);
+ strcat(libmawtpath, motifstr);
+ if (::stat(libmawtpath, &statbuf) == 0) return false;
+
+ return true;
+}
diff --git a/src/os/bsd/vm/os_bsd.hpp b/src/os/bsd/vm/os_bsd.hpp
new file mode 100644
index 000000000..271d1e291
--- /dev/null
+++ b/src/os/bsd/vm/os_bsd.hpp
@@ -0,0 +1,368 @@
+/*
+ * 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.
+ *
+ * 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 OS_BSD_VM_OS_BSD_HPP
+#define OS_BSD_VM_OS_BSD_HPP
+
+// Bsd_OS defines the interface to Bsd operating systems
+
+/* pthread_getattr_np comes with BsdThreads-0.9-7 on RedHat 7.1 */
+typedef int (*pthread_getattr_func_type) (pthread_t, pthread_attr_t *);
+
+#ifdef __APPLE__
+// Mac OS X doesn't support clock_gettime. Stub out the type, it is
+// unused
+typedef int clockid_t;
+#endif
+
+class Bsd {
+ friend class os;
+
+ // For signal-chaining
+#define MAXSIGNUM 32
+ static struct sigaction sigact[MAXSIGNUM]; // saved preinstalled sigactions
+ static unsigned int sigs; // mask of signals that have
+ // preinstalled signal handlers
+ static bool libjsig_is_loaded; // libjsig that interposes sigaction(),
+ // __sigaction(), signal() is loaded
+ static struct sigaction *(*get_signal_action)(int);
+ static struct sigaction *get_preinstalled_handler(int);
+ static void save_preinstalled_handler(int, struct sigaction&);
+
+ static void check_signal_handler(int sig);
+
+ // For signal flags diagnostics
+ static int sigflags[MAXSIGNUM];
+
+ static int (*_clock_gettime)(clockid_t, struct timespec *);
+#ifndef _ALLBSD_SOURCE
+ static int (*_pthread_getcpuclockid)(pthread_t, clockid_t *);
+
+ static address _initial_thread_stack_bottom;
+ static uintptr_t _initial_thread_stack_size;
+
+ static const char *_glibc_version;
+ static const char *_libpthread_version;
+
+ static bool _is_floating_stack;
+ static bool _is_NPTL;
+ static bool _supports_fast_thread_cpu_time;
+#endif
+
+ static GrowableArray<int>* _cpu_to_node;
+
+ protected:
+
+ static julong _physical_memory;
+ static pthread_t _main_thread;
+#ifndef _ALLBSD_SOURCE
+ static Mutex* _createThread_lock;
+#endif
+ static int _page_size;
+
+ static julong available_memory();
+ static julong physical_memory() { return _physical_memory; }
+ static void initialize_system_info();
+
+#ifndef _ALLBSD_SOURCE
+ static void set_glibc_version(const char *s) { _glibc_version = s; }
+ static void set_libpthread_version(const char *s) { _libpthread_version = s; }
+#endif
+
+ static bool supports_variable_stack_size();
+
+#ifndef _ALLBSD_SOURCE
+ static void set_is_NPTL() { _is_NPTL = true; }
+ static void set_is_BsdThreads() { _is_NPTL = false; }
+ static void set_is_floating_stack() { _is_floating_stack = true; }
+#endif
+
+ static void rebuild_cpu_to_node_map();
+ static GrowableArray<int>* cpu_to_node() { return _cpu_to_node; }
+
+ static bool hugetlbfs_sanity_check(bool warn, size_t page_size);
+
+ public:
+
+ static void init_thread_fpu_state();
+#ifndef _ALLBSD_SOURCE
+ static int get_fpu_control_word();
+ static void set_fpu_control_word(int fpu_control);
+#endif
+ static pthread_t main_thread(void) { return _main_thread; }
+
+#ifndef _ALLBSD_SOURCE
+ // returns kernel thread id (similar to LWP id on Solaris), which can be
+ // used to access /proc
+ static pid_t gettid();
+ static void set_createThread_lock(Mutex* lk) { _createThread_lock = lk; }
+ static Mutex* createThread_lock(void) { return _createThread_lock; }
+#endif
+ static void hotspot_sigmask(Thread* thread);
+
+#ifndef _ALLBSD_SOURCE
+ static address initial_thread_stack_bottom(void) { return _initial_thread_stack_bottom; }
+ static uintptr_t initial_thread_stack_size(void) { return _initial_thread_stack_size; }
+#endif
+ static bool is_initial_thread(void);
+
+ static int page_size(void) { return _page_size; }
+ static void set_page_size(int val) { _page_size = val; }
+
+ static address ucontext_get_pc(ucontext_t* uc);
+ static intptr_t* ucontext_get_sp(ucontext_t* uc);
+ static intptr_t* ucontext_get_fp(ucontext_t* uc);
+
+ // For Analyzer Forte AsyncGetCallTrace profiling support:
+ //
+ // This interface should be declared in os_bsd_i486.hpp, but
+ // that file provides extensions to the os class and not the
+ // Bsd class.
+ static ExtendedPC fetch_frame_from_ucontext(Thread* thread, ucontext_t* uc,
+ intptr_t** ret_sp, intptr_t** ret_fp);
+
+ // This boolean allows users to forward their own non-matching signals
+ // to JVM_handle_bsd_signal, harmlessly.
+ static bool signal_handlers_are_installed;
+
+ static int get_our_sigflags(int);
+ static void set_our_sigflags(int, int);
+ static void signal_sets_init();
+ static void install_signal_handlers();
+ static void set_signal_handler(int, bool);
+ static bool is_sig_ignored(int sig);
+
+ static sigset_t* unblocked_signals();
+ static sigset_t* vm_signals();
+ static sigset_t* allowdebug_blocked_signals();
+
+ // For signal-chaining
+ static struct sigaction *get_chained_signal_action(int sig);
+ static bool chained_handler(int sig, siginfo_t* siginfo, void* context);
+
+#ifndef _ALLBSD_SOURCE
+ // GNU libc and libpthread version strings
+ static const char *glibc_version() { return _glibc_version; }
+ static const char *libpthread_version() { return _libpthread_version; }
+
+ // NPTL or BsdThreads?
+ static bool is_BsdThreads() { return !_is_NPTL; }
+ static bool is_NPTL() { return _is_NPTL; }
+
+ // NPTL is always floating stack. BsdThreads could be using floating
+ // stack or fixed stack.
+ static bool is_floating_stack() { return _is_floating_stack; }
+
+ static void libpthread_init();
+ static bool libnuma_init();
+ static void* libnuma_dlsym(void* handle, const char* name);
+#endif
+ // Minimum stack size a thread can be created with (allowing
+ // the VM to completely create the thread and enter user code)
+ static size_t min_stack_allowed;
+
+ // Return default stack size or guard size for the specified thread type
+ static size_t default_stack_size(os::ThreadType thr_type);
+ static size_t default_guard_size(os::ThreadType thr_type);
+
+#ifndef _ALLBSD_SOURCE
+ static void capture_initial_stack(size_t max_size);
+
+ // Stack overflow handling
+ static bool manually_expand_stack(JavaThread * t, address addr);
+ static int max_register_window_saves_before_flushing();
+#endif
+
+ // Real-time clock functions
+ static void clock_init(void);
+
+#ifndef _ALLBSD_SOURCE
+ // fast POSIX clocks support
+ static void fast_thread_clock_init(void);
+#endif
+
+ static bool supports_monotonic_clock() {
+ return _clock_gettime != NULL;
+ }
+
+ static int clock_gettime(clockid_t clock_id, struct timespec *tp) {
+ return _clock_gettime ? _clock_gettime(clock_id, tp) : -1;
+ }
+
+#ifndef _ALLBSD_SOURCE
+ static int pthread_getcpuclockid(pthread_t tid, clockid_t *clock_id) {
+ return _pthread_getcpuclockid ? _pthread_getcpuclockid(tid, clock_id) : -1;
+ }
+
+ static bool supports_fast_thread_cpu_time() {
+ return _supports_fast_thread_cpu_time;
+ }
+
+ static jlong fast_thread_cpu_time(clockid_t clockid);
+#endif
+
+ // Stack repair handling
+
+ // none present
+
+ // BsdThreads work-around for 6292965
+ static int safe_cond_timedwait(pthread_cond_t *_cond, pthread_mutex_t *_mutex, const struct timespec *_abstime);
+
+
+ // Bsd suspend/resume support - this helper is a shadow of its former
+ // self now that low-level suspension is barely used, and old workarounds
+ // for BsdThreads are no longer needed.
+ class SuspendResume {
+ private:
+ volatile int _suspend_action;
+ // values for suspend_action:
+ #define SR_NONE (0x00)
+ #define SR_SUSPEND (0x01) // suspend request
+ #define SR_CONTINUE (0x02) // resume request
+
+ volatile jint _state;
+ // values for _state: + SR_NONE
+ #define SR_SUSPENDED (0x20)
+ public:
+ SuspendResume() { _suspend_action = SR_NONE; _state = SR_NONE; }
+
+ int suspend_action() const { return _suspend_action; }
+ void set_suspend_action(int x) { _suspend_action = x; }
+
+ // atomic updates for _state
+ void set_suspended() {
+ jint temp, temp2;
+ do {
+ temp = _state;
+ temp2 = Atomic::cmpxchg(temp | SR_SUSPENDED, &_state, temp);
+ } while (temp2 != temp);
+ }
+ void clear_suspended() {
+ jint temp, temp2;
+ do {
+ temp = _state;
+ temp2 = Atomic::cmpxchg(temp & ~SR_SUSPENDED, &_state, temp);
+ } while (temp2 != temp);
+ }
+ bool is_suspended() { return _state & SR_SUSPENDED; }
+
+ #undef SR_SUSPENDED
+ };
+
+private:
+ typedef int (*sched_getcpu_func_t)(void);
+ typedef int (*numa_node_to_cpus_func_t)(int node, unsigned long *buffer, int bufferlen);
+ typedef int (*numa_max_node_func_t)(void);
+ typedef int (*numa_available_func_t)(void);
+ typedef int (*numa_tonode_memory_func_t)(void *start, size_t size, int node);
+ typedef void (*numa_interleave_memory_func_t)(void *start, size_t size, unsigned long *nodemask);
+
+ static sched_getcpu_func_t _sched_getcpu;
+ static numa_node_to_cpus_func_t _numa_node_to_cpus;
+ static numa_max_node_func_t _numa_max_node;
+ static numa_available_func_t _numa_available;
+ static numa_tonode_memory_func_t _numa_tonode_memory;
+ static numa_interleave_memory_func_t _numa_interleave_memory;
+ static unsigned long* _numa_all_nodes;
+
+ static void set_sched_getcpu(sched_getcpu_func_t func) { _sched_getcpu = func; }
+ static void set_numa_node_to_cpus(numa_node_to_cpus_func_t func) { _numa_node_to_cpus = func; }
+ static void set_numa_max_node(numa_max_node_func_t func) { _numa_max_node = func; }
+ static void set_numa_available(numa_available_func_t func) { _numa_available = func; }
+ static void set_numa_tonode_memory(numa_tonode_memory_func_t func) { _numa_tonode_memory = func; }
+ static void set_numa_interleave_memory(numa_interleave_memory_func_t func) { _numa_interleave_memory = func; }
+ static void set_numa_all_nodes(unsigned long* ptr) { _numa_all_nodes = ptr; }
+public:
+ static int sched_getcpu() { return _sched_getcpu != NULL ? _sched_getcpu() : -1; }
+ static int numa_node_to_cpus(int node, unsigned long *buffer, int bufferlen) {
+ return _numa_node_to_cpus != NULL ? _numa_node_to_cpus(node, buffer, bufferlen) : -1;
+ }
+ static int numa_max_node() { return _numa_max_node != NULL ? _numa_max_node() : -1; }
+ static int numa_available() { return _numa_available != NULL ? _numa_available() : -1; }
+ static int numa_tonode_memory(void *start, size_t size, int node) {
+ return _numa_tonode_memory != NULL ? _numa_tonode_memory(start, size, node) : -1;
+ }
+ static void numa_interleave_memory(void *start, size_t size) {
+ if (_numa_interleave_memory != NULL && _numa_all_nodes != NULL) {
+ _numa_interleave_memory(start, size, _numa_all_nodes);
+ }
+ }
+ static int get_node_by_cpu(int cpu_id);
+};
+
+
+class PlatformEvent : public CHeapObj {
+ private:
+ double CachePad [4] ; // increase odds that _mutex is sole occupant of cache line
+ volatile int _Event ;
+ volatile int _nParked ;
+ pthread_mutex_t _mutex [1] ;
+ pthread_cond_t _cond [1] ;
+ double PostPad [2] ;
+ Thread * _Assoc ;
+
+ public: // TODO-FIXME: make dtor private
+ ~PlatformEvent() { guarantee (0, "invariant") ; }
+
+ public:
+ PlatformEvent() {
+ int status;
+ status = pthread_cond_init (_cond, NULL);
+ assert_status(status == 0, status, "cond_init");
+ status = pthread_mutex_init (_mutex, NULL);
+ assert_status(status == 0, status, "mutex_init");
+ _Event = 0 ;
+ _nParked = 0 ;
+ _Assoc = NULL ;
+ }
+
+ // Use caution with reset() and fired() -- they may require MEMBARs
+ void reset() { _Event = 0 ; }
+ int fired() { return _Event; }
+ void park () ;
+ void unpark () ;
+ int TryPark () ;
+ int park (jlong millis) ;
+ void SetAssociation (Thread * a) { _Assoc = a ; }
+} ;
+
+class PlatformParker : public CHeapObj {
+ protected:
+ pthread_mutex_t _mutex [1] ;
+ pthread_cond_t _cond [1] ;
+
+ public: // TODO-FIXME: make dtor private
+ ~PlatformParker() { guarantee (0, "invariant") ; }
+
+ public:
+ PlatformParker() {
+ int status;
+ status = pthread_cond_init (_cond, NULL);
+ assert_status(status == 0, status, "cond_init");
+ status = pthread_mutex_init (_mutex, NULL);
+ assert_status(status == 0, status, "mutex_init");
+ }
+} ;
+
+#endif // OS_BSD_VM_OS_BSD_HPP
diff --git a/src/os/bsd/vm/os_bsd.inline.hpp b/src/os/bsd/vm/os_bsd.inline.hpp
new file mode 100644
index 000000000..731a7e61e
--- /dev/null
+++ b/src/os/bsd/vm/os_bsd.inline.hpp
@@ -0,0 +1,302 @@
+/*
+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef OS_BSD_VM_OS_BSD_INLINE_HPP
+#define OS_BSD_VM_OS_BSD_INLINE_HPP
+
+#include "runtime/atomic.hpp"
+#include "runtime/os.hpp"
+#ifdef TARGET_OS_ARCH_bsd_x86
+# include "atomic_bsd_x86.inline.hpp"
+# include "orderAccess_bsd_x86.inline.hpp"
+#endif
+#ifdef TARGET_OS_ARCH_bsd_zero
+# include "atomic_bsd_zero.inline.hpp"
+# include "orderAccess_bsd_zero.inline.hpp"
+#endif
+
+// System includes
+
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/poll.h>
+#include <netdb.h>
+
+inline void* os::thread_local_storage_at(int index) {
+ return pthread_getspecific((pthread_key_t)index);
+}
+
+inline const char* os::file_separator() {
+ return "/";
+}
+
+inline const char* os::line_separator() {
+ return "\n";
+}
+
+inline const char* os::path_separator() {
+ return ":";
+}
+
+inline const char* os::jlong_format_specifier() {
+ return "%lld";
+}
+
+inline const char* os::julong_format_specifier() {
+ return "%llu";
+}
+
+// File names are case-sensitive on windows only
+inline int os::file_name_strcmp(const char* s1, const char* s2) {
+ return strcmp(s1, s2);
+}
+
+inline bool os::obsolete_option(const JavaVMOption *option) {
+ return false;
+}
+
+inline bool os::uses_stack_guard_pages() {
+ return true;
+}
+
+inline bool os::allocate_stack_guard_pages() {
+ assert(uses_stack_guard_pages(), "sanity check");
+#if !defined(__FreeBSD__) || __FreeBSD__ < 5
+ // Since FreeBSD 4 uses malloc() for allocating the thread stack
+ // there is no need to do anything extra to allocate the guard pages
+ return false;
+#else
+ // FreeBSD 5+ uses mmap MAP_STACK for allocating the thread stacks.
+ // Must 'allocate' them or guard pages are ignored.
+ return true;
+#endif
+}
+
+
+// On Bsd, reservations are made on a page by page basis, nothing to do.
+inline void os::split_reserved_memory(char *base, size_t size,
+ size_t split, bool realloc) {
+}
+
+
+// Bang the shadow pages if they need to be touched to be mapped.
+inline void os::bang_stack_shadow_pages() {
+}
+
+inline void os::dll_unload(void *lib) {
+ ::dlclose(lib);
+}
+
+inline const int os::default_file_open_flags() { return 0;}
+
+inline DIR* os::opendir(const char* dirname)
+{
+ assert(dirname != NULL, "just checking");
+ return ::opendir(dirname);
+}
+
+inline int os::readdir_buf_size(const char *path)
+{
+ return NAME_MAX + sizeof(dirent) + 1;
+}
+
+inline jlong os::lseek(int fd, jlong offset, int whence) {
+ return (jlong) ::lseek(fd, offset, whence);
+}
+
+inline int os::fsync(int fd) {
+ return ::fsync(fd);
+}
+
+inline char* os::native_path(char *path) {
+ return path;
+}
+
+inline int os::ftruncate(int fd, jlong length) {
+ return ::ftruncate(fd, length);
+}
+
+inline struct dirent* os::readdir(DIR* dirp, dirent *dbuf)
+{
+ dirent* p;
+ int status;
+ assert(dirp != NULL, "just checking");
+
+ // NOTE: Bsd readdir_r (on RH 6.2 and 7.2 at least) is NOT like the POSIX
+ // version. Here is the doc for this function:
+ // http://www.gnu.org/manual/glibc-2.2.3/html_node/libc_262.html
+
+ if((status = ::readdir_r(dirp, dbuf, &p)) != 0) {
+ errno = status;
+ return NULL;
+ } else
+ return p;
+}
+
+inline int os::closedir(DIR *dirp) {
+ assert(dirp != NULL, "argument is NULL");
+ return ::closedir(dirp);
+}
+
+// macros for restartable system calls
+
+#define RESTARTABLE(_cmd, _result) do { \
+ _result = _cmd; \
+ } while(((int)_result == OS_ERR) && (errno == EINTR))
+
+#define RESTARTABLE_RETURN_INT(_cmd) do { \
+ int _result; \
+ RESTARTABLE(_cmd, _result); \
+ return _result; \
+} while(false)
+
+inline bool os::numa_has_static_binding() { return true; }
+inline bool os::numa_has_group_homing() { return false; }
+
+inline size_t os::restartable_read(int fd, void *buf, unsigned int nBytes) {
+ size_t res;
+ RESTARTABLE( (size_t) ::read(fd, buf, (size_t) nBytes), res);
+ return res;
+}
+
+inline size_t os::write(int fd, const void *buf, unsigned int nBytes) {
+ size_t res;
+ RESTARTABLE((size_t) ::write(fd, buf, (size_t) nBytes), res);
+ return res;
+}
+
+inline int os::close(int fd) {
+ RESTARTABLE_RETURN_INT(::close(fd));
+}
+
+inline int os::socket_close(int fd) {
+ RESTARTABLE_RETURN_INT(::close(fd));
+}
+
+inline int os::socket(int domain, int type, int protocol) {
+ return ::socket(domain, type, protocol);
+}
+
+inline int os::recv(int fd, char *buf, int nBytes, int flags) {
+ RESTARTABLE_RETURN_INT(::recv(fd, buf, nBytes, (unsigned int) flags));
+}
+
+inline int os::send(int fd, char *buf, int nBytes, int flags) {
+ RESTARTABLE_RETURN_INT(::send(fd, buf, nBytes, (unsigned int) flags));
+}
+
+inline int os::raw_send(int fd, char *buf, int nBytes, int flags) {
+ return os::send(fd, buf, nBytes, flags);
+}
+
+inline int os::timeout(int fd, long timeout) {
+ julong prevtime,newtime;
+ struct timeval t;
+
+ gettimeofday(&t, NULL);
+ prevtime = ((julong)t.tv_sec * 1000) + t.tv_usec / 1000;
+
+ for(;;) {
+ struct pollfd pfd;
+
+ pfd.fd = fd;
+ pfd.events = POLLIN | POLLERR;
+
+ int res = ::poll(&pfd, 1, timeout);
+
+ if (res == OS_ERR && errno == EINTR) {
+
+ // On Bsd any value < 0 means "forever"
+
+ if(timeout >= 0) {
+ gettimeofday(&t, NULL);
+ newtime = ((julong)t.tv_sec * 1000) + t.tv_usec / 1000;
+ timeout -= newtime - prevtime;
+ if(timeout <= 0)
+ return OS_OK;
+ prevtime = newtime;
+ }
+ } else
+ return res;
+ }
+}
+
+inline int os::listen(int fd, int count) {
+ return ::listen(fd, count);
+}
+
+inline int os::connect(int fd, struct sockaddr *him, int len) {
+ RESTARTABLE_RETURN_INT(::connect(fd, him, len));
+}
+
+inline int os::accept(int fd, struct sockaddr *him, int *len) {
+ // This cast is from int to unsigned int on bsd. Since we
+ // only pass the parameter "len" around the vm and don't try to
+ // fetch it's value, this cast is safe for now. The java.net group
+ // may need and want to change this interface someday if socklen_t goes
+ // to 64 bits on some platform that we support.
+
+ // At least OpenBSD and FreeBSD can return EINTR from accept.
+ RESTARTABLE_RETURN_INT(::accept(fd, him, (socklen_t *)len));
+}
+
+inline int os::recvfrom(int fd, char *buf, int nBytes, int flags,
+ sockaddr *from, int *fromlen) {
+ RESTARTABLE_RETURN_INT(::recvfrom(fd, buf, nBytes, (unsigned int) flags, from, (socklen_t *)fromlen));
+}
+
+inline int os::sendto(int fd, char *buf, int len, int flags,
+ struct sockaddr *to, int tolen) {
+ RESTARTABLE_RETURN_INT(::sendto(fd, buf, len, (unsigned int) flags, to, tolen));
+}
+
+inline int os::socket_shutdown(int fd, int howto){
+ return ::shutdown(fd, howto);
+}
+
+inline int os::bind(int fd, struct sockaddr *him, int len){
+ return ::bind(fd, him, len);
+}
+
+inline int os::get_sock_name(int fd, struct sockaddr *him, int *len){
+ return ::getsockname(fd, him, (socklen_t *)len);
+}
+
+inline int os::get_host_name(char* name, int namelen){
+ return ::gethostname(name, namelen);
+}
+
+inline struct hostent* os::get_host_by_name(char* name) {
+ return ::gethostbyname(name);
+}
+inline int os::get_sock_opt(int fd, int level, int optname,
+ char *optval, int* optlen){
+ return ::getsockopt(fd, level, optname, optval, (socklen_t *)optlen);
+}
+
+inline int os::set_sock_opt(int fd, int level, int optname,
+ const char *optval, int optlen){
+ return ::setsockopt(fd, level, optname, optval, optlen);
+}
+#endif // OS_BSD_VM_OS_BSD_INLINE_HPP
diff --git a/src/os/bsd/vm/os_share_bsd.hpp b/src/os/bsd/vm/os_share_bsd.hpp
new file mode 100644
index 000000000..5caa7825c
--- /dev/null
+++ b/src/os/bsd/vm/os_share_bsd.hpp
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ *
+ * 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 OS_BSD_VM_OS_SHARE_BSD_HPP
+#define OS_BSD_VM_OS_SHARE_BSD_HPP
+
+// misc
+void signalHandler(int, siginfo_t*, ucontext_t*);
+void handle_unexpected_exception(Thread* thread, int sig, siginfo_t* info, address pc, address adjusted_pc);
+#ifndef PRODUCT
+void continue_with_dump(void);
+#endif
+
+#define PROCFILE_LENGTH 128
+
+#endif // OS_BSD_VM_OS_SHARE_BSD_HPP
diff --git a/src/os/bsd/vm/perfMemory_bsd.cpp b/src/os/bsd/vm/perfMemory_bsd.cpp
new file mode 100644
index 000000000..c93289e59
--- /dev/null
+++ b/src/os/bsd/vm/perfMemory_bsd.cpp
@@ -0,0 +1,1041 @@
+/*
+ * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "classfile/vmSymbols.hpp"
+#include "memory/allocation.inline.hpp"
+#include "memory/resourceArea.hpp"
+#include "oops/oop.inline.hpp"
+#include "os_bsd.inline.hpp"
+#include "runtime/handles.inline.hpp"
+#include "runtime/perfMemory.hpp"
+#include "utilities/exceptions.hpp"
+
+// put OS-includes here
+# include <sys/types.h>
+# include <sys/mman.h>
+# include <errno.h>
+# include <stdio.h>
+# include <unistd.h>
+# include <sys/stat.h>
+# include <signal.h>
+# include <pwd.h>
+
+static char* backing_store_file_name = NULL; // name of the backing store
+ // file, if successfully created.
+
+// Standard Memory Implementation Details
+
+// create the PerfData memory region in standard memory.
+//
+static char* create_standard_memory(size_t size) {
+
+ // allocate an aligned chuck of memory
+ char* mapAddress = os::reserve_memory(size);
+
+ if (mapAddress == NULL) {
+ return NULL;
+ }
+
+ // commit memory
+ if (!os::commit_memory(mapAddress, size)) {
+ if (PrintMiscellaneous && Verbose) {
+ warning("Could not commit PerfData memory\n");
+ }
+ os::release_memory(mapAddress, size);
+ return NULL;
+ }
+
+ return mapAddress;
+}
+
+// delete the PerfData memory region
+//
+static void delete_standard_memory(char* addr, size_t size) {
+
+ // there are no persistent external resources to cleanup for standard
+ // memory. since DestroyJavaVM does not support unloading of the JVM,
+ // cleanup of the memory resource is not performed. The memory will be
+ // reclaimed by the OS upon termination of the process.
+ //
+ return;
+}
+
+// save the specified memory region to the given file
+//
+// Note: this function might be called from signal handler (by os::abort()),
+// don't allocate heap memory.
+//
+static void save_memory_to_file(char* addr, size_t size) {
+
+ const char* destfile = PerfMemory::get_perfdata_file_path();
+ assert(destfile[0] != '\0', "invalid PerfData file path");
+
+ int result;
+
+ RESTARTABLE(::open(destfile, O_CREAT|O_WRONLY|O_TRUNC, S_IREAD|S_IWRITE),
+ result);;
+ if (result == OS_ERR) {
+ if (PrintMiscellaneous && Verbose) {
+ warning("Could not create Perfdata save file: %s: %s\n",
+ destfile, strerror(errno));
+ }
+ } else {
+ int fd = result;
+
+ for (size_t remaining = size; remaining > 0;) {
+
+ RESTARTABLE(::write(fd, addr, remaining), result);
+ if (result == OS_ERR) {
+ if (PrintMiscellaneous && Verbose) {
+ warning("Could not write Perfdata save file: %s: %s\n",
+ destfile, strerror(errno));
+ }
+ break;
+ }
+
+ remaining -= (size_t)result;
+ addr += result;
+ }
+
+ RESTARTABLE(::close(fd), result);
+ if (PrintMiscellaneous && Verbose) {
+ if (result == OS_ERR) {
+ warning("Could not close %s: %s\n", destfile, strerror(errno));
+ }
+ }
+ }
+ FREE_C_HEAP_ARRAY(char, destfile);
+}
+
+
+// Shared Memory Implementation Details
+
+// Note: the solaris and bsd shared memory implementation uses the mmap
+// interface with a backing store file to implement named shared memory.
+// Using the file system as the name space for shared memory allows a
+// common name space to be supported across a variety of platforms. It
+// also provides a name space that Java applications can deal with through
+// simple file apis.
+//
+// The solaris and bsd implementations store the backing store file in
+// a user specific temporary directory located in the /tmp file system,
+// which is always a local file system and is sometimes a RAM based file
+// system.
+
+// return the user specific temporary directory name.
+//
+// the caller is expected to free the allocated memory.
+//
+static char* get_user_tmp_dir(const char* user) {
+
+ const char* tmpdir = os::get_temp_directory();
+ const char* perfdir = PERFDATA_NAME;
+ size_t nbytes = strlen(tmpdir) + strlen(perfdir) + strlen(user) + 3;
+ char* dirname = NEW_C_HEAP_ARRAY(char, nbytes);
+
+ // construct the path name to user specific tmp directory
+ snprintf(dirname, nbytes, "%s/%s_%s", tmpdir, perfdir, user);
+
+ return dirname;
+}
+
+// convert the given file name into a process id. if the file
+// does not meet the file naming constraints, return 0.
+//
+static pid_t filename_to_pid(const char* filename) {
+
+ // a filename that doesn't begin with a digit is not a
+ // candidate for conversion.
+ //
+ if (!isdigit(*filename)) {
+ return 0;
+ }
+
+ // check if file name can be converted to an integer without
+ // any leftover characters.
+ //
+ char* remainder = NULL;
+ errno = 0;
+ pid_t pid = (pid_t)strtol(filename, &remainder, 10);
+
+ if (errno != 0) {
+ return 0;
+ }
+
+ // check for left over characters. If any, then the filename is
+ // not a candidate for conversion.
+ //
+ if (remainder != NULL && *remainder != '\0') {
+ return 0;
+ }
+
+ // successful conversion, return the pid
+ return pid;
+}
+
+
+// check if the given path is considered a secure directory for
+// the backing store files. Returns true if the directory exists
+// and is considered a secure location. Returns false if the path
+// is a symbolic link or if an error occurred.
+//
+static bool is_directory_secure(const char* path) {
+ struct stat statbuf;
+ int result = 0;
+
+ RESTARTABLE(::lstat(path, &statbuf), result);
+ if (result == OS_ERR) {
+ return false;
+ }
+
+ // the path exists, now check it's mode
+ if (S_ISLNK(statbuf.st_mode) || !S_ISDIR(statbuf.st_mode)) {
+ // the path represents a link or some non-directory file type,
+ // which is not what we expected. declare it insecure.
+ //
+ return false;
+ }
+ else {
+ // we have an existing directory, check if the permissions are safe.
+ //
+ if ((statbuf.st_mode & (S_IWGRP|S_IWOTH)) != 0) {
+ // the directory is open for writing and could be subjected
+ // to a symlnk attack. declare it insecure.
+ //
+ return false;
+ }
+ }
+ return true;
+}
+
+
+// return the user name for the given user id
+//
+// the caller is expected to free the allocated memory.
+//
+static char* get_user_name(uid_t uid) {
+
+ struct passwd pwent;
+
+ // determine the max pwbuf size from sysconf, and hardcode
+ // a default if this not available through sysconf.
+ //
+ long bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
+ if (bufsize == -1)
+ bufsize = 1024;
+
+ char* pwbuf = NEW_C_HEAP_ARRAY(char, bufsize);
+
+ // POSIX interface to getpwuid_r is used on LINUX
+ struct passwd* p;
+ int result = getpwuid_r(uid, &pwent, pwbuf, (size_t)bufsize, &p);
+
+ if (result != 0 || p == NULL || p->pw_name == NULL || *(p->pw_name) == '\0') {
+ if (PrintMiscellaneous && Verbose) {
+ if (result != 0) {
+ warning("Could not retrieve passwd entry: %s\n",
+ strerror(result));
+ }
+ else if (p == NULL) {
+ // this check is added to protect against an observed problem
+ // with getpwuid_r() on RedHat 9 where getpwuid_r returns 0,
+ // indicating success, but has p == NULL. This was observed when
+ // inserting a file descriptor exhaustion fault prior to the call
+ // getpwuid_r() call. In this case, error is set to the appropriate
+ // error condition, but this is undocumented behavior. This check
+ // is safe under any condition, but the use of errno in the output
+ // message may result in an erroneous message.
+ // Bug Id 89052 was opened with RedHat.
+ //
+ warning("Could not retrieve passwd entry: %s\n",
+ strerror(errno));
+ }
+ else {
+ warning("Could not determine user name: %s\n",
+ p->pw_name == NULL ? "pw_name = NULL" :
+ "pw_name zero length");
+ }
+ }
+ FREE_C_HEAP_ARRAY(char, pwbuf);
+ return NULL;
+ }
+
+ char* user_name = NEW_C_HEAP_ARRAY(char, strlen(p->pw_name) + 1);
+ strcpy(user_name, p->pw_name);
+
+ FREE_C_HEAP_ARRAY(char, pwbuf);
+ return user_name;
+}
+
+// return the name of the user that owns the process identified by vmid.
+//
+// This method uses a slow directory search algorithm to find the backing
+// store file for the specified vmid and returns the user name, as determined
+// by the user name suffix of the hsperfdata_<username> directory name.
+//
+// the caller is expected to free the allocated memory.
+//
+static char* get_user_name_slow(int vmid, TRAPS) {
+
+ // short circuit the directory search if the process doesn't even exist.
+ if (kill(vmid, 0) == OS_ERR) {
+ if (errno == ESRCH) {
+ THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
+ "Process not found");
+ }
+ else /* EPERM */ {
+ THROW_MSG_0(vmSymbols::java_io_IOException(), strerror(errno));
+ }
+ }
+
+ // directory search
+ char* oldest_user = NULL;
+ time_t oldest_ctime = 0;
+
+ const char* tmpdirname = os::get_temp_directory();
+
+ DIR* tmpdirp = os::opendir(tmpdirname);
+
+ if (tmpdirp == NULL) {
+ return NULL;
+ }
+
+ // for each entry in the directory that matches the pattern hsperfdata_*,
+ // open the directory and check if the file for the given vmid exists.
+ // The file with the expected name and the latest creation date is used
+ // to determine the user name for the process id.
+ //
+ struct dirent* dentry;
+ char* tdbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(tmpdirname));
+ errno = 0;
+ while ((dentry = os::readdir(tmpdirp, (struct dirent *)tdbuf)) != NULL) {
+
+ // check if the directory entry is a hsperfdata file
+ if (strncmp(dentry->d_name, PERFDATA_NAME, strlen(PERFDATA_NAME)) != 0) {
+ continue;
+ }
+
+ char* usrdir_name = NEW_C_HEAP_ARRAY(char,
+ strlen(tmpdirname) + strlen(dentry->d_name) + 2);
+ strcpy(usrdir_name, tmpdirname);
+ strcat(usrdir_name, "/");
+ strcat(usrdir_name, dentry->d_name);
+
+ DIR* subdirp = os::opendir(usrdir_name);
+
+ if (subdirp == NULL) {
+ FREE_C_HEAP_ARRAY(char, usrdir_name);
+ continue;
+ }
+
+ // Since we don't create the backing store files in directories
+ // pointed to by symbolic links, we also don't follow them when
+ // looking for the files. We check for a symbolic link after the
+ // call to opendir in order to eliminate a small window where the
+ // symlink can be exploited.
+ //
+ if (!is_directory_secure(usrdir_name)) {
+ FREE_C_HEAP_ARRAY(char, usrdir_name);
+ os::closedir(subdirp);
+ continue;
+ }
+
+ struct dirent* udentry;
+ char* udbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(usrdir_name));
+ errno = 0;
+ while ((udentry = os::readdir(subdirp, (struct dirent *)udbuf)) != NULL) {
+
+ if (filename_to_pid(udentry->d_name) == vmid) {
+ struct stat statbuf;
+ int result;
+
+ char* filename = NEW_C_HEAP_ARRAY(char,
+ strlen(usrdir_name) + strlen(udentry->d_name) + 2);
+
+ strcpy(filename, usrdir_name);
+ strcat(filename, "/");
+ strcat(filename, udentry->d_name);
+
+ // don't follow symbolic links for the file
+ RESTARTABLE(::lstat(filename, &statbuf), result);
+ if (result == OS_ERR) {
+ FREE_C_HEAP_ARRAY(char, filename);
+ continue;
+ }
+
+ // skip over files that are not regular files.
+ if (!S_ISREG(statbuf.st_mode)) {
+ FREE_C_HEAP_ARRAY(char, filename);
+ continue;
+ }
+
+ // compare and save filename with latest creation time
+ if (statbuf.st_size > 0 && statbuf.st_ctime > oldest_ctime) {
+
+ if (statbuf.st_ctime > oldest_ctime) {
+ char* user = strchr(dentry->d_name, '_') + 1;
+
+ if (oldest_user != NULL) FREE_C_HEAP_ARRAY(char, oldest_user);
+ oldest_user = NEW_C_HEAP_ARRAY(char, strlen(user)+1);
+
+ strcpy(oldest_user, user);
+ oldest_ctime = statbuf.st_ctime;
+ }
+ }
+
+ FREE_C_HEAP_ARRAY(char, filename);
+ }
+ }
+ os::closedir(subdirp);
+ FREE_C_HEAP_ARRAY(char, udbuf);
+ FREE_C_HEAP_ARRAY(char, usrdir_name);
+ }
+ os::closedir(tmpdirp);
+ FREE_C_HEAP_ARRAY(char, tdbuf);
+
+ return(oldest_user);
+}
+
+// return the name of the user that owns the JVM indicated by the given vmid.
+//
+static char* get_user_name(int vmid, TRAPS) {
+ return get_user_name_slow(vmid, CHECK_NULL);
+}
+
+// return the file name of the backing store file for the named
+// shared memory region for the given user name and vmid.
+//
+// the caller is expected to free the allocated memory.
+//
+static char* get_sharedmem_filename(const char* dirname, int vmid) {
+
+ // add 2 for the file separator and a null terminator.
+ size_t nbytes = strlen(dirname) + UINT_CHARS + 2;
+
+ char* name = NEW_C_HEAP_ARRAY(char, nbytes);
+ snprintf(name, nbytes, "%s/%d", dirname, vmid);
+
+ return name;
+}
+
+
+// remove file
+//
+// this method removes the file specified by the given path
+//
+static void remove_file(const char* path) {
+
+ int result;
+
+ // if the file is a directory, the following unlink will fail. since
+ // we don't expect to find directories in the user temp directory, we
+ // won't try to handle this situation. even if accidentially or
+ // maliciously planted, the directory's presence won't hurt anything.
+ //
+ RESTARTABLE(::unlink(path), result);
+ if (PrintMiscellaneous && Verbose && result == OS_ERR) {
+ if (errno != ENOENT) {
+ warning("Could not unlink shared memory backing"
+ " store file %s : %s\n", path, strerror(errno));
+ }
+ }
+}
+
+
+// remove file
+//
+// this method removes the file with the given file name in the
+// named directory.
+//
+static void remove_file(const char* dirname, const char* filename) {
+
+ size_t nbytes = strlen(dirname) + strlen(filename) + 2;
+ char* path = NEW_C_HEAP_ARRAY(char, nbytes);
+
+ strcpy(path, dirname);
+ strcat(path, "/");
+ strcat(path, filename);
+
+ remove_file(path);
+
+ FREE_C_HEAP_ARRAY(char, path);
+}
+
+
+// cleanup stale shared memory resources
+//
+// This method attempts to remove all stale shared memory files in
+// the named user temporary directory. It scans the named directory
+// for files matching the pattern ^$[0-9]*$. For each file found, the
+// process id is extracted from the file name and a test is run to
+// determine if the process is alive. If the process is not alive,
+// any stale file resources are removed.
+//
+static void cleanup_sharedmem_resources(const char* dirname) {
+
+ // open the user temp directory
+ DIR* dirp = os::opendir(dirname);
+
+ if (dirp == NULL) {
+ // directory doesn't exist, so there is nothing to cleanup
+ return;
+ }
+
+ if (!is_directory_secure(dirname)) {
+ // the directory is not a secure directory
+ return;
+ }
+
+ // for each entry in the directory that matches the expected file
+ // name pattern, determine if the file resources are stale and if
+ // so, remove the file resources. Note, instrumented HotSpot processes
+ // for this user may start and/or terminate during this search and
+ // remove or create new files in this directory. The behavior of this
+ // loop under these conditions is dependent upon the implementation of
+ // opendir/readdir.
+ //
+ struct dirent* entry;
+ char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname));
+ errno = 0;
+ while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) {
+
+ pid_t pid = filename_to_pid(entry->d_name);
+
+ if (pid == 0) {
+
+ if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
+
+ // attempt to remove all unexpected files, except "." and ".."
+ remove_file(dirname, entry->d_name);
+ }
+
+ errno = 0;
+ continue;
+ }
+
+ // we now have a file name that converts to a valid integer
+ // that could represent a process id . if this process id
+ // matches the current process id or the process is not running,
+ // then remove the stale file resources.
+ //
+ // process liveness is detected by sending signal number 0 to
+ // the process id (see kill(2)). if kill determines that the
+ // process does not exist, then the file resources are removed.
+ // if kill determines that that we don't have permission to
+ // signal the process, then the file resources are assumed to
+ // be stale and are removed because the resources for such a
+ // process should be in a different user specific directory.
+ //
+ if ((pid == os::current_process_id()) ||
+ (kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) {
+
+ remove_file(dirname, entry->d_name);
+ }
+ errno = 0;
+ }
+ os::closedir(dirp);
+ FREE_C_HEAP_ARRAY(char, dbuf);
+}
+
+// make the user specific temporary directory. Returns true if
+// the directory exists and is secure upon return. Returns false
+// if the directory exists but is either a symlink, is otherwise
+// insecure, or if an error occurred.
+//
+static bool make_user_tmp_dir(const char* dirname) {
+
+ // create the directory with 0755 permissions. note that the directory
+ // will be owned by euid::egid, which may not be the same as uid::gid.
+ //
+ if (mkdir(dirname, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) == OS_ERR) {
+ if (errno == EEXIST) {
+ // The directory already exists and was probably created by another
+ // JVM instance. However, this could also be the result of a
+ // deliberate symlink. Verify that the existing directory is safe.
+ //
+ if (!is_directory_secure(dirname)) {
+ // directory is not secure
+ if (PrintMiscellaneous && Verbose) {
+ warning("%s directory is insecure\n", dirname);
+ }
+ return false;
+ }
+ }
+ else {
+ // we encountered some other failure while attempting
+ // to create the directory
+ //
+ if (PrintMiscellaneous && Verbose) {
+ warning("could not create directory %s: %s\n",
+ dirname, strerror(errno));
+ }
+ return false;
+ }
+ }
+ return true;
+}
+
+// create the shared memory file resources
+//
+// This method creates the shared memory file with the given size
+// This method also creates the user specific temporary directory, if
+// it does not yet exist.
+//
+static int create_sharedmem_resources(const char* dirname, const char* filename, size_t size) {
+
+ // make the user temporary directory
+ if (!make_user_tmp_dir(dirname)) {
+ // could not make/find the directory or the found directory
+ // was not secure
+ return -1;
+ }
+
+ int result;
+
+ RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE), result);
+ if (result == OS_ERR) {
+ if (PrintMiscellaneous && Verbose) {
+ warning("could not create file %s: %s\n", filename, strerror(errno));
+ }
+ return -1;
+ }
+
+ // save the file descriptor
+ int fd = result;
+
+ // set the file size
+ RESTARTABLE(::ftruncate(fd, (off_t)size), result);
+ if (result == OS_ERR) {
+ if (PrintMiscellaneous && Verbose) {
+ warning("could not set shared memory file size: %s\n", strerror(errno));
+ }
+ RESTARTABLE(::close(fd), result);
+ return -1;
+ }
+
+ // Verify that we have enough disk space for this file.
+ // We'll get random SIGBUS crashes on memory accesses if
+ // we don't.
+
+ for (size_t seekpos = 0; seekpos < size; seekpos += os::vm_page_size()) {
+ int zero_int = 0;
+ result = (int)os::seek_to_file_offset(fd, (jlong)(seekpos));
+ if (result == -1 ) break;
+ RESTARTABLE(::write(fd, &zero_int, 1), result);
+ if (result != 1) {
+ if (errno == ENOSPC) {
+ warning("Insufficient space for shared memory file:\n %s\nTry using the -Djava.io.tmpdir= option to select an alternate temp location.\n", filename);
+ }
+ break;
+ }
+ }
+
+ if (result != -1) {
+ return fd;
+ } else {
+ RESTARTABLE(::close(fd), result);
+ return -1;
+ }
+}
+
+// open the shared memory file for the given user and vmid. returns
+// the file descriptor for the open file or -1 if the file could not
+// be opened.
+//
+static int open_sharedmem_file(const char* filename, int oflags, TRAPS) {
+
+ // open the file
+ int result;
+ RESTARTABLE(::open(filename, oflags), result);
+ if (result == OS_ERR) {
+ if (errno == ENOENT) {
+ THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
+ "Process not found");
+ }
+ else if (errno == EACCES) {
+ THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
+ "Permission denied");
+ }
+ else {
+ THROW_MSG_0(vmSymbols::java_io_IOException(), strerror(errno));
+ }
+ }
+
+ return result;
+}
+
+// create a named shared memory region. returns the address of the
+// memory region on success or NULL on failure. A return value of
+// NULL will ultimately disable the shared memory feature.
+//
+// On Solaris and Bsd, the name space for shared memory objects
+// is the file system name space.
+//
+// A monitoring application attaching to a JVM does not need to know
+// the file system name of the shared memory object. However, it may
+// be convenient for applications to discover the existence of newly
+// created and terminating JVMs by watching the file system name space
+// for files being created or removed.
+//
+static char* mmap_create_shared(size_t size) {
+
+ int result;
+ int fd;
+ char* mapAddress;
+
+ int vmid = os::current_process_id();
+
+ char* user_name = get_user_name(geteuid());
+
+ if (user_name == NULL)
+ return NULL;
+
+ char* dirname = get_user_tmp_dir(user_name);
+ char* filename = get_sharedmem_filename(dirname, vmid);
+
+ // cleanup any stale shared memory files
+ cleanup_sharedmem_resources(dirname);
+
+ assert(((size > 0) && (size % os::vm_page_size() == 0)),
+ "unexpected PerfMemory region size");
+
+ fd = create_sharedmem_resources(dirname, filename, size);
+
+ FREE_C_HEAP_ARRAY(char, user_name);
+ FREE_C_HEAP_ARRAY(char, dirname);
+
+ if (fd == -1) {
+ FREE_C_HEAP_ARRAY(char, filename);
+ return NULL;
+ }
+
+ mapAddress = (char*)::mmap((char*)0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+
+ // attempt to close the file - restart it if it was interrupted,
+ // but ignore other failures
+ RESTARTABLE(::close(fd), result);
+ assert(result != OS_ERR, "could not close file");
+
+ if (mapAddress == MAP_FAILED) {
+ if (PrintMiscellaneous && Verbose) {
+ warning("mmap failed - %s\n", strerror(errno));
+ }
+ remove_file(filename);
+ FREE_C_HEAP_ARRAY(char, filename);
+ return NULL;
+ }
+
+ // save the file name for use in delete_shared_memory()
+ backing_store_file_name = filename;
+
+ // clear the shared memory region
+ (void)::memset((void*) mapAddress, 0, size);
+
+ return mapAddress;
+}
+
+// release a named shared memory region
+//
+static void unmap_shared(char* addr, size_t bytes) {
+ os::release_memory(addr, bytes);
+}
+
+// create the PerfData memory region in shared memory.
+//
+static char* create_shared_memory(size_t size) {
+
+ // create the shared memory region.
+ return mmap_create_shared(size);
+}
+
+// delete the shared PerfData memory region
+//
+static void delete_shared_memory(char* addr, size_t size) {
+
+ // cleanup the persistent shared memory resources. since DestroyJavaVM does
+ // not support unloading of the JVM, unmapping of the memory resource is
+ // not performed. The memory will be reclaimed by the OS upon termination of
+ // the process. The backing store file is deleted from the file system.
+
+ assert(!PerfDisableSharedMem, "shouldn't be here");
+
+ if (backing_store_file_name != NULL) {
+ remove_file(backing_store_file_name);
+ // Don't.. Free heap memory could deadlock os::abort() if it is called
+ // from signal handler. OS will reclaim the heap memory.
+ // FREE_C_HEAP_ARRAY(char, backing_store_file_name);
+ backing_store_file_name = NULL;
+ }
+}
+
+// return the size of the file for the given file descriptor
+// or 0 if it is not a valid size for a shared memory file
+//
+static size_t sharedmem_filesize(int fd, TRAPS) {
+
+ struct stat statbuf;
+ int result;
+
+ RESTARTABLE(::fstat(fd, &statbuf), result);
+ if (result == OS_ERR) {
+ if (PrintMiscellaneous && Verbose) {
+ warning("fstat failed: %s\n", strerror(errno));
+ }
+ THROW_MSG_0(vmSymbols::java_io_IOException(),
+ "Could not determine PerfMemory size");
+ }
+
+ if ((statbuf.st_size == 0) ||
+ ((size_t)statbuf.st_size % os::vm_page_size() != 0)) {
+ THROW_MSG_0(vmSymbols::java_lang_Exception(),
+ "Invalid PerfMemory size");
+ }
+
+ return (size_t)statbuf.st_size;
+}
+
+// attach to a named shared memory region.
+//
+static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemoryMode mode, char** addr, size_t* sizep, TRAPS) {
+
+ char* mapAddress;
+ int result;
+ int fd;
+ size_t size;
+ const char* luser = NULL;
+
+ int mmap_prot;
+ int file_flags;
+
+ ResourceMark rm;
+
+ // map the high level access mode to the appropriate permission
+ // constructs for the file and the shared memory mapping.
+ if (mode == PerfMemory::PERF_MODE_RO) {
+ mmap_prot = PROT_READ;
+ file_flags = O_RDONLY;
+ }
+ else if (mode == PerfMemory::PERF_MODE_RW) {
+#ifdef LATER
+ mmap_prot = PROT_READ | PROT_WRITE;
+ file_flags = O_RDWR;
+#else
+ THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+ "Unsupported access mode");
+#endif
+ }
+ else {
+ THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+ "Illegal access mode");
+ }
+
+ if (user == NULL || strlen(user) == 0) {
+ luser = get_user_name(vmid, CHECK);
+ }
+ else {
+ luser = user;
+ }
+
+ if (luser == NULL) {
+ THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+ "Could not map vmid to user Name");
+ }
+
+ char* dirname = get_user_tmp_dir(luser);
+
+ // since we don't follow symbolic links when creating the backing
+ // store file, we don't follow them when attaching either.
+ //
+ if (!is_directory_secure(dirname)) {
+ FREE_C_HEAP_ARRAY(char, dirname);
+ THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+ "Process not found");
+ }
+
+ char* filename = get_sharedmem_filename(dirname, vmid);
+
+ // copy heap memory to resource memory. the open_sharedmem_file
+ // method below need to use the filename, but could throw an
+ // exception. using a resource array prevents the leak that
+ // would otherwise occur.
+ char* rfilename = NEW_RESOURCE_ARRAY(char, strlen(filename) + 1);
+ strcpy(rfilename, filename);
+
+ // free the c heap resources that are no longer needed
+ if (luser != user) FREE_C_HEAP_ARRAY(char, luser);
+ FREE_C_HEAP_ARRAY(char, dirname);
+ FREE_C_HEAP_ARRAY(char, filename);
+
+ // open the shared memory file for the give vmid
+ fd = open_sharedmem_file(rfilename, file_flags, CHECK);
+ assert(fd != OS_ERR, "unexpected value");
+
+ if (*sizep == 0) {
+ size = sharedmem_filesize(fd, CHECK);
+ assert(size != 0, "unexpected size");
+ }
+
+ mapAddress = (char*)::mmap((char*)0, size, mmap_prot, MAP_SHARED, fd, 0);
+
+ // attempt to close the file - restart if it gets interrupted,
+ // but ignore other failures
+ RESTARTABLE(::close(fd), result);
+ assert(result != OS_ERR, "could not close file");
+
+ if (mapAddress == MAP_FAILED) {
+ if (PrintMiscellaneous && Verbose) {
+ warning("mmap failed: %s\n", strerror(errno));
+ }
+ THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(),
+ "Could not map PerfMemory");
+ }
+
+ *addr = mapAddress;
+ *sizep = size;
+
+ if (PerfTraceMemOps) {
+ tty->print("mapped " SIZE_FORMAT " bytes for vmid %d at "
+ INTPTR_FORMAT "\n", size, vmid, (void*)mapAddress);
+ }
+}
+
+
+
+
+// create the PerfData memory region
+//
+// This method creates the memory region used to store performance
+// data for the JVM. The memory may be created in standard or
+// shared memory.
+//
+void PerfMemory::create_memory_region(size_t size) {
+
+ if (PerfDisableSharedMem) {
+ // do not share the memory for the performance data.
+ _start = create_standard_memory(size);
+ }
+ else {
+ _start = create_shared_memory(size);
+ if (_start == NULL) {
+
+ // creation of the shared memory region failed, attempt
+ // to create a contiguous, non-shared memory region instead.
+ //
+ if (PrintMiscellaneous && Verbose) {
+ warning("Reverting to non-shared PerfMemory region.\n");
+ }
+ PerfDisableSharedMem = true;
+ _start = create_standard_memory(size);
+ }
+ }
+
+ if (_start != NULL) _capacity = size;
+
+}
+
+// delete the PerfData memory region
+//
+// This method deletes the memory region used to store performance
+// data for the JVM. The memory region indicated by the <address, size>
+// tuple will be inaccessible after a call to this method.
+//
+void PerfMemory::delete_memory_region() {
+
+ assert((start() != NULL && capacity() > 0), "verify proper state");
+
+ // If user specifies PerfDataSaveFile, it will save the performance data
+ // to the specified file name no matter whether PerfDataSaveToFile is specified
+ // or not. In other word, -XX:PerfDataSaveFile=.. overrides flag
+ // -XX:+PerfDataSaveToFile.
+ if (PerfDataSaveToFile || PerfDataSaveFile != NULL) {
+ save_memory_to_file(start(), capacity());
+ }
+
+ if (PerfDisableSharedMem) {
+ delete_standard_memory(start(), capacity());
+ }
+ else {
+ delete_shared_memory(start(), capacity());
+ }
+}
+
+// attach to the PerfData memory region for another JVM
+//
+// This method returns an <address, size> tuple that points to
+// a memory buffer that is kept reasonably synchronized with
+// the PerfData memory region for the indicated JVM. This
+// buffer may be kept in synchronization via shared memory
+// or some other mechanism that keeps the buffer updated.
+//
+// If the JVM chooses not to support the attachability feature,
+// this method should throw an UnsupportedOperation exception.
+//
+// This implementation utilizes named shared memory to map
+// the indicated process's PerfData memory region into this JVMs
+// address space.
+//
+void PerfMemory::attach(const char* user, int vmid, PerfMemoryMode mode, char** addrp, size_t* sizep, TRAPS) {
+
+ if (vmid == 0 || vmid == os::current_process_id()) {
+ *addrp = start();
+ *sizep = capacity();
+ return;
+ }
+
+ mmap_attach_shared(user, vmid, mode, addrp, sizep, CHECK);
+}
+
+// detach from the PerfData memory region of another JVM
+//
+// This method detaches the PerfData memory region of another
+// JVM, specified as an <address, size> tuple of a buffer
+// in this process's address space. This method may perform
+// arbitrary actions to accomplish the detachment. The memory
+// region specified by <address, size> will be inaccessible after
+// a call to this method.
+//
+// If the JVM chooses not to support the attachability feature,
+// this method should throw an UnsupportedOperation exception.
+//
+// This implementation utilizes named shared memory to detach
+// the indicated process's PerfData memory region from this
+// process's address space.
+//
+void PerfMemory::detach(char* addr, size_t bytes, TRAPS) {
+
+ assert(addr != 0, "address sanity check");
+ assert(bytes > 0, "capacity sanity check");
+
+ if (PerfMemory::contains(addr) || PerfMemory::contains(addr + bytes - 1)) {
+ // prevent accidental detachment of this process's PerfMemory region
+ return;
+ }
+
+ unmap_shared(addr, bytes);
+}
+
+char* PerfMemory::backing_store_filename() {
+ return backing_store_file_name;
+}
diff --git a/src/os/bsd/vm/stubRoutines_bsd.cpp b/src/os/bsd/vm/stubRoutines_bsd.cpp
new file mode 100644
index 000000000..1fa7d3a9f
--- /dev/null
+++ b/src/os/bsd/vm/stubRoutines_bsd.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "runtime/os.hpp"
+#include "runtime/stubRoutines.hpp"
diff --git a/src/os/bsd/vm/threadCritical_bsd.cpp b/src/os/bsd/vm/threadCritical_bsd.cpp
new file mode 100644
index 000000000..e337a5bd5
--- /dev/null
+++ b/src/os/bsd/vm/threadCritical_bsd.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "runtime/threadCritical.hpp"
+#include "thread_bsd.inline.hpp"
+
+// put OS-includes here
+# include <pthread.h>
+
+//
+// See threadCritical.hpp for details of this class.
+//
+
+static pthread_t tc_owner = 0;
+static pthread_mutex_t tc_mutex = PTHREAD_MUTEX_INITIALIZER;
+static int tc_count = 0;
+
+void ThreadCritical::initialize() {
+}
+
+void ThreadCritical::release() {
+}
+
+ThreadCritical::ThreadCritical() {
+ pthread_t self = pthread_self();
+ if (self != tc_owner) {
+ int ret = pthread_mutex_lock(&tc_mutex);
+ guarantee(ret == 0, "fatal error with pthread_mutex_lock()");
+ assert(tc_count == 0, "Lock acquired with illegal reentry count.");
+ tc_owner = self;
+ }
+ tc_count++;
+}
+
+ThreadCritical::~ThreadCritical() {
+ assert(tc_owner == pthread_self(), "must have correct owner");
+ assert(tc_count > 0, "must have correct count");
+
+ tc_count--;
+ if (tc_count == 0) {
+ tc_owner = 0;
+ int ret = pthread_mutex_unlock(&tc_mutex);
+ guarantee(ret == 0, "fatal error with pthread_mutex_unlock()");
+ }
+}
diff --git a/src/os/bsd/vm/thread_bsd.inline.hpp b/src/os/bsd/vm/thread_bsd.inline.hpp
new file mode 100644
index 000000000..290f47786
--- /dev/null
+++ b/src/os/bsd/vm/thread_bsd.inline.hpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef OS_BSD_VM_THREAD_BSD_INLINE_HPP
+#define OS_BSD_VM_THREAD_BSD_INLINE_HPP
+
+#include "runtime/atomic.hpp"
+#include "runtime/prefetch.hpp"
+#include "runtime/thread.hpp"
+#include "runtime/threadLocalStorage.hpp"
+#ifdef TARGET_OS_ARCH_bsd_x86
+# include "atomic_bsd_x86.inline.hpp"
+# include "orderAccess_bsd_x86.inline.hpp"
+# include "prefetch_bsd_x86.inline.hpp"
+#endif
+#ifdef TARGET_OS_ARCH_bsd_zero
+# include "atomic_bsd_zero.inline.hpp"
+# include "orderAccess_bsd_zero.inline.hpp"
+# include "prefetch_bsd_zero.inline.hpp"
+#endif
+
+// Contains inlined functions for class Thread and ThreadLocalStorage
+
+inline void ThreadLocalStorage::pd_invalidate_all() {} // nothing to do
+
+#endif // OS_BSD_VM_THREAD_BSD_INLINE_HPP
diff --git a/src/os/bsd/vm/vmError_bsd.cpp b/src/os/bsd/vm/vmError_bsd.cpp
new file mode 100644
index 000000000..8ec6ca04c
--- /dev/null
+++ b/src/os/bsd/vm/vmError_bsd.cpp
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "runtime/arguments.hpp"
+#include "runtime/os.hpp"
+#include "runtime/thread.hpp"
+#include "utilities/vmError.hpp"
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <signal.h>
+
+void VMError::show_message_box(char *buf, int buflen) {
+ bool yes;
+ do {
+ error_string(buf, buflen);
+ int len = (int)strlen(buf);
+ char *p = &buf[len];
+
+ jio_snprintf(p, buflen - len,
+ "\n\n"
+ "Do you want to debug the problem?\n\n"
+ "To debug, run 'gdb /proc/%d/exe %d'; then switch to thread " INTX_FORMAT " (" INTPTR_FORMAT ")\n"
+ "Enter 'yes' to launch gdb automatically (PATH must include gdb)\n"
+ "Otherwise, press RETURN to abort...",
+ os::current_process_id(), os::current_process_id(),
+ os::current_thread_id(), os::current_thread_id());
+
+ yes = os::message_box("Unexpected Error", buf);
+
+ if (yes) {
+ // yes, user asked VM to launch debugger
+ jio_snprintf(buf, buflen, "gdb /proc/%d/exe %d",
+ os::current_process_id(), os::current_process_id());
+
+ os::fork_and_exec(buf);
+ yes = false;
+ }
+ } while (yes);
+}
+
+// Space for our "saved" signal flags and handlers
+static int resettedSigflags[2];
+static address resettedSighandler[2];
+
+static void save_signal(int idx, int sig)
+{
+ struct sigaction sa;
+ sigaction(sig, NULL, &sa);
+ resettedSigflags[idx] = sa.sa_flags;
+ resettedSighandler[idx] = (sa.sa_flags & SA_SIGINFO)
+ ? CAST_FROM_FN_PTR(address, sa.sa_sigaction)
+ : CAST_FROM_FN_PTR(address, sa.sa_handler);
+}
+
+int VMError::get_resetted_sigflags(int sig) {
+ if(SIGSEGV == sig) {
+ return resettedSigflags[0];
+ } else if(SIGBUS == sig) {
+ return resettedSigflags[1];
+ }
+ return -1;
+}
+
+address VMError::get_resetted_sighandler(int sig) {
+ if(SIGSEGV == sig) {
+ return resettedSighandler[0];
+ } else if(SIGBUS == sig) {
+ return resettedSighandler[1];
+ }
+ return NULL;
+}
+
+static void crash_handler(int sig, siginfo_t* info, void* ucVoid) {
+ // unmask current signal
+ sigset_t newset;
+ sigemptyset(&newset);
+ sigaddset(&newset, sig);
+ sigprocmask(SIG_UNBLOCK, &newset, NULL);
+
+ VMError err(NULL, sig, NULL, info, ucVoid);
+ err.report_and_die();
+}
+
+void VMError::reset_signal_handlers() {
+ // Save sigflags for resetted signals
+ save_signal(0, SIGSEGV);
+ save_signal(1, SIGBUS);
+ os::signal(SIGSEGV, CAST_FROM_FN_PTR(void *, crash_handler));
+ os::signal(SIGBUS, CAST_FROM_FN_PTR(void *, crash_handler));
+}
diff --git a/src/os/linux/vm/os_linux.cpp b/src/os/linux/vm/os_linux.cpp
index be867d366..5a5087301 100644
--- a/src/os/linux/vm/os_linux.cpp
+++ b/src/os/linux/vm/os_linux.cpp
@@ -22,8 +22,6 @@
*
*/
-# define __STDC_FORMAT_MACROS
-
// no precompiled headers
#include "classfile/classLoader.hpp"
#include "classfile/systemDictionary.hpp"
diff --git a/src/os/posix/launcher/java_md.c b/src/os/posix/launcher/java_md.c
index 3ee0f20a7..63cee98e3 100644
--- a/src/os/posix/launcher/java_md.c
+++ b/src/os/posix/launcher/java_md.c
@@ -41,14 +41,21 @@
#include "version_comp.h"
#endif
-#ifdef __linux__
+#if defined(__linux__) || defined(_ALLBSD_SOURCE)
#include <pthread.h>
#else
#include <thread.h>
#endif
+#ifdef __APPLE__
+#define JVM_DLL "libjvm.dylib"
+#define JAVA_DLL "libjava.dylib"
+#define LD_LIBRARY_PATH "DYLD_LIBRARY_PATH"
+#else
#define JVM_DLL "libjvm.so"
#define JAVA_DLL "libjava.so"
+#define LD_LIBRARY_PATH "LD_LIBRARY_PATH"
+#endif
#ifndef GAMMA /* launcher.make defines ARCH */
/*
@@ -423,10 +430,10 @@ CreateExecutionEnvironment(int *_argcp,
* If not on Solaris, assume only a single LD_LIBRARY_PATH
* variable.
*/
- runpath = getenv("LD_LIBRARY_PATH");
+ runpath = getenv(LD_LIBRARY_PATH);
#endif /* __sun */
-#ifdef __linux
+#if defined(__linux__)
/*
* On linux, if a binary is running as sgid or suid, glibc sets
* LD_LIBRARY_PATH to the empty string for security purposes. (In
@@ -442,6 +449,22 @@ CreateExecutionEnvironment(int *_argcp,
if((getgid() != getegid()) || (getuid() != geteuid()) ) {
return;
}
+#elif defined(_ALLBSD_SOURCE)
+ /*
+ * On BSD, if a binary is running as sgid or suid, libc sets
+ * LD_LIBRARY_PATH to the empty string for security purposes. (In
+ * contrast, on Solaris the LD_LIBRARY_PATH variable for a
+ * privileged binary does not lose its settings; but the dynamic
+ * linker does apply more scrutiny to the path.) The launcher uses
+ * the value of LD_LIBRARY_PATH to prevent an exec loop.
+ * Therefore, if we are running sgid or suid, this function's
+ * setting of LD_LIBRARY_PATH will be ineffective and we should
+ * return from the function now. Getting the right libraries to
+ * be found must be handled through other mechanisms.
+ */
+ if(issetugid()) {
+ return;
+ }
#endif
/* runpath contains current effective LD_LIBRARY_PATH setting */
@@ -450,7 +473,7 @@ CreateExecutionEnvironment(int *_argcp,
new_runpath = JLI_MemAlloc( ((runpath!=NULL)?strlen(runpath):0) +
2*strlen(jrepath) + 2*strlen(arch) +
strlen(jvmpath) + 52);
- newpath = new_runpath + strlen("LD_LIBRARY_PATH=");
+ newpath = new_runpath + strlen(LD_LIBRARY_PATH "=");
/*
@@ -465,7 +488,7 @@ CreateExecutionEnvironment(int *_argcp,
/* jvmpath, ((running != wanted)?((wanted==64)?"/"LIBARCH64NAME:"/.."):""), */
- sprintf(new_runpath, "LD_LIBRARY_PATH="
+ sprintf(new_runpath, LD_LIBRARY_PATH "="
"%s:"
"%s/lib/%s:"
"%s/../lib/%s",
@@ -792,7 +815,7 @@ error:
jboolean
GetApplicationHome(char *buf, jint bufsize)
{
-#ifdef __linux__
+#if defined(__linux__) || defined(_ALLBSD_SOURCE)
char *execname = GetExecname();
if (execname) {
strncpy(buf, execname, bufsize-1);
@@ -1175,7 +1198,7 @@ get_cpuid(uint32_t arg,
#endif /* __sun && i586 */
-#if defined(__linux__) && defined(i586)
+#if (defined(__linux__) || defined(_ALLBSD_SOURCE)) && defined(i586)
/*
* A utility method for asking the CPU about itself.
@@ -1452,6 +1475,39 @@ linux_i586_ServerClassMachine(void) {
#endif /* __linux__ && i586 */
+#if defined(_ALLBSD_SOURCE) && defined(i586)
+
+/* The definition of a server-class machine for bsd-i586 */
+jboolean
+bsd_i586_ServerClassMachine(void) {
+ jboolean result = JNI_FALSE;
+ /* How big is a server class machine? */
+ const unsigned long server_processors = 2UL;
+ const uint64_t server_memory = 2UL * GB;
+ /*
+ * We seem not to get our full complement of memory.
+ * We allow some part (1/8?) of the memory to be "missing",
+ * based on the sizes of DIMMs, and maybe graphics cards.
+ */
+ const uint64_t missing_memory = 256UL * MB;
+ const uint64_t actual_memory = physical_memory();
+
+ /* Is this a server class machine? */
+ if (actual_memory >= (server_memory - missing_memory)) {
+ const unsigned long actual_processors = physical_processors();
+ if (actual_processors >= server_processors) {
+ result = JNI_TRUE;
+ }
+ }
+ if (_launcher_debug) {
+ printf("linux_" LIBARCHNAME "_ServerClassMachine: %s\n",
+ (result == JNI_TRUE ? "true" : "false"));
+ }
+ return result;
+}
+
+#endif /* _ALLBSD_SOURCE && i586 */
+
/* Dispatch to the platform-specific definition of "server-class" */
jboolean
ServerClassMachine(void) {
@@ -1466,6 +1522,8 @@ ServerClassMachine(void) {
result = solaris_i586_ServerClassMachine();
#elif defined(__linux__) && defined(i586)
result = linux_i586_ServerClassMachine();
+#elif defined(_ALLBSD_SOURCE) && defined(i586)
+ result = bsd_i586_ServerClassMachine();
#else
if (_launcher_debug) {
printf("ServerClassMachine: returns default value of %s\n",
@@ -1821,7 +1879,7 @@ jlong_format_specifier() {
int
ContinueInNewThread(int (JNICALL *continuation)(void *), jlong stack_size, void * args) {
int rslt;
-#ifdef __linux__
+#if defined(__linux__) || defined(_ALLBSD_SOURCE)
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
diff --git a/src/os/posix/launcher/launcher.script b/src/os/posix/launcher/launcher.script
index 22ed66b9c..21bf44e92 100644
--- a/src/os/posix/launcher/launcher.script
+++ b/src/os/posix/launcher/launcher.script
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
diff --git a/src/os_cpu/bsd_x86/vm/assembler_bsd_x86.cpp b/src/os_cpu/bsd_x86/vm/assembler_bsd_x86.cpp
new file mode 100644
index 000000000..5cd941075
--- /dev/null
+++ b/src/os_cpu/bsd_x86/vm/assembler_bsd_x86.cpp
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ *
+ * 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 "precompiled.hpp"
+#include "asm/assembler.hpp"
+#include "assembler_x86.inline.hpp"
+#include "runtime/os.hpp"
+#include "runtime/threadLocalStorage.hpp"
+
+#ifndef _LP64
+void MacroAssembler::int3() {
+ call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint)));
+}
+
+void MacroAssembler::get_thread(Register thread) {
+ movl(thread, rsp);
+ shrl(thread, PAGE_SHIFT);
+
+ ExternalAddress tls_base((address)ThreadLocalStorage::sp_map_addr());
+ Address index(noreg, thread, Address::times_4);
+ ArrayAddress tls(tls_base, index);
+
+ movptr(thread, tls);
+}
+#else
+void MacroAssembler::int3() {
+ call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint)));
+}
+
+void MacroAssembler::get_thread(Register thread) {
+ // call pthread_getspecific
+ // void * pthread_getspecific(pthread_key_t key);
+ if (thread != rax) {
+ push(rax);
+ }
+ push(rdi);
+ push(rsi);
+ push(rdx);
+ push(rcx);
+ push(r8);
+ push(r9);
+ push(r10);
+ // XXX
+ mov(r10, rsp);
+ andq(rsp, -16);
+ push(r10);
+ push(r11);
+
+ movl(rdi, ThreadLocalStorage::thread_index());
+ call(RuntimeAddress(CAST_FROM_FN_PTR(address, pthread_getspecific)));
+
+ pop(r11);
+ pop(rsp);
+ pop(r10);
+ pop(r9);
+ pop(r8);
+ pop(rcx);
+ pop(rdx);
+ pop(rsi);
+ pop(rdi);
+ if (thread != rax) {
+ mov(thread, rax);
+ pop(rax);
+ }
+}
+#endif
diff --git a/src/os_cpu/bsd_x86/vm/atomic_bsd_x86.inline.hpp b/src/os_cpu/bsd_x86/vm/atomic_bsd_x86.inline.hpp
new file mode 100644
index 000000000..aa4719619
--- /dev/null
+++ b/src/os_cpu/bsd_x86/vm/atomic_bsd_x86.inline.hpp
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef OS_CPU_BSD_X86_VM_ATOMIC_BSD_X86_INLINE_HPP
+#define OS_CPU_BSD_X86_VM_ATOMIC_BSD_X86_INLINE_HPP
+
+#include "orderAccess_bsd_x86.inline.hpp"
+#include "runtime/atomic.hpp"
+#include "runtime/os.hpp"
+#include "vm_version_x86.hpp"
+
+// Implementation of class atomic
+
+inline void Atomic::store (jbyte store_value, jbyte* dest) { *dest = store_value; }
+inline void Atomic::store (jshort store_value, jshort* dest) { *dest = store_value; }
+inline void Atomic::store (jint store_value, jint* dest) { *dest = store_value; }
+inline void Atomic::store_ptr(intptr_t store_value, intptr_t* dest) { *dest = store_value; }
+inline void Atomic::store_ptr(void* store_value, void* dest) { *(void**)dest = store_value; }
+
+inline void Atomic::store (jbyte store_value, volatile jbyte* dest) { *dest = store_value; }
+inline void Atomic::store (jshort store_value, volatile jshort* dest) { *dest = store_value; }
+inline void Atomic::store (jint store_value, volatile jint* dest) { *dest = store_value; }
+inline void Atomic::store_ptr(intptr_t store_value, volatile intptr_t* dest) { *dest = store_value; }
+inline void Atomic::store_ptr(void* store_value, volatile void* dest) { *(void* volatile *)dest = store_value; }
+
+
+// Adding a lock prefix to an instruction on MP machine
+#define LOCK_IF_MP(mp) "cmp $0, " #mp "; je 1f; lock; 1: "
+
+inline jint Atomic::add (jint add_value, volatile jint* dest) {
+ jint addend = add_value;
+ int mp = os::is_MP();
+ __asm__ volatile ( LOCK_IF_MP(%3) "xaddl %0,(%2)"
+ : "=r" (addend)
+ : "0" (addend), "r" (dest), "r" (mp)
+ : "cc", "memory");
+ return addend + add_value;
+}
+
+inline void Atomic::inc (volatile jint* dest) {
+ int mp = os::is_MP();
+ __asm__ volatile (LOCK_IF_MP(%1) "addl $1,(%0)" :
+ : "r" (dest), "r" (mp) : "cc", "memory");
+}
+
+inline void Atomic::inc_ptr(volatile void* dest) {
+ inc_ptr((volatile intptr_t*)dest);
+}
+
+inline void Atomic::dec (volatile jint* dest) {
+ int mp = os::is_MP();
+ __asm__ volatile (LOCK_IF_MP(%1) "subl $1,(%0)" :
+ : "r" (dest), "r" (mp) : "cc", "memory");
+}
+
+inline void Atomic::dec_ptr(volatile void* dest) {
+ dec_ptr((volatile intptr_t*)dest);
+}
+
+inline jint Atomic::xchg (jint exchange_value, volatile jint* dest) {
+ __asm__ volatile ( "xchgl (%2),%0"
+ : "=r" (exchange_value)
+ : "0" (exchange_value), "r" (dest)
+ : "memory");
+ return exchange_value;
+}
+
+inline void* Atomic::xchg_ptr(void* exchange_value, volatile void* dest) {
+ return (void*)xchg_ptr((intptr_t)exchange_value, (volatile intptr_t*)dest);
+}
+
+
+inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value) {
+ int mp = os::is_MP();
+ __asm__ volatile (LOCK_IF_MP(%4) "cmpxchgl %1,(%3)"
+ : "=a" (exchange_value)
+ : "r" (exchange_value), "a" (compare_value), "r" (dest), "r" (mp)
+ : "cc", "memory");
+ return exchange_value;
+}
+
+#ifdef AMD64
+inline void Atomic::store (jlong store_value, jlong* dest) { *dest = store_value; }
+inline void Atomic::store (jlong store_value, volatile jlong* dest) { *dest = store_value; }
+
+inline intptr_t Atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest) {
+ intptr_t addend = add_value;
+ bool mp = os::is_MP();
+ __asm__ __volatile__ (LOCK_IF_MP(%3) "xaddq %0,(%2)"
+ : "=r" (addend)
+ : "0" (addend), "r" (dest), "r" (mp)
+ : "cc", "memory");
+ return addend + add_value;
+}
+
+inline void* Atomic::add_ptr(intptr_t add_value, volatile void* dest) {
+ return (void*)add_ptr(add_value, (volatile intptr_t*)dest);
+}
+
+inline void Atomic::inc_ptr(volatile intptr_t* dest) {
+ bool mp = os::is_MP();
+ __asm__ __volatile__ (LOCK_IF_MP(%1) "addq $1,(%0)"
+ :
+ : "r" (dest), "r" (mp)
+ : "cc", "memory");
+}
+
+inline void Atomic::dec_ptr(volatile intptr_t* dest) {
+ bool mp = os::is_MP();
+ __asm__ __volatile__ (LOCK_IF_MP(%1) "subq $1,(%0)"
+ :
+ : "r" (dest), "r" (mp)
+ : "cc", "memory");
+}
+
+inline intptr_t Atomic::xchg_ptr(intptr_t exchange_value, volatile intptr_t* dest) {
+ __asm__ __volatile__ ("xchgq (%2),%0"
+ : "=r" (exchange_value)
+ : "0" (exchange_value), "r" (dest)
+ : "memory");
+ return exchange_value;
+}
+
+inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value) {
+ bool mp = os::is_MP();
+ __asm__ __volatile__ (LOCK_IF_MP(%4) "cmpxchgq %1,(%3)"
+ : "=a" (exchange_value)
+ : "r" (exchange_value), "a" (compare_value), "r" (dest), "r" (mp)
+ : "cc", "memory");
+ return exchange_value;
+}
+
+inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value) {
+ return (intptr_t)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value);
+}
+
+inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value) {
+ return (void*)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value);
+}
+
+inline jlong Atomic::load(volatile jlong* src) { return *src; }
+
+#else // !AMD64
+
+inline intptr_t Atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest) {
+ return (intptr_t)Atomic::add((jint)add_value, (volatile jint*)dest);
+}
+
+inline void* Atomic::add_ptr(intptr_t add_value, volatile void* dest) {
+ return (void*)Atomic::add((jint)add_value, (volatile jint*)dest);
+}
+
+
+inline void Atomic::inc_ptr(volatile intptr_t* dest) {
+ inc((volatile jint*)dest);
+}
+
+inline void Atomic::dec_ptr(volatile intptr_t* dest) {
+ dec((volatile jint*)dest);
+}
+
+inline intptr_t Atomic::xchg_ptr(intptr_t exchange_value, volatile intptr_t* dest) {
+ return (intptr_t)xchg((jint)exchange_value, (volatile jint*)dest);
+}
+
+extern "C" {
+ // defined in bsd_x86.s
+ jlong _Atomic_cmpxchg_long(jlong, volatile jlong*, jlong, bool);
+ void _Atomic_move_long(volatile jlong* src, volatile jlong* dst);
+}
+
+inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value) {
+ return _Atomic_cmpxchg_long(exchange_value, dest, compare_value, os::is_MP());
+}
+
+inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value) {
+ return (intptr_t)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value);
+}
+
+inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value) {
+ return (void*)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value);
+}
+
+inline jlong Atomic::load(volatile jlong* src) {
+ volatile jlong dest;
+ _Atomic_move_long(src, &dest);
+ return dest;
+}
+
+inline void Atomic::store(jlong store_value, jlong* dest) {
+ _Atomic_move_long((volatile jlong*)&store_value, (volatile jlong*)dest);
+}
+
+inline void Atomic::store(jlong store_value, volatile jlong* dest) {
+ _Atomic_move_long((volatile jlong*)&store_value, dest);
+}
+
+#endif // AMD64
+
+#endif // OS_CPU_BSD_X86_VM_ATOMIC_BSD_X86_INLINE_HPP
diff --git a/src/os_cpu/bsd_x86/vm/bsd_x86_32.ad b/src/os_cpu/bsd_x86/vm/bsd_x86_32.ad
new file mode 100644
index 000000000..192a78f7d
--- /dev/null
+++ b/src/os_cpu/bsd_x86/vm/bsd_x86_32.ad
@@ -0,0 +1,160 @@
+//
+// Copyright (c) 1999, 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.
+//
+// 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.
+//
+//
+
+// X86 Bsd Architecture Description File
+
+//----------OS-DEPENDENT ENCODING BLOCK-----------------------------------------------------
+// This block specifies the encoding classes used by the compiler to output
+// byte streams. Encoding classes generate functions which are called by
+// Machine Instruction Nodes in order to generate the bit encoding of the
+// instruction. Operands specify their base encoding interface with the
+// interface keyword. There are currently supported four interfaces,
+// REG_INTER, CONST_INTER, MEMORY_INTER, & COND_INTER. REG_INTER causes an
+// operand to generate a function which returns its register number when
+// queried. CONST_INTER causes an operand to generate a function which
+// returns the value of the constant when queried. MEMORY_INTER causes an
+// operand to generate four functions which return the Base Register, the
+// Index Register, the Scale Value, and the Offset Value of the operand when
+// queried. COND_INTER causes an operand to generate six functions which
+// return the encoding code (ie - encoding bits for the instruction)
+// associated with each basic boolean condition for a conditional instruction.
+// Instructions specify two basic values for encoding. They use the
+// ins_encode keyword to specify their encoding class (which must be one of
+// the class names specified in the encoding block), and they use the
+// opcode keyword to specify, in order, their primary, secondary, and
+// tertiary opcode. Only the opcode sections which a particular instruction
+// needs for encoding need to be specified.
+encode %{
+ // Build emit functions for each basic byte or larger field in the intel
+ // encoding scheme (opcode, rm, sib, immediate), and call them from C++
+ // code in the enc_class source block. Emit functions will live in the
+ // main source block for now. In future, we can generalize this by
+ // adding a syntax that specifies the sizes of fields in an order,
+ // so that the adlc can build the emit functions automagically
+
+ enc_class bsd_tlsencode (eRegP dst) %{
+ Register dstReg = as_Register($dst$$reg);
+ MacroAssembler* masm = new MacroAssembler(&cbuf);
+ masm->get_thread(dstReg);
+ %}
+
+ enc_class bsd_breakpoint %{
+ MacroAssembler* masm = new MacroAssembler(&cbuf);
+ masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint)));
+ %}
+
+ enc_class call_epilog %{
+ if( VerifyStackAtCalls ) {
+ // Check that stack depth is unchanged: find majik cookie on stack
+ int framesize = ra_->reg2offset_unchecked(OptoReg::add(ra_->_matcher._old_SP,-3*VMRegImpl::slots_per_word));
+ if(framesize >= 128) {
+ emit_opcode(cbuf, 0x81); // cmp [esp+0],0xbadb1ood
+ emit_d8(cbuf,0xBC);
+ emit_d8(cbuf,0x24);
+ emit_d32(cbuf,framesize); // Find majik cookie from ESP
+ emit_d32(cbuf, 0xbadb100d);
+ }
+ else {
+ emit_opcode(cbuf, 0x81); // cmp [esp+0],0xbadb1ood
+ emit_d8(cbuf,0x7C);
+ emit_d8(cbuf,0x24);
+ emit_d8(cbuf,framesize); // Find majik cookie from ESP
+ emit_d32(cbuf, 0xbadb100d);
+ }
+ // jmp EQ around INT3
+ // QQQ TODO
+ const int jump_around = 5; // size of call to breakpoint, 1 for CC
+ emit_opcode(cbuf,0x74);
+ emit_d8(cbuf, jump_around);
+ // QQQ temporary
+ emit_break(cbuf);
+ // Die if stack mismatch
+ // emit_opcode(cbuf,0xCC);
+ }
+ %}
+
+%}
+
+// INSTRUCTIONS -- Platform dependent
+
+//----------OS and Locking Instructions----------------------------------------
+
+// This name is KNOWN by the ADLC and cannot be changed.
+// The ADLC forces a 'TypeRawPtr::BOTTOM' output type
+// for this guy.
+instruct tlsLoadP(eRegP dst, eFlagsReg cr) %{
+ match(Set dst (ThreadLocal));
+ effect(DEF dst, KILL cr);
+
+ format %{ "MOV $dst, Thread::current()" %}
+ ins_encode( bsd_tlsencode(dst) );
+ ins_pipe( ialu_reg_fat );
+%}
+
+instruct TLS(eRegP dst) %{
+ match(Set dst (ThreadLocal));
+
+ expand %{
+ tlsLoadP(dst);
+ %}
+%}
+
+// Die now
+instruct ShouldNotReachHere( )
+%{
+ match(Halt);
+
+ // Use the following format syntax
+ format %{ "INT3 ; ShouldNotReachHere" %}
+ // QQQ TODO for now call breakpoint
+ // opcode(0xCC);
+ // ins_encode(Opc);
+ ins_encode(bsd_breakpoint);
+ ins_pipe( pipe_slow );
+%}
+
+
+
+// Platform dependent source
+
+source %{
+
+// emit an interrupt that is caught by the debugger
+void emit_break(CodeBuffer &cbuf) {
+
+ // Debugger doesn't really catch this but best we can do so far QQQ
+ MacroAssembler* masm = new MacroAssembler(&cbuf);
+ masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint)));
+}
+
+void MachBreakpointNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
+ emit_break(cbuf);
+}
+
+
+uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const {
+ return 5;
+}
+
+%}
diff --git a/src/os_cpu/bsd_x86/vm/bsd_x86_32.s b/src/os_cpu/bsd_x86/vm/bsd_x86_32.s
new file mode 100644
index 000000000..d35b4a6b4
--- /dev/null
+++ b/src/os_cpu/bsd_x86/vm/bsd_x86_32.s
@@ -0,0 +1,689 @@
+#
+# Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+
+#ifdef __APPLE__
+# Darwin uses _ prefixed global symbols
+#define SYMBOL(s) _ ## s
+#define ELF_TYPE(name, description)
+#else
+#define SYMBOL(s) s
+#define ELF_TYPE(name, description) .type name,description
+#endif
+
+ .globl SYMBOL(fixcw)
+
+ # NOTE WELL! The _Copy functions are called directly
+ # from server-compiler-generated code via CallLeafNoFP,
+ # which means that they *must* either not use floating
+ # point or use it in the same manner as does the server
+ # compiler.
+
+ .globl SYMBOL(_Copy_conjoint_bytes)
+ .globl SYMBOL(_Copy_arrayof_conjoint_bytes)
+ .globl SYMBOL(_Copy_conjoint_jshorts_atomic)
+ .globl SYMBOL(_Copy_arrayof_conjoint_jshorts)
+ .globl SYMBOL(_Copy_conjoint_jints_atomic)
+ .globl SYMBOL(_Copy_arrayof_conjoint_jints)
+ .globl SYMBOL(_Copy_conjoint_jlongs_atomic)
+ .globl SYMBOL(_mmx_Copy_arrayof_conjoint_jshorts)
+
+ .globl SYMBOL(_Atomic_cmpxchg_long)
+ .globl SYMBOL(_Atomic_move_long)
+
+ .text
+
+# Support for void os::Solaris::init_thread_fpu_state() in os_solaris_i486.cpp
+# Set fpu to 53 bit precision. This happens too early to use a stub.
+# ported from solaris_x86_32.s
+ .p2align 4,,15
+SYMBOL(fixcw):
+ pushl $0x27f
+ fldcw 0(%esp)
+ popl %eax
+ ret
+
+ .globl SYMBOL(SafeFetch32), SYMBOL(Fetch32PFI), SYMBOL(Fetch32Resume)
+ .globl SYMBOL(SafeFetchN)
+ ## TODO: avoid exposing Fetch32PFI and Fetch32Resume.
+ ## Instead, the signal handler would call a new SafeFetchTriage(FaultingEIP)
+ ## routine to vet the address. If the address is the faulting LD then
+ ## SafeFetchTriage() would return the resume-at EIP, otherwise null.
+ ELF_TYPE(SafeFetch32,@function)
+ .p2align 4,,15
+SYMBOL(SafeFetch32):
+SYMBOL(SafeFetchN):
+ movl 0x8(%esp), %eax
+ movl 0x4(%esp), %ecx
+SYMBOL(Fetch32PFI):
+ movl (%ecx), %eax
+SYMBOL(Fetch32Resume):
+ ret
+
+
+ .globl SYMBOL(SpinPause)
+ ELF_TYPE(SpinPause,@function)
+ .p2align 4,,15
+SYMBOL(SpinPause):
+ rep
+ nop
+ movl $1, %eax
+ ret
+
+ # Support for void Copy::conjoint_bytes(void* from,
+ # void* to,
+ # size_t count)
+ .p2align 4,,15
+ ELF_TYPE(_Copy_conjoint_bytes,@function)
+SYMBOL(_Copy_conjoint_bytes):
+ pushl %esi
+ movl 4+12(%esp),%ecx # count
+ pushl %edi
+ movl 8+ 4(%esp),%esi # from
+ movl 8+ 8(%esp),%edi # to
+ cmpl %esi,%edi
+ leal -1(%esi,%ecx),%eax # from + count - 1
+ jbe cb_CopyRight
+ cmpl %eax,%edi
+ jbe cb_CopyLeft
+ # copy from low to high
+cb_CopyRight:
+ cmpl $3,%ecx
+ jbe 5f # <= 3 bytes
+ # align source address at dword address boundary
+ movl %ecx,%eax # original count
+ movl $4,%ecx
+ subl %esi,%ecx
+ andl $3,%ecx # prefix byte count
+ jz 1f # no prefix
+ subl %ecx,%eax # byte count less prefix
+ # copy prefix
+ subl %esi,%edi
+0: movb (%esi),%dl
+ movb %dl,(%edi,%esi,1)
+ addl $1,%esi
+ subl $1,%ecx
+ jnz 0b
+ addl %esi,%edi
+1: movl %eax,%ecx # byte count less prefix
+ shrl $2,%ecx # dword count
+ jz 4f # no dwords to move
+ cmpl $32,%ecx
+ jbe 2f # <= 32 dwords
+ # copy aligned dwords
+ rep; smovl
+ jmp 4f
+ # copy aligned dwords
+2: subl %esi,%edi
+ .p2align 4,,15
+3: movl (%esi),%edx
+ movl %edx,(%edi,%esi,1)
+ addl $4,%esi
+ subl $1,%ecx
+ jnz 3b
+ addl %esi,%edi
+4: movl %eax,%ecx # byte count less prefix
+5: andl $3,%ecx # suffix byte count
+ jz 7f # no suffix
+ # copy suffix
+ xorl %eax,%eax
+6: movb (%esi,%eax,1),%dl
+ movb %dl,(%edi,%eax,1)
+ addl $1,%eax
+ subl $1,%ecx
+ jnz 6b
+7: popl %edi
+ popl %esi
+ ret
+ # copy from high to low
+cb_CopyLeft:
+ std
+ leal -4(%edi,%ecx),%edi # to + count - 4
+ movl %eax,%esi # from + count - 1
+ movl %ecx,%eax
+ subl $3,%esi # from + count - 4
+ cmpl $3,%ecx
+ jbe 5f # <= 3 bytes
+1: shrl $2,%ecx # dword count
+ jz 4f # no dwords to move
+ cmpl $32,%ecx
+ ja 3f # > 32 dwords
+ # copy dwords, aligned or not
+ subl %esi,%edi
+ .p2align 4,,15
+2: movl (%esi),%edx
+ movl %edx,(%edi,%esi,1)
+ subl $4,%esi
+ subl $1,%ecx
+ jnz 2b
+ addl %esi,%edi
+ jmp 4f
+ # copy dwords, aligned or not
+3: rep; smovl
+4: movl %eax,%ecx # byte count
+5: andl $3,%ecx # suffix byte count
+ jz 7f # no suffix
+ # copy suffix
+ subl %esi,%edi
+ addl $3,%esi
+6: movb (%esi),%dl
+ movb %dl,(%edi,%esi,1)
+ subl $1,%esi
+ subl $1,%ecx
+ jnz 6b
+7: cld
+ popl %edi
+ popl %esi
+ ret
+
+ # Support for void Copy::arrayof_conjoint_bytes(void* from,
+ # void* to,
+ # size_t count)
+ #
+ # Same as _Copy_conjoint_bytes, except no source alignment check.
+ .p2align 4,,15
+ ELF_TYPE(_Copy_arrayof_conjoint_bytes,@function)
+SYMBOL(_Copy_arrayof_conjoint_bytes):
+ pushl %esi
+ movl 4+12(%esp),%ecx # count
+ pushl %edi
+ movl 8+ 4(%esp),%esi # from
+ movl 8+ 8(%esp),%edi # to
+ cmpl %esi,%edi
+ leal -1(%esi,%ecx),%eax # from + count - 1
+ jbe acb_CopyRight
+ cmpl %eax,%edi
+ jbe acb_CopyLeft
+ # copy from low to high
+acb_CopyRight:
+ cmpl $3,%ecx
+ jbe 5f
+1: movl %ecx,%eax
+ shrl $2,%ecx
+ jz 4f
+ cmpl $32,%ecx
+ ja 3f
+ # copy aligned dwords
+ subl %esi,%edi
+ .p2align 4,,15
+2: movl (%esi),%edx
+ movl %edx,(%edi,%esi,1)
+ addl $4,%esi
+ subl $1,%ecx
+ jnz 2b
+ addl %esi,%edi
+ jmp 4f
+ # copy aligned dwords
+3: rep; smovl
+4: movl %eax,%ecx
+5: andl $3,%ecx
+ jz 7f
+ # copy suffix
+ xorl %eax,%eax
+6: movb (%esi,%eax,1),%dl
+ movb %dl,(%edi,%eax,1)
+ addl $1,%eax
+ subl $1,%ecx
+ jnz 6b
+7: popl %edi
+ popl %esi
+ ret
+acb_CopyLeft:
+ std
+ leal -4(%edi,%ecx),%edi # to + count - 4
+ movl %eax,%esi # from + count - 1
+ movl %ecx,%eax
+ subl $3,%esi # from + count - 4
+ cmpl $3,%ecx
+ jbe 5f
+1: shrl $2,%ecx
+ jz 4f
+ cmpl $32,%ecx
+ jbe 2f # <= 32 dwords
+ rep; smovl
+ jmp 4f
+ .=.+8
+2: subl %esi,%edi
+ .p2align 4,,15
+3: movl (%esi),%edx
+ movl %edx,(%edi,%esi,1)
+ subl $4,%esi
+ subl $1,%ecx
+ jnz 3b
+ addl %esi,%edi
+4: movl %eax,%ecx
+5: andl $3,%ecx
+ jz 7f
+ subl %esi,%edi
+ addl $3,%esi
+6: movb (%esi),%dl
+ movb %dl,(%edi,%esi,1)
+ subl $1,%esi
+ subl $1,%ecx
+ jnz 6b
+7: cld
+ popl %edi
+ popl %esi
+ ret
+
+ # Support for void Copy::conjoint_jshorts_atomic(void* from,
+ # void* to,
+ # size_t count)
+ .p2align 4,,15
+ ELF_TYPE(_Copy_conjoint_jshorts_atomic,@function)
+SYMBOL(_Copy_conjoint_jshorts_atomic):
+ pushl %esi
+ movl 4+12(%esp),%ecx # count
+ pushl %edi
+ movl 8+ 4(%esp),%esi # from
+ movl 8+ 8(%esp),%edi # to
+ cmpl %esi,%edi
+ leal -2(%esi,%ecx,2),%eax # from + count*2 - 2
+ jbe cs_CopyRight
+ cmpl %eax,%edi
+ jbe cs_CopyLeft
+ # copy from low to high
+cs_CopyRight:
+ # align source address at dword address boundary
+ movl %esi,%eax # original from
+ andl $3,%eax # either 0 or 2
+ jz 1f # no prefix
+ # copy prefix
+ subl $1,%ecx
+ jl 5f # zero count
+ movw (%esi),%dx
+ movw %dx,(%edi)
+ addl %eax,%esi # %eax == 2
+ addl %eax,%edi
+1: movl %ecx,%eax # word count less prefix
+ sarl %ecx # dword count
+ jz 4f # no dwords to move
+ cmpl $32,%ecx
+ jbe 2f # <= 32 dwords
+ # copy aligned dwords
+ rep; smovl
+ jmp 4f
+ # copy aligned dwords
+2: subl %esi,%edi
+ .p2align 4,,15
+3: movl (%esi),%edx
+ movl %edx,(%edi,%esi,1)
+ addl $4,%esi
+ subl $1,%ecx
+ jnz 3b
+ addl %esi,%edi
+4: andl $1,%eax # suffix count
+ jz 5f # no suffix
+ # copy suffix
+ movw (%esi),%dx
+ movw %dx,(%edi)
+5: popl %edi
+ popl %esi
+ ret
+ # copy from high to low
+cs_CopyLeft:
+ std
+ leal -4(%edi,%ecx,2),%edi # to + count*2 - 4
+ movl %eax,%esi # from + count*2 - 2
+ movl %ecx,%eax
+ subl $2,%esi # from + count*2 - 4
+1: sarl %ecx # dword count
+ jz 4f # no dwords to move
+ cmpl $32,%ecx
+ ja 3f # > 32 dwords
+ subl %esi,%edi
+ .p2align 4,,15
+2: movl (%esi),%edx
+ movl %edx,(%edi,%esi,1)
+ subl $4,%esi
+ subl $1,%ecx
+ jnz 2b
+ addl %esi,%edi
+ jmp 4f
+3: rep; smovl
+4: andl $1,%eax # suffix count
+ jz 5f # no suffix
+ # copy suffix
+ addl $2,%esi
+ addl $2,%edi
+ movw (%esi),%dx
+ movw %dx,(%edi)
+5: cld
+ popl %edi
+ popl %esi
+ ret
+
+ # Support for void Copy::arrayof_conjoint_jshorts(void* from,
+ # void* to,
+ # size_t count)
+ .p2align 4,,15
+ ELF_TYPE(_Copy_arrayof_conjoint_jshorts,@function)
+SYMBOL(_Copy_arrayof_conjoint_jshorts):
+ pushl %esi
+ movl 4+12(%esp),%ecx # count
+ pushl %edi
+ movl 8+ 4(%esp),%esi # from
+ movl 8+ 8(%esp),%edi # to
+ cmpl %esi,%edi
+ leal -2(%esi,%ecx,2),%eax # from + count*2 - 2
+ jbe acs_CopyRight
+ cmpl %eax,%edi
+ jbe acs_CopyLeft
+acs_CopyRight:
+ movl %ecx,%eax # word count
+ sarl %ecx # dword count
+ jz 4f # no dwords to move
+ cmpl $32,%ecx
+ jbe 2f # <= 32 dwords
+ # copy aligned dwords
+ rep; smovl
+ jmp 4f
+ # copy aligned dwords
+ .=.+5
+2: subl %esi,%edi
+ .p2align 4,,15
+3: movl (%esi),%edx
+ movl %edx,(%edi,%esi,1)
+ addl $4,%esi
+ subl $1,%ecx
+ jnz 3b
+ addl %esi,%edi
+4: andl $1,%eax # suffix count
+ jz 5f # no suffix
+ # copy suffix
+ movw (%esi),%dx
+ movw %dx,(%edi)
+5: popl %edi
+ popl %esi
+ ret
+acs_CopyLeft:
+ std
+ leal -4(%edi,%ecx,2),%edi # to + count*2 - 4
+ movl %eax,%esi # from + count*2 - 2
+ movl %ecx,%eax
+ subl $2,%esi # from + count*2 - 4
+ sarl %ecx # dword count
+ jz 4f # no dwords to move
+ cmpl $32,%ecx
+ ja 3f # > 32 dwords
+ subl %esi,%edi
+ .p2align 4,,15
+2: movl (%esi),%edx
+ movl %edx,(%edi,%esi,1)
+ subl $4,%esi
+ subl $1,%ecx
+ jnz 2b
+ addl %esi,%edi
+ jmp 4f
+3: rep; smovl
+4: andl $1,%eax # suffix count
+ jz 5f # no suffix
+ # copy suffix
+ addl $2,%esi
+ addl $2,%edi
+ movw (%esi),%dx
+ movw %dx,(%edi)
+5: cld
+ popl %edi
+ popl %esi
+ ret
+
+ # Support for void Copy::conjoint_jints_atomic(void* from,
+ # void* to,
+ # size_t count)
+ # Equivalent to
+ # arrayof_conjoint_jints
+ .p2align 4,,15
+ ELF_TYPE(_Copy_conjoint_jints_atomic,@function)
+ ELF_TYPE(_Copy_arrayof_conjoint_jints,@function)
+SYMBOL(_Copy_conjoint_jints_atomic):
+SYMBOL(_Copy_arrayof_conjoint_jints):
+ pushl %esi
+ movl 4+12(%esp),%ecx # count
+ pushl %edi
+ movl 8+ 4(%esp),%esi # from
+ movl 8+ 8(%esp),%edi # to
+ cmpl %esi,%edi
+ leal -4(%esi,%ecx,4),%eax # from + count*4 - 4
+ jbe ci_CopyRight
+ cmpl %eax,%edi
+ jbe ci_CopyLeft
+ci_CopyRight:
+ cmpl $32,%ecx
+ jbe 2f # <= 32 dwords
+ rep; smovl
+ popl %edi
+ popl %esi
+ ret
+ .=.+10
+2: subl %esi,%edi
+ jmp 4f
+ .p2align 4,,15
+3: movl (%esi),%edx
+ movl %edx,(%edi,%esi,1)
+ addl $4,%esi
+4: subl $1,%ecx
+ jge 3b
+ popl %edi
+ popl %esi
+ ret
+ci_CopyLeft:
+ std
+ leal -4(%edi,%ecx,4),%edi # to + count*4 - 4
+ cmpl $32,%ecx
+ ja 4f # > 32 dwords
+ subl %eax,%edi # eax == from + count*4 - 4
+ jmp 3f
+ .p2align 4,,15
+2: movl (%eax),%edx
+ movl %edx,(%edi,%eax,1)
+ subl $4,%eax
+3: subl $1,%ecx
+ jge 2b
+ cld
+ popl %edi
+ popl %esi
+ ret
+4: movl %eax,%esi # from + count*4 - 4
+ rep; smovl
+ cld
+ popl %edi
+ popl %esi
+ ret
+
+ # Support for void Copy::conjoint_jlongs_atomic(jlong* from,
+ # jlong* to,
+ # size_t count)
+ #
+ # 32-bit
+ #
+ # count treated as signed
+ #
+ # // if (from > to) {
+ # while (--count >= 0) {
+ # *to++ = *from++;
+ # }
+ # } else {
+ # while (--count >= 0) {
+ # to[count] = from[count];
+ # }
+ # }
+ .p2align 4,,15
+ ELF_TYPE(_Copy_conjoint_jlongs_atomic,@function)
+SYMBOL(_Copy_conjoint_jlongs_atomic):
+ movl 4+8(%esp),%ecx # count
+ movl 4+0(%esp),%eax # from
+ movl 4+4(%esp),%edx # to
+ cmpl %eax,%edx
+ jae cla_CopyLeft
+cla_CopyRight:
+ subl %eax,%edx
+ jmp 2f
+ .p2align 4,,15
+1: fildll (%eax)
+ fistpll (%edx,%eax,1)
+ addl $8,%eax
+2: subl $1,%ecx
+ jge 1b
+ ret
+ .p2align 4,,15
+3: fildll (%eax,%ecx,8)
+ fistpll (%edx,%ecx,8)
+cla_CopyLeft:
+ subl $1,%ecx
+ jge 3b
+ ret
+
+ # Support for void Copy::arrayof_conjoint_jshorts(void* from,
+ # void* to,
+ # size_t count)
+ .p2align 4,,15
+ ELF_TYPE(_mmx_Copy_arrayof_conjoint_jshorts,@function)
+SYMBOL(_mmx_Copy_arrayof_conjoint_jshorts):
+ pushl %esi
+ movl 4+12(%esp),%ecx
+ pushl %edi
+ movl 8+ 4(%esp),%esi
+ movl 8+ 8(%esp),%edi
+ cmpl %esi,%edi
+ leal -2(%esi,%ecx,2),%eax
+ jbe mmx_acs_CopyRight
+ cmpl %eax,%edi
+ jbe mmx_acs_CopyLeft
+mmx_acs_CopyRight:
+ movl %ecx,%eax
+ sarl %ecx
+ je 5f
+ cmpl $33,%ecx
+ jae 3f
+1: subl %esi,%edi
+ .p2align 4,,15
+2: movl (%esi),%edx
+ movl %edx,(%edi,%esi,1)
+ addl $4,%esi
+ subl $1,%ecx
+ jnz 2b
+ addl %esi,%edi
+ jmp 5f
+3: smovl # align to 8 bytes, we know we are 4 byte aligned to start
+ subl $1,%ecx
+4: .p2align 4,,15
+ movq 0(%esi),%mm0
+ addl $64,%edi
+ movq 8(%esi),%mm1
+ subl $16,%ecx
+ movq 16(%esi),%mm2
+ movq %mm0,-64(%edi)
+ movq 24(%esi),%mm0
+ movq %mm1,-56(%edi)
+ movq 32(%esi),%mm1
+ movq %mm2,-48(%edi)
+ movq 40(%esi),%mm2
+ movq %mm0,-40(%edi)
+ movq 48(%esi),%mm0
+ movq %mm1,-32(%edi)
+ movq 56(%esi),%mm1
+ movq %mm2,-24(%edi)
+ movq %mm0,-16(%edi)
+ addl $64,%esi
+ movq %mm1,-8(%edi)
+ cmpl $16,%ecx
+ jge 4b
+ emms
+ testl %ecx,%ecx
+ ja 1b
+5: andl $1,%eax
+ je 7f
+6: movw (%esi),%dx
+ movw %dx,(%edi)
+7: popl %edi
+ popl %esi
+ ret
+mmx_acs_CopyLeft:
+ std
+ leal -4(%edi,%ecx,2),%edi
+ movl %eax,%esi
+ movl %ecx,%eax
+ subl $2,%esi
+ sarl %ecx
+ je 4f
+ cmpl $32,%ecx
+ ja 3f
+ subl %esi,%edi
+ .p2align 4,,15
+2: movl (%esi),%edx
+ movl %edx,(%edi,%esi,1)
+ subl $4,%esi
+ subl $1,%ecx
+ jnz 2b
+ addl %esi,%edi
+ jmp 4f
+3: rep; smovl
+4: andl $1,%eax
+ je 6f
+ addl $2,%esi
+ addl $2,%edi
+5: movw (%esi),%dx
+ movw %dx,(%edi)
+6: cld
+ popl %edi
+ popl %esi
+ ret
+
+
+ # Support for jlong Atomic::cmpxchg(jlong exchange_value,
+ # volatile jlong* dest,
+ # jlong compare_value,
+ # bool is_MP)
+ #
+ .p2align 4,,15
+ ELF_TYPE(_Atomic_cmpxchg_long,@function)
+SYMBOL(_Atomic_cmpxchg_long):
+ # 8(%esp) : return PC
+ pushl %ebx # 4(%esp) : old %ebx
+ pushl %edi # 0(%esp) : old %edi
+ movl 12(%esp), %ebx # 12(%esp) : exchange_value (low)
+ movl 16(%esp), %ecx # 16(%esp) : exchange_value (high)
+ movl 24(%esp), %eax # 24(%esp) : compare_value (low)
+ movl 28(%esp), %edx # 28(%esp) : compare_value (high)
+ movl 20(%esp), %edi # 20(%esp) : dest
+ cmpl $0, 32(%esp) # 32(%esp) : is_MP
+ je 1f
+ lock
+1: cmpxchg8b (%edi)
+ popl %edi
+ popl %ebx
+ ret
+
+
+ # Support for jlong Atomic::load and Atomic::store.
+ # void _Atomic_move_long(volatile jlong* src, volatile jlong* dst)
+ .p2align 4,,15
+ ELF_TYPE(_Atomic_move_long,@function)
+SYMBOL(_Atomic_move_long):
+ movl 4(%esp), %eax # src
+ fildll (%eax)
+ movl 8(%esp), %eax # dest
+ fistpll (%eax)
+ ret
+
diff --git a/src/os_cpu/bsd_x86/vm/bsd_x86_64.ad b/src/os_cpu/bsd_x86/vm/bsd_x86_64.ad
new file mode 100644
index 000000000..233a1fef7
--- /dev/null
+++ b/src/os_cpu/bsd_x86/vm/bsd_x86_64.ad
@@ -0,0 +1,173 @@
+//
+// Copyright (c) 2003, 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.
+//
+// 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.
+//
+//
+
+// AMD64 Bsd Architecture Description File
+
+//----------OS-DEPENDENT ENCODING BLOCK----------------------------------------
+// This block specifies the encoding classes used by the compiler to
+// output byte streams. Encoding classes generate functions which are
+// called by Machine Instruction Nodes in order to generate the bit
+// encoding of the instruction. Operands specify their base encoding
+// interface with the interface keyword. There are currently
+// supported four interfaces, REG_INTER, CONST_INTER, MEMORY_INTER, &
+// COND_INTER. REG_INTER causes an operand to generate a function
+// which returns its register number when queried. CONST_INTER causes
+// an operand to generate a function which returns the value of the
+// constant when queried. MEMORY_INTER causes an operand to generate
+// four functions which return the Base Register, the Index Register,
+// the Scale Value, and the Offset Value of the operand when queried.
+// COND_INTER causes an operand to generate six functions which return
+// the encoding code (ie - encoding bits for the instruction)
+// associated with each basic boolean condition for a conditional
+// instruction. Instructions specify two basic values for encoding.
+// They use the ins_encode keyword to specify their encoding class
+// (which must be one of the class names specified in the encoding
+// block), and they use the opcode keyword to specify, in order, their
+// primary, secondary, and tertiary opcode. Only the opcode sections
+// which a particular instruction needs for encoding need to be
+// specified.
+encode %{
+ // Build emit functions for each basic byte or larger field in the intel
+ // encoding scheme (opcode, rm, sib, immediate), and call them from C++
+ // code in the enc_class source block. Emit functions will live in the
+ // main source block for now. In future, we can generalize this by
+ // adding a syntax that specifies the sizes of fields in an order,
+ // so that the adlc can build the emit functions automagically
+
+ enc_class Java_To_Runtime(method meth)
+ %{
+ // No relocation needed
+
+ // movq r10, <meth>
+ emit_opcode(cbuf, Assembler::REX_WB);
+ emit_opcode(cbuf, 0xB8 | (R10_enc - 8));
+ emit_d64(cbuf, (int64_t) $meth$$method);
+
+ // call (r10)
+ emit_opcode(cbuf, Assembler::REX_B);
+ emit_opcode(cbuf, 0xFF);
+ emit_opcode(cbuf, 0xD0 | (R10_enc - 8));
+ %}
+
+ enc_class bsd_breakpoint
+ %{
+ MacroAssembler* masm = new MacroAssembler(&cbuf);
+ masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint)));
+ %}
+
+ enc_class call_epilog
+ %{
+ if (VerifyStackAtCalls) {
+ // Check that stack depth is unchanged: find majik cookie on stack
+ int framesize =
+ ra_->reg2offset_unchecked(OptoReg::add(ra_->_matcher._old_SP, -3*VMRegImpl::slots_per_word));
+ if (framesize) {
+ if (framesize < 0x80) {
+ emit_opcode(cbuf, Assembler::REX_W);
+ emit_opcode(cbuf, 0x81); // cmpq [rsp+0],0xbadb1ood
+ emit_d8(cbuf, 0x7C);
+ emit_d8(cbuf, 0x24);
+ emit_d8(cbuf, framesize); // Find majik cookie from ESP
+ emit_d32(cbuf, 0xbadb100d);
+ } else {
+ emit_opcode(cbuf, Assembler::REX_W);
+ emit_opcode(cbuf, 0x81); // cmpq [rsp+0],0xbadb1ood
+ emit_d8(cbuf, 0xBC);
+ emit_d8(cbuf, 0x24);
+ emit_d32(cbuf, framesize); // Find majik cookie from ESP
+ emit_d32(cbuf, 0xbadb100d);
+ }
+ }
+ // jmp EQ around INT3
+ // QQQ TODO
+ const int jump_around = 5; // size of call to breakpoint, 1 for CC
+ emit_opcode(cbuf, 0x74);
+ emit_d8(cbuf, jump_around);
+ // QQQ temporary
+ emit_break(cbuf);
+ // Die if stack mismatch
+ // emit_opcode(cbuf,0xCC);
+ }
+ %}
+
+%}
+
+// INSTRUCTIONS -- Platform dependent
+
+//----------OS and Locking Instructions----------------------------------------
+
+// This name is KNOWN by the ADLC and cannot be changed.
+// The ADLC forces a 'TypeRawPtr::BOTTOM' output type
+// for this guy.
+instruct tlsLoadP(r15_RegP dst)
+%{
+ match(Set dst (ThreadLocal));
+ effect(DEF dst);
+
+ size(0);
+ format %{ "# TLS is in R15" %}
+ ins_encode( /*empty encoding*/ );
+ ins_pipe(ialu_reg_reg);
+%}
+
+// Die now
+instruct ShouldNotReachHere()
+%{
+ match(Halt);
+
+ // Use the following format syntax
+ format %{ "int3\t# ShouldNotReachHere" %}
+ // QQQ TODO for now call breakpoint
+ // opcode(0xCC);
+ // ins_encode(Opc);
+ ins_encode(bsd_breakpoint);
+ ins_pipe(pipe_slow);
+%}
+
+
+// Platform dependent source
+
+source
+%{
+
+int MachCallRuntimeNode::ret_addr_offset() {
+ return 13; // movq r10,#addr; callq (r10)
+}
+
+// emit an interrupt that is caught by the debugger
+void emit_break(CodeBuffer& cbuf) {
+ // Debugger doesn't really catch this but best we can do so far QQQ
+ MacroAssembler* masm = new MacroAssembler(&cbuf);
+ masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint)));
+}
+
+void MachBreakpointNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {
+ emit_break(cbuf);
+}
+
+uint MachBreakpointNode::size(PhaseRegAlloc* ra_) const {
+ return 5;
+}
+
+%}
diff --git a/src/os_cpu/bsd_x86/vm/bsd_x86_64.s b/src/os_cpu/bsd_x86/vm/bsd_x86_64.s
new file mode 100644
index 000000000..65d2db45f
--- /dev/null
+++ b/src/os_cpu/bsd_x86/vm/bsd_x86_64.s
@@ -0,0 +1,410 @@
+#
+# Copyright (c) 2004, 2007, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+#ifdef __APPLE__
+# Darwin uses _ prefixed global symbols
+#define SYMBOL(s) _ ## s
+#define ELF_TYPE(name, description)
+#else
+#define SYMBOL(s) s
+#define ELF_TYPE(name, description) .type name,description
+#endif
+
+ # NOTE WELL! The _Copy functions are called directly
+ # from server-compiler-generated code via CallLeafNoFP,
+ # which means that they *must* either not use floating
+ # point or use it in the same manner as does the server
+ # compiler.
+
+ .globl SYMBOL(_Copy_arrayof_conjoint_bytes)
+ .globl SYMBOL(_Copy_arrayof_conjoint_jshorts)
+ .globl SYMBOL(_Copy_conjoint_jshorts_atomic)
+ .globl SYMBOL(_Copy_arrayof_conjoint_jints)
+ .globl SYMBOL(_Copy_conjoint_jints_atomic)
+ .globl SYMBOL(_Copy_arrayof_conjoint_jlongs)
+ .globl SYMBOL(_Copy_conjoint_jlongs_atomic)
+
+ .text
+
+ .globl SYMBOL(SafeFetch32), SYMBOL(Fetch32PFI), SYMBOL(Fetch32Resume)
+ .p2align 4,,15
+ ELF_TYPE(SafeFetch32,@function)
+ // Prototype: int SafeFetch32 (int * Adr, int ErrValue)
+SYMBOL(SafeFetch32):
+ movl %esi, %eax
+SYMBOL(Fetch32PFI):
+ movl (%rdi), %eax
+SYMBOL(Fetch32Resume):
+ ret
+
+ .globl SYMBOL(SafeFetchN), SYMBOL(FetchNPFI), SYMBOL(FetchNResume)
+ .p2align 4,,15
+ ELF_TYPE(SafeFetchN,@function)
+ // Prototype: intptr_t SafeFetchN (intptr_t * Adr, intptr_t ErrValue)
+SYMBOL(SafeFetchN):
+ movq %rsi, %rax
+SYMBOL(FetchNPFI):
+ movq (%rdi), %rax
+SYMBOL(FetchNResume):
+ ret
+
+ .globl SYMBOL(SpinPause)
+ .p2align 4,,15
+ ELF_TYPE(SpinPause,@function)
+SYMBOL(SpinPause):
+ rep
+ nop
+ movq $1, %rax
+ ret
+
+ # Support for void Copy::arrayof_conjoint_bytes(void* from,
+ # void* to,
+ # size_t count)
+ # rdi - from
+ # rsi - to
+ # rdx - count, treated as ssize_t
+ #
+ .p2align 4,,15
+ ELF_TYPE(_Copy_arrayof_conjoint_bytes,@function)
+SYMBOL(_Copy_arrayof_conjoint_bytes):
+ movq %rdx,%r8 # byte count
+ shrq $3,%rdx # qword count
+ cmpq %rdi,%rsi
+ leaq -1(%rdi,%r8,1),%rax # from + bcount*1 - 1
+ jbe acb_CopyRight
+ cmpq %rax,%rsi
+ jbe acb_CopyLeft
+acb_CopyRight:
+ leaq -8(%rdi,%rdx,8),%rax # from + qcount*8 - 8
+ leaq -8(%rsi,%rdx,8),%rcx # to + qcount*8 - 8
+ negq %rdx
+ jmp 7f
+ .p2align 4,,15
+1: movq 8(%rax,%rdx,8),%rsi
+ movq %rsi,8(%rcx,%rdx,8)
+ addq $1,%rdx
+ jnz 1b
+2: testq $4,%r8 # check for trailing dword
+ jz 3f
+ movl 8(%rax),%esi # copy trailing dword
+ movl %esi,8(%rcx)
+ addq $4,%rax
+ addq $4,%rcx # original %rsi is trashed, so we
+ # can't use it as a base register
+3: testq $2,%r8 # check for trailing word
+ jz 4f
+ movw 8(%rax),%si # copy trailing word
+ movw %si,8(%rcx)
+ addq $2,%rcx
+4: testq $1,%r8 # check for trailing byte
+ jz 5f
+ movb -1(%rdi,%r8,1),%al # copy trailing byte
+ movb %al,8(%rcx)
+5: ret
+ .p2align 4,,15
+6: movq -24(%rax,%rdx,8),%rsi
+ movq %rsi,-24(%rcx,%rdx,8)
+ movq -16(%rax,%rdx,8),%rsi
+ movq %rsi,-16(%rcx,%rdx,8)
+ movq -8(%rax,%rdx,8),%rsi
+ movq %rsi,-8(%rcx,%rdx,8)
+ movq (%rax,%rdx,8),%rsi
+ movq %rsi,(%rcx,%rdx,8)
+7: addq $4,%rdx
+ jle 6b
+ subq $4,%rdx
+ jl 1b
+ jmp 2b
+acb_CopyLeft:
+ testq $1,%r8 # check for trailing byte
+ jz 1f
+ movb -1(%rdi,%r8,1),%cl # copy trailing byte
+ movb %cl,-1(%rsi,%r8,1)
+ subq $1,%r8 # adjust for possible trailing word
+1: testq $2,%r8 # check for trailing word
+ jz 2f
+ movw -2(%rdi,%r8,1),%cx # copy trailing word
+ movw %cx,-2(%rsi,%r8,1)
+2: testq $4,%r8 # check for trailing dword
+ jz 5f
+ movl (%rdi,%rdx,8),%ecx # copy trailing dword
+ movl %ecx,(%rsi,%rdx,8)
+ jmp 5f
+ .p2align 4,,15
+3: movq -8(%rdi,%rdx,8),%rcx
+ movq %rcx,-8(%rsi,%rdx,8)
+ subq $1,%rdx
+ jnz 3b
+ ret
+ .p2align 4,,15
+4: movq 24(%rdi,%rdx,8),%rcx
+ movq %rcx,24(%rsi,%rdx,8)
+ movq 16(%rdi,%rdx,8),%rcx
+ movq %rcx,16(%rsi,%rdx,8)
+ movq 8(%rdi,%rdx,8),%rcx
+ movq %rcx,8(%rsi,%rdx,8)
+ movq (%rdi,%rdx,8),%rcx
+ movq %rcx,(%rsi,%rdx,8)
+5: subq $4,%rdx
+ jge 4b
+ addq $4,%rdx
+ jg 3b
+ ret
+
+ # Support for void Copy::arrayof_conjoint_jshorts(void* from,
+ # void* to,
+ # size_t count)
+ # Equivalent to
+ # conjoint_jshorts_atomic
+ #
+ # If 'from' and/or 'to' are aligned on 4- or 2-byte boundaries, we
+ # let the hardware handle it. The tow or four words within dwords
+ # or qwords that span cache line boundaries will still be loaded
+ # and stored atomically.
+ #
+ # rdi - from
+ # rsi - to
+ # rdx - count, treated as ssize_t
+ #
+ .p2align 4,,15
+ ELF_TYPE(_Copy_arrayof_conjoint_jshorts,@function)
+ ELF_TYPE(_Copy_conjoint_jshorts_atomic,@function)
+SYMBOL(_Copy_arrayof_conjoint_jshorts):
+SYMBOL(_Copy_conjoint_jshorts_atomic):
+ movq %rdx,%r8 # word count
+ shrq $2,%rdx # qword count
+ cmpq %rdi,%rsi
+ leaq -2(%rdi,%r8,2),%rax # from + wcount*2 - 2
+ jbe acs_CopyRight
+ cmpq %rax,%rsi
+ jbe acs_CopyLeft
+acs_CopyRight:
+ leaq -8(%rdi,%rdx,8),%rax # from + qcount*8 - 8
+ leaq -8(%rsi,%rdx,8),%rcx # to + qcount*8 - 8
+ negq %rdx
+ jmp 6f
+1: movq 8(%rax,%rdx,8),%rsi
+ movq %rsi,8(%rcx,%rdx,8)
+ addq $1,%rdx
+ jnz 1b
+2: testq $2,%r8 # check for trailing dword
+ jz 3f
+ movl 8(%rax),%esi # copy trailing dword
+ movl %esi,8(%rcx)
+ addq $4,%rcx # original %rsi is trashed, so we
+ # can't use it as a base register
+3: testq $1,%r8 # check for trailing word
+ jz 4f
+ movw -2(%rdi,%r8,2),%si # copy trailing word
+ movw %si,8(%rcx)
+4: ret
+ .p2align 4,,15
+5: movq -24(%rax,%rdx,8),%rsi
+ movq %rsi,-24(%rcx,%rdx,8)
+ movq -16(%rax,%rdx,8),%rsi
+ movq %rsi,-16(%rcx,%rdx,8)
+ movq -8(%rax,%rdx,8),%rsi
+ movq %rsi,-8(%rcx,%rdx,8)
+ movq (%rax,%rdx,8),%rsi
+ movq %rsi,(%rcx,%rdx,8)
+6: addq $4,%rdx
+ jle 5b
+ subq $4,%rdx
+ jl 1b
+ jmp 2b
+acs_CopyLeft:
+ testq $1,%r8 # check for trailing word
+ jz 1f
+ movw -2(%rdi,%r8,2),%cx # copy trailing word
+ movw %cx,-2(%rsi,%r8,2)
+1: testq $2,%r8 # check for trailing dword
+ jz 4f
+ movl (%rdi,%rdx,8),%ecx # copy trailing dword
+ movl %ecx,(%rsi,%rdx,8)
+ jmp 4f
+2: movq -8(%rdi,%rdx,8),%rcx
+ movq %rcx,-8(%rsi,%rdx,8)
+ subq $1,%rdx
+ jnz 2b
+ ret
+ .p2align 4,,15
+3: movq 24(%rdi,%rdx,8),%rcx
+ movq %rcx,24(%rsi,%rdx,8)
+ movq 16(%rdi,%rdx,8),%rcx
+ movq %rcx,16(%rsi,%rdx,8)
+ movq 8(%rdi,%rdx,8),%rcx
+ movq %rcx,8(%rsi,%rdx,8)
+ movq (%rdi,%rdx,8),%rcx
+ movq %rcx,(%rsi,%rdx,8)
+4: subq $4,%rdx
+ jge 3b
+ addq $4,%rdx
+ jg 2b
+ ret
+
+ # Support for void Copy::arrayof_conjoint_jints(jint* from,
+ # jint* to,
+ # size_t count)
+ # Equivalent to
+ # conjoint_jints_atomic
+ #
+ # If 'from' and/or 'to' are aligned on 4-byte boundaries, we let
+ # the hardware handle it. The two dwords within qwords that span
+ # cache line boundaries will still be loaded and stored atomically.
+ #
+ # rdi - from
+ # rsi - to
+ # rdx - count, treated as ssize_t
+ #
+ .p2align 4,,15
+ ELF_TYPE(_Copy_arrayof_conjoint_jints,@function)
+ ELF_TYPE(_Copy_conjoint_jints_atomic,@function)
+SYMBOL(_Copy_arrayof_conjoint_jints):
+SYMBOL(_Copy_conjoint_jints_atomic):
+ movq %rdx,%r8 # dword count
+ shrq %rdx # qword count
+ cmpq %rdi,%rsi
+ leaq -4(%rdi,%r8,4),%rax # from + dcount*4 - 4
+ jbe aci_CopyRight
+ cmpq %rax,%rsi
+ jbe aci_CopyLeft
+aci_CopyRight:
+ leaq -8(%rdi,%rdx,8),%rax # from + qcount*8 - 8
+ leaq -8(%rsi,%rdx,8),%rcx # to + qcount*8 - 8
+ negq %rdx
+ jmp 5f
+ .p2align 4,,15
+1: movq 8(%rax,%rdx,8),%rsi
+ movq %rsi,8(%rcx,%rdx,8)
+ addq $1,%rdx
+ jnz 1b
+2: testq $1,%r8 # check for trailing dword
+ jz 3f
+ movl 8(%rax),%esi # copy trailing dword
+ movl %esi,8(%rcx)
+3: ret
+ .p2align 4,,15
+4: movq -24(%rax,%rdx,8),%rsi
+ movq %rsi,-24(%rcx,%rdx,8)
+ movq -16(%rax,%rdx,8),%rsi
+ movq %rsi,-16(%rcx,%rdx,8)
+ movq -8(%rax,%rdx,8),%rsi
+ movq %rsi,-8(%rcx,%rdx,8)
+ movq (%rax,%rdx,8),%rsi
+ movq %rsi,(%rcx,%rdx,8)
+5: addq $4,%rdx
+ jle 4b
+ subq $4,%rdx
+ jl 1b
+ jmp 2b
+aci_CopyLeft:
+ testq $1,%r8 # check for trailing dword
+ jz 3f
+ movl -4(%rdi,%r8,4),%ecx # copy trailing dword
+ movl %ecx,-4(%rsi,%r8,4)
+ jmp 3f
+1: movq -8(%rdi,%rdx,8),%rcx
+ movq %rcx,-8(%rsi,%rdx,8)
+ subq $1,%rdx
+ jnz 1b
+ ret
+ .p2align 4,,15
+2: movq 24(%rdi,%rdx,8),%rcx
+ movq %rcx,24(%rsi,%rdx,8)
+ movq 16(%rdi,%rdx,8),%rcx
+ movq %rcx,16(%rsi,%rdx,8)
+ movq 8(%rdi,%rdx,8),%rcx
+ movq %rcx,8(%rsi,%rdx,8)
+ movq (%rdi,%rdx,8),%rcx
+ movq %rcx,(%rsi,%rdx,8)
+3: subq $4,%rdx
+ jge 2b
+ addq $4,%rdx
+ jg 1b
+ ret
+
+ # Support for void Copy::arrayof_conjoint_jlongs(jlong* from,
+ # jlong* to,
+ # size_t count)
+ # Equivalent to
+ # conjoint_jlongs_atomic
+ # arrayof_conjoint_oops
+ # conjoint_oops_atomic
+ #
+ # rdi - from
+ # rsi - to
+ # rdx - count, treated as ssize_t
+ #
+ .p2align 4,,15
+ ELF_TYPE(_Copy_arrayof_conjoint_jlongs,@function)
+ ELF_TYPE(_Copy_conjoint_jlongs_atomic,@function)
+SYMBOL(_Copy_arrayof_conjoint_jlongs):
+SYMBOL(_Copy_conjoint_jlongs_atomic):
+ cmpq %rdi,%rsi
+ leaq -8(%rdi,%rdx,8),%rax # from + count*8 - 8
+ jbe acl_CopyRight
+ cmpq %rax,%rsi
+ jbe acl_CopyLeft
+acl_CopyRight:
+ leaq -8(%rsi,%rdx,8),%rcx # to + count*8 - 8
+ negq %rdx
+ jmp 3f
+1: movq 8(%rax,%rdx,8),%rsi
+ movq %rsi,8(%rcx,%rdx,8)
+ addq $1,%rdx
+ jnz 1b
+ ret
+ .p2align 4,,15
+2: movq -24(%rax,%rdx,8),%rsi
+ movq %rsi,-24(%rcx,%rdx,8)
+ movq -16(%rax,%rdx,8),%rsi
+ movq %rsi,-16(%rcx,%rdx,8)
+ movq -8(%rax,%rdx,8),%rsi
+ movq %rsi,-8(%rcx,%rdx,8)
+ movq (%rax,%rdx,8),%rsi
+ movq %rsi,(%rcx,%rdx,8)
+3: addq $4,%rdx
+ jle 2b
+ subq $4,%rdx
+ jl 1b
+ ret
+4: movq -8(%rdi,%rdx,8),%rcx
+ movq %rcx,-8(%rsi,%rdx,8)
+ subq $1,%rdx
+ jnz 4b
+ ret
+ .p2align 4,,15
+5: movq 24(%rdi,%rdx,8),%rcx
+ movq %rcx,24(%rsi,%rdx,8)
+ movq 16(%rdi,%rdx,8),%rcx
+ movq %rcx,16(%rsi,%rdx,8)
+ movq 8(%rdi,%rdx,8),%rcx
+ movq %rcx,8(%rsi,%rdx,8)
+ movq (%rdi,%rdx,8),%rcx
+ movq %rcx,(%rsi,%rdx,8)
+acl_CopyLeft:
+ subq $4,%rdx
+ jge 5b
+ addq $4,%rdx
+ jg 4b
+ ret
diff --git a/src/os_cpu/bsd_x86/vm/bytes_bsd_x86.inline.hpp b/src/os_cpu/bsd_x86/vm/bytes_bsd_x86.inline.hpp
new file mode 100644
index 000000000..4fe770a0e
--- /dev/null
+++ b/src/os_cpu/bsd_x86/vm/bytes_bsd_x86.inline.hpp
@@ -0,0 +1,116 @@
+/*
+ * 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.
+ *
+ * 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 OS_CPU_BSD_X86_VM_BYTES_BSD_X86_INLINE_HPP
+#define OS_CPU_BSD_X86_VM_BYTES_BSD_X86_INLINE_HPP
+
+#ifndef _ALLBSD_SOURCE
+#include <byteswap.h>
+#endif
+
+#ifdef __APPLE__
+#include <libkern/OSByteOrder.h>
+#endif
+
+#if defined(AMD64)
+# if defined(__APPLE__)
+# define bswap_16(x) OSSwapInt16(x)
+# define bswap_32(x) OSSwapInt32(x)
+# define bswap_64(x) OSSwapInt64(x)
+# elif defined(__OpenBSD__)
+# define bswap_16(x) swap16(x)
+# define bswap_32(x) swap32(x)
+# define bswap_64(x) swap64(x)
+# elif defined(__NetBSD__)
+# define bswap_16(x) bswap16(x)
+# define bswap_32(x) bswap32(x)
+# define bswap_64(x) bswap64(x)
+# else
+# define bswap_16(x) __bswap16(x)
+# define bswap_32(x) __bswap32(x)
+# define bswap_64(x) __bswap64(x)
+# endif
+#endif
+
+// Efficient swapping of data bytes from Java byte
+// ordering to native byte ordering and vice versa.
+inline u2 Bytes::swap_u2(u2 x) {
+#ifdef AMD64
+ return bswap_16(x);
+#else
+ u2 ret;
+ __asm__ __volatile__ (
+ "movw %0, %%ax;"
+ "xchg %%al, %%ah;"
+ "movw %%ax, %0"
+ :"=r" (ret) // output : register 0 => ret
+ :"0" (x) // input : x => register 0
+ :"ax", "0" // clobbered registers
+ );
+ return ret;
+#endif // AMD64
+}
+
+inline u4 Bytes::swap_u4(u4 x) {
+#ifdef AMD64
+ return bswap_32(x);
+#else
+ u4 ret;
+ __asm__ __volatile__ (
+ "bswap %0"
+ :"=r" (ret) // output : register 0 => ret
+ :"0" (x) // input : x => register 0
+ :"0" // clobbered register
+ );
+ return ret;
+#endif // AMD64
+}
+
+#ifdef AMD64
+inline u8 Bytes::swap_u8(u8 x) {
+#ifdef SPARC_WORKS
+ // workaround for SunStudio12 CR6615391
+ __asm__ __volatile__ (
+ "bswapq %0"
+ :"=r" (x) // output : register 0 => x
+ :"0" (x) // input : x => register 0
+ :"0" // clobbered register
+ );
+ return x;
+#else
+ return bswap_64(x);
+#endif
+}
+#else
+// Helper function for swap_u8
+inline u8 Bytes::swap_u8_base(u4 x, u4 y) {
+ return (((u8)swap_u4(x))<<32) | swap_u4(y);
+}
+
+inline u8 Bytes::swap_u8(u8 x) {
+ return swap_u8_base(*(u4*)&x, *(((u4*)&x)+1));
+}
+#endif // !AMD64
+
+#endif // OS_CPU_BSD_X86_VM_BYTES_BSD_X86_INLINE_HPP
diff --git a/src/os_cpu/bsd_x86/vm/copy_bsd_x86.inline.hpp b/src/os_cpu/bsd_x86/vm/copy_bsd_x86.inline.hpp
new file mode 100644
index 000000000..760c61adb
--- /dev/null
+++ b/src/os_cpu/bsd_x86/vm/copy_bsd_x86.inline.hpp
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef OS_CPU_BSD_X86_VM_COPY_BSD_X86_INLINE_HPP
+#define OS_CPU_BSD_X86_VM_COPY_BSD_X86_INLINE_HPP
+
+static void pd_conjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+#ifdef AMD64
+ (void)memmove(to, from, count * HeapWordSize);
+#else
+ // Includes a zero-count check.
+ intx temp;
+ __asm__ volatile(" testl %6,%6 ;"
+ " jz 7f ;"
+ " cmpl %4,%5 ;"
+ " leal -4(%4,%6,4),%3;"
+ " jbe 1f ;"
+ " cmpl %7,%5 ;"
+ " jbe 4f ;"
+ "1: cmpl $32,%6 ;"
+ " ja 3f ;"
+ " subl %4,%1 ;"
+ "2: movl (%4),%3 ;"
+ " movl %7,(%5,%4,1) ;"
+ " addl $4,%0 ;"
+ " subl $1,%2 ;"
+ " jnz 2b ;"
+ " jmp 7f ;"
+ "3: rep; smovl ;"
+ " jmp 7f ;"
+ "4: cmpl $32,%2 ;"
+ " movl %7,%0 ;"
+ " leal -4(%5,%6,4),%1;"
+ " ja 6f ;"
+ " subl %4,%1 ;"
+ "5: movl (%4),%3 ;"
+ " movl %7,(%5,%4,1) ;"
+ " subl $4,%0 ;"
+ " subl $1,%2 ;"
+ " jnz 5b ;"
+ " jmp 7f ;"
+ "6: std ;"
+ " rep; smovl ;"
+ " cld ;"
+ "7: nop "
+ : "=S" (from), "=D" (to), "=c" (count), "=r" (temp)
+ : "0" (from), "1" (to), "2" (count), "3" (temp)
+ : "memory", "flags");
+#endif // AMD64
+}
+
+static void pd_disjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+#ifdef AMD64
+ switch (count) {
+ case 8: to[7] = from[7];
+ case 7: to[6] = from[6];
+ case 6: to[5] = from[5];
+ case 5: to[4] = from[4];
+ case 4: to[3] = from[3];
+ case 3: to[2] = from[2];
+ case 2: to[1] = from[1];
+ case 1: to[0] = from[0];
+ case 0: break;
+ default:
+ (void)memcpy(to, from, count * HeapWordSize);
+ break;
+ }
+#else
+ // Includes a zero-count check.
+ intx temp;
+ __asm__ volatile(" testl %6,%6 ;"
+ " jz 3f ;"
+ " cmpl $32,%6 ;"
+ " ja 2f ;"
+ " subl %4,%1 ;"
+ "1: movl (%4),%3 ;"
+ " movl %7,(%5,%4,1);"
+ " addl $4,%0 ;"
+ " subl $1,%2 ;"
+ " jnz 1b ;"
+ " jmp 3f ;"
+ "2: rep; smovl ;"
+ "3: nop "
+ : "=S" (from), "=D" (to), "=c" (count), "=r" (temp)
+ : "0" (from), "1" (to), "2" (count), "3" (temp)
+ : "memory", "cc");
+#endif // AMD64
+}
+
+static void pd_disjoint_words_atomic(HeapWord* from, HeapWord* to, size_t count) {
+#ifdef AMD64
+ switch (count) {
+ case 8: to[7] = from[7];
+ case 7: to[6] = from[6];
+ case 6: to[5] = from[5];
+ case 5: to[4] = from[4];
+ case 4: to[3] = from[3];
+ case 3: to[2] = from[2];
+ case 2: to[1] = from[1];
+ case 1: to[0] = from[0];
+ case 0: break;
+ default:
+ while (count-- > 0) {
+ *to++ = *from++;
+ }
+ break;
+ }
+#else
+ // pd_disjoint_words is word-atomic in this implementation.
+ pd_disjoint_words(from, to, count);
+#endif // AMD64
+}
+
+static void pd_aligned_conjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+ pd_conjoint_words(from, to, count);
+}
+
+static void pd_aligned_disjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+ pd_disjoint_words(from, to, count);
+}
+
+static void pd_conjoint_bytes(void* from, void* to, size_t count) {
+#ifdef AMD64
+ (void)memmove(to, from, count);
+#else
+ // Includes a zero-count check.
+ intx temp;
+ __asm__ volatile(" testl %6,%6 ;"
+ " jz 13f ;"
+ " cmpl %4,%5 ;"
+ " leal -1(%4,%6),%3 ;"
+ " jbe 1f ;"
+ " cmpl %7,%5 ;"
+ " jbe 8f ;"
+ "1: cmpl $3,%6 ;"
+ " jbe 6f ;"
+ " movl %6,%3 ;"
+ " movl $4,%2 ;"
+ " subl %4,%2 ;"
+ " andl $3,%2 ;"
+ " jz 2f ;"
+ " subl %6,%3 ;"
+ " rep; smovb ;"
+ "2: movl %7,%2 ;"
+ " shrl $2,%2 ;"
+ " jz 5f ;"
+ " cmpl $32,%2 ;"
+ " ja 4f ;"
+ " subl %4,%1 ;"
+ "3: movl (%4),%%edx ;"
+ " movl %%edx,(%5,%4,1);"
+ " addl $4,%0 ;"
+ " subl $1,%2 ;"
+ " jnz 3b ;"
+ " addl %4,%1 ;"
+ " jmp 5f ;"
+ "4: rep; smovl ;"
+ "5: movl %7,%2 ;"
+ " andl $3,%2 ;"
+ " jz 13f ;"
+ "6: xorl %7,%3 ;"
+ "7: movb (%4,%7,1),%%dl ;"
+ " movb %%dl,(%5,%7,1) ;"
+ " addl $1,%3 ;"
+ " subl $1,%2 ;"
+ " jnz 7b ;"
+ " jmp 13f ;"
+ "8: std ;"
+ " cmpl $12,%2 ;"
+ " ja 9f ;"
+ " movl %7,%0 ;"
+ " leal -1(%6,%5),%1 ;"
+ " jmp 11f ;"
+ "9: xchgl %3,%2 ;"
+ " movl %6,%0 ;"
+ " addl $1,%2 ;"
+ " leal -1(%7,%5),%1 ;"
+ " andl $3,%2 ;"
+ " jz 10f ;"
+ " subl %6,%3 ;"
+ " rep; smovb ;"
+ "10: movl %7,%2 ;"
+ " subl $3,%0 ;"
+ " shrl $2,%2 ;"
+ " subl $3,%1 ;"
+ " rep; smovl ;"
+ " andl $3,%3 ;"
+ " jz 12f ;"
+ " movl %7,%2 ;"
+ " addl $3,%0 ;"
+ " addl $3,%1 ;"
+ "11: rep; smovb ;"
+ "12: cld ;"
+ "13: nop ;"
+ : "=S" (from), "=D" (to), "=c" (count), "=r" (temp)
+ : "0" (from), "1" (to), "2" (count), "3" (temp)
+ : "memory", "flags", "%edx");
+#endif // AMD64
+}
+
+static void pd_conjoint_bytes_atomic(void* from, void* to, size_t count) {
+ pd_conjoint_bytes(from, to, count);
+}
+
+static void pd_conjoint_jshorts_atomic(jshort* from, jshort* to, size_t count) {
+ _Copy_conjoint_jshorts_atomic(from, to, count);
+}
+
+static void pd_conjoint_jints_atomic(jint* from, jint* to, size_t count) {
+#ifdef AMD64
+ _Copy_conjoint_jints_atomic(from, to, count);
+#else
+ assert(HeapWordSize == BytesPerInt, "heapwords and jints must be the same size");
+ // pd_conjoint_words is word-atomic in this implementation.
+ pd_conjoint_words((HeapWord*)from, (HeapWord*)to, count);
+#endif // AMD64
+}
+
+static void pd_conjoint_jlongs_atomic(jlong* from, jlong* to, size_t count) {
+#ifdef AMD64
+ _Copy_conjoint_jlongs_atomic(from, to, count);
+#else
+ // Guarantee use of fild/fistp or xmm regs via some asm code, because compilers won't.
+ if (from > to) {
+ while (count-- > 0) {
+ __asm__ volatile("fildll (%0); fistpll (%1)"
+ :
+ : "r" (from), "r" (to)
+ : "memory" );
+ ++from;
+ ++to;
+ }
+ } else {
+ while (count-- > 0) {
+ __asm__ volatile("fildll (%0,%2,8); fistpll (%1,%2,8)"
+ :
+ : "r" (from), "r" (to), "r" (count)
+ : "memory" );
+ }
+ }
+#endif // AMD64
+}
+
+static void pd_conjoint_oops_atomic(oop* from, oop* to, size_t count) {
+#ifdef AMD64
+ assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size");
+ _Copy_conjoint_jlongs_atomic((jlong*)from, (jlong*)to, count);
+#else
+ assert(HeapWordSize == BytesPerOop, "heapwords and oops must be the same size");
+ // pd_conjoint_words is word-atomic in this implementation.
+ pd_conjoint_words((HeapWord*)from, (HeapWord*)to, count);
+#endif // AMD64
+}
+
+static void pd_arrayof_conjoint_bytes(HeapWord* from, HeapWord* to, size_t count) {
+ _Copy_arrayof_conjoint_bytes(from, to, count);
+}
+
+static void pd_arrayof_conjoint_jshorts(HeapWord* from, HeapWord* to, size_t count) {
+ _Copy_arrayof_conjoint_jshorts(from, to, count);
+}
+
+static void pd_arrayof_conjoint_jints(HeapWord* from, HeapWord* to, size_t count) {
+#ifdef AMD64
+ _Copy_arrayof_conjoint_jints(from, to, count);
+#else
+ pd_conjoint_jints_atomic((jint*)from, (jint*)to, count);
+#endif // AMD64
+}
+
+static void pd_arrayof_conjoint_jlongs(HeapWord* from, HeapWord* to, size_t count) {
+#ifdef AMD64
+ _Copy_arrayof_conjoint_jlongs(from, to, count);
+#else
+ pd_conjoint_jlongs_atomic((jlong*)from, (jlong*)to, count);
+#endif // AMD64
+}
+
+static void pd_arrayof_conjoint_oops(HeapWord* from, HeapWord* to, size_t count) {
+#ifdef AMD64
+ assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size");
+ _Copy_arrayof_conjoint_jlongs(from, to, count);
+#else
+ pd_conjoint_oops_atomic((oop*)from, (oop*)to, count);
+#endif // AMD64
+}
+
+#endif // OS_CPU_BSD_X86_VM_COPY_BSD_X86_INLINE_HPP
diff --git a/src/os_cpu/bsd_x86/vm/globals_bsd_x86.hpp b/src/os_cpu/bsd_x86/vm/globals_bsd_x86.hpp
new file mode 100644
index 000000000..960118831
--- /dev/null
+++ b/src/os_cpu/bsd_x86/vm/globals_bsd_x86.hpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef OS_CPU_BSD_X86_VM_GLOBALS_BSD_X86_HPP
+#define OS_CPU_BSD_X86_VM_GLOBALS_BSD_X86_HPP
+
+//
+// Sets the default values for platform dependent flags used by the runtime system.
+// (see globals.hpp)
+//
+define_pd_global(bool, DontYieldALot, false);
+#ifdef AMD64
+define_pd_global(intx, ThreadStackSize, 1024); // 0 => use system default
+define_pd_global(intx, VMThreadStackSize, 1024);
+#else
+// ThreadStackSize 320 allows a couple of test cases to run while
+// keeping the number of threads that can be created high. System
+// default ThreadStackSize appears to be 512 which is too big.
+define_pd_global(intx, ThreadStackSize, 320);
+define_pd_global(intx, VMThreadStackSize, 512);
+#endif // AMD64
+
+define_pd_global(intx, CompilerThreadStackSize, 0);
+define_pd_global(intx, SurvivorRatio, 8);
+
+define_pd_global(uintx, JVMInvokeMethodSlack, 8192);
+
+// Only used on 64 bit platforms
+define_pd_global(uintx, HeapBaseMinAddress, 2*G);
+// Only used on 64 bit Windows platforms
+define_pd_global(bool, UseVectoredExceptions, false);
+
+#endif // OS_CPU_BSD_X86_VM_GLOBALS_BSD_X86_HPP
diff --git a/src/os_cpu/bsd_x86/vm/orderAccess_bsd_x86.inline.hpp b/src/os_cpu/bsd_x86/vm/orderAccess_bsd_x86.inline.hpp
new file mode 100644
index 000000000..eaecd9cd3
--- /dev/null
+++ b/src/os_cpu/bsd_x86/vm/orderAccess_bsd_x86.inline.hpp
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef OS_CPU_BSD_X86_VM_ORDERACCESS_BSD_X86_INLINE_HPP
+#define OS_CPU_BSD_X86_VM_ORDERACCESS_BSD_X86_INLINE_HPP
+
+#include "runtime/atomic.hpp"
+#include "runtime/orderAccess.hpp"
+#include "vm_version_x86.hpp"
+
+// Implementation of class OrderAccess.
+
+inline void OrderAccess::loadload() { acquire(); }
+inline void OrderAccess::storestore() { release(); }
+inline void OrderAccess::loadstore() { acquire(); }
+inline void OrderAccess::storeload() { fence(); }
+
+inline void OrderAccess::acquire() {
+ volatile intptr_t local_dummy;
+#ifdef AMD64
+ __asm__ volatile ("movq 0(%%rsp), %0" : "=r" (local_dummy) : : "memory");
+#else
+ __asm__ volatile ("movl 0(%%esp),%0" : "=r" (local_dummy) : : "memory");
+#endif // AMD64
+}
+
+inline void OrderAccess::release() {
+ // Avoid hitting the same cache-line from
+ // different threads.
+ volatile jint local_dummy = 0;
+}
+
+inline void OrderAccess::fence() {
+ if (os::is_MP()) {
+ // always use locked addl since mfence is sometimes expensive
+#ifdef AMD64
+ __asm__ volatile ("lock; addl $0,0(%%rsp)" : : : "cc", "memory");
+#else
+ __asm__ volatile ("lock; addl $0,0(%%esp)" : : : "cc", "memory");
+#endif
+ }
+}
+
+inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { return *p; }
+inline jshort OrderAccess::load_acquire(volatile jshort* p) { return *p; }
+inline jint OrderAccess::load_acquire(volatile jint* p) { return *p; }
+inline jlong OrderAccess::load_acquire(volatile jlong* p) { return Atomic::load(p); }
+inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { return *p; }
+inline jushort OrderAccess::load_acquire(volatile jushort* p) { return *p; }
+inline juint OrderAccess::load_acquire(volatile juint* p) { return *p; }
+inline julong OrderAccess::load_acquire(volatile julong* p) { return Atomic::load((volatile jlong*)p); }
+inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { return *p; }
+inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { return *p; }
+
+inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t* p) { return *p; }
+inline void* OrderAccess::load_ptr_acquire(volatile void* p) { return *(void* volatile *)p; }
+inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { return *(void* const volatile *)p; }
+
+inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { *p = v; }
+inline void OrderAccess::release_store(volatile jshort* p, jshort v) { *p = v; }
+inline void OrderAccess::release_store(volatile jint* p, jint v) { *p = v; }
+inline void OrderAccess::release_store(volatile jlong* p, jlong v) { Atomic::store(v, p); }
+inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { *p = v; }
+inline void OrderAccess::release_store(volatile jushort* p, jushort v) { *p = v; }
+inline void OrderAccess::release_store(volatile juint* p, juint v) { *p = v; }
+inline void OrderAccess::release_store(volatile julong* p, julong v) { Atomic::store((jlong)v, (volatile jlong*)p); }
+inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { *p = v; }
+inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { *p = v; }
+
+inline void OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { *p = v; }
+inline void OrderAccess::release_store_ptr(volatile void* p, void* v) { *(void* volatile *)p = v; }
+
+inline void OrderAccess::store_fence(jbyte* p, jbyte v) {
+ __asm__ volatile ( "xchgb (%2),%0"
+ : "=q" (v)
+ : "0" (v), "r" (p)
+ : "memory");
+}
+inline void OrderAccess::store_fence(jshort* p, jshort v) {
+ __asm__ volatile ( "xchgw (%2),%0"
+ : "=r" (v)
+ : "0" (v), "r" (p)
+ : "memory");
+}
+inline void OrderAccess::store_fence(jint* p, jint v) {
+ __asm__ volatile ( "xchgl (%2),%0"
+ : "=r" (v)
+ : "0" (v), "r" (p)
+ : "memory");
+}
+
+inline void OrderAccess::store_fence(jlong* p, jlong v) {
+#ifdef AMD64
+ __asm__ __volatile__ ("xchgq (%2), %0"
+ : "=r" (v)
+ : "0" (v), "r" (p)
+ : "memory");
+#else
+ *p = v; fence();
+#endif // AMD64
+}
+
+// AMD64 copied the bodies for the the signed version. 32bit did this. As long as the
+// compiler does the inlining this is simpler.
+inline void OrderAccess::store_fence(jubyte* p, jubyte v) { store_fence((jbyte*)p, (jbyte)v); }
+inline void OrderAccess::store_fence(jushort* p, jushort v) { store_fence((jshort*)p, (jshort)v); }
+inline void OrderAccess::store_fence(juint* p, juint v) { store_fence((jint*)p, (jint)v); }
+inline void OrderAccess::store_fence(julong* p, julong v) { store_fence((jlong*)p, (jlong)v); }
+inline void OrderAccess::store_fence(jfloat* p, jfloat v) { *p = v; fence(); }
+inline void OrderAccess::store_fence(jdouble* p, jdouble v) { *p = v; fence(); }
+
+inline void OrderAccess::store_ptr_fence(intptr_t* p, intptr_t v) {
+#ifdef AMD64
+ __asm__ __volatile__ ("xchgq (%2), %0"
+ : "=r" (v)
+ : "0" (v), "r" (p)
+ : "memory");
+#else
+ store_fence((jint*)p, (jint)v);
+#endif // AMD64
+}
+
+inline void OrderAccess::store_ptr_fence(void** p, void* v) {
+#ifdef AMD64
+ __asm__ __volatile__ ("xchgq (%2), %0"
+ : "=r" (v)
+ : "0" (v), "r" (p)
+ : "memory");
+#else
+ store_fence((jint*)p, (jint)v);
+#endif // AMD64
+}
+
+// Must duplicate definitions instead of calling store_fence because we don't want to cast away volatile.
+inline void OrderAccess::release_store_fence(volatile jbyte* p, jbyte v) {
+ __asm__ volatile ( "xchgb (%2),%0"
+ : "=q" (v)
+ : "0" (v), "r" (p)
+ : "memory");
+}
+inline void OrderAccess::release_store_fence(volatile jshort* p, jshort v) {
+ __asm__ volatile ( "xchgw (%2),%0"
+ : "=r" (v)
+ : "0" (v), "r" (p)
+ : "memory");
+}
+inline void OrderAccess::release_store_fence(volatile jint* p, jint v) {
+ __asm__ volatile ( "xchgl (%2),%0"
+ : "=r" (v)
+ : "0" (v), "r" (p)
+ : "memory");
+}
+
+inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) {
+#ifdef AMD64
+ __asm__ __volatile__ ( "xchgq (%2), %0"
+ : "=r" (v)
+ : "0" (v), "r" (p)
+ : "memory");
+#else
+ release_store(p, v); fence();
+#endif // AMD64
+}
+
+inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { release_store_fence((volatile jbyte*)p, (jbyte)v); }
+inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { release_store_fence((volatile jshort*)p, (jshort)v); }
+inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { release_store_fence((volatile jint*)p, (jint)v); }
+inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { release_store_fence((volatile jlong*)p, (jlong)v); }
+
+inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { *p = v; fence(); }
+inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { *p = v; fence(); }
+
+inline void OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) {
+#ifdef AMD64
+ __asm__ __volatile__ ( "xchgq (%2), %0"
+ : "=r" (v)
+ : "0" (v), "r" (p)
+ : "memory");
+#else
+ release_store_fence((volatile jint*)p, (jint)v);
+#endif // AMD64
+}
+inline void OrderAccess::release_store_ptr_fence(volatile void* p, void* v) {
+#ifdef AMD64
+ __asm__ __volatile__ ( "xchgq (%2), %0"
+ : "=r" (v)
+ : "0" (v), "r" (p)
+ : "memory");
+#else
+ release_store_fence((volatile jint*)p, (jint)v);
+#endif // AMD64
+}
+
+#endif // OS_CPU_BSD_X86_VM_ORDERACCESS_BSD_X86_INLINE_HPP
diff --git a/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp b/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp
new file mode 100644
index 000000000..11374ac2f
--- /dev/null
+++ b/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp
@@ -0,0 +1,1124 @@
+/*
+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+// no precompiled headers
+#include "assembler_x86.inline.hpp"
+#include "classfile/classLoader.hpp"
+#include "classfile/systemDictionary.hpp"
+#include "classfile/vmSymbols.hpp"
+#include "code/icBuffer.hpp"
+#include "code/vtableStubs.hpp"
+#include "interpreter/interpreter.hpp"
+#include "jvm_bsd.h"
+#include "memory/allocation.inline.hpp"
+#include "mutex_bsd.inline.hpp"
+#include "nativeInst_x86.hpp"
+#include "os_share_bsd.hpp"
+#include "prims/jniFastGetField.hpp"
+#include "prims/jvm.h"
+#include "prims/jvm_misc.hpp"
+#include "runtime/arguments.hpp"
+#include "runtime/extendedPC.hpp"
+#include "runtime/frame.inline.hpp"
+#include "runtime/interfaceSupport.hpp"
+#include "runtime/java.hpp"
+#include "runtime/javaCalls.hpp"
+#include "runtime/mutexLocker.hpp"
+#include "runtime/osThread.hpp"
+#include "runtime/sharedRuntime.hpp"
+#include "runtime/stubRoutines.hpp"
+#include "runtime/timer.hpp"
+#include "thread_bsd.inline.hpp"
+#include "utilities/events.hpp"
+#include "utilities/vmError.hpp"
+#ifdef COMPILER1
+#include "c1/c1_Runtime1.hpp"
+#endif
+#ifdef COMPILER2
+#include "opto/runtime.hpp"
+#endif
+
+// put OS-includes here
+# include <sys/types.h>
+# include <sys/mman.h>
+# include <pthread.h>
+# include <signal.h>
+# include <errno.h>
+# include <dlfcn.h>
+# include <stdlib.h>
+# include <stdio.h>
+# include <unistd.h>
+# include <sys/resource.h>
+# include <pthread.h>
+# include <sys/stat.h>
+# include <sys/time.h>
+# include <sys/utsname.h>
+# include <sys/socket.h>
+# include <sys/wait.h>
+# include <pwd.h>
+# include <poll.h>
+#ifndef __OpenBSD__
+# include <ucontext.h>
+#endif
+
+#if defined(_ALLBSD_SOURCE) && !defined(__APPLE__) && !defined(__NetBSD__)
+# include <pthread_np.h>
+#endif
+
+#ifdef AMD64
+#define SPELL_REG_SP "rsp"
+#define SPELL_REG_FP "rbp"
+#else
+#define SPELL_REG_SP "esp"
+#define SPELL_REG_FP "ebp"
+#endif // AMD64
+
+#ifdef __FreeBSD__
+# define context_trapno uc_mcontext.mc_trapno
+# ifdef AMD64
+# define context_pc uc_mcontext.mc_rip
+# define context_sp uc_mcontext.mc_rsp
+# define context_fp uc_mcontext.mc_rbp
+# define context_rip uc_mcontext.mc_rip
+# define context_rsp uc_mcontext.mc_rsp
+# define context_rbp uc_mcontext.mc_rbp
+# define context_rax uc_mcontext.mc_rax
+# define context_rbx uc_mcontext.mc_rbx
+# define context_rcx uc_mcontext.mc_rcx
+# define context_rdx uc_mcontext.mc_rdx
+# define context_rsi uc_mcontext.mc_rsi
+# define context_rdi uc_mcontext.mc_rdi
+# define context_r8 uc_mcontext.mc_r8
+# define context_r9 uc_mcontext.mc_r9
+# define context_r10 uc_mcontext.mc_r10
+# define context_r11 uc_mcontext.mc_r11
+# define context_r12 uc_mcontext.mc_r12
+# define context_r13 uc_mcontext.mc_r13
+# define context_r14 uc_mcontext.mc_r14
+# define context_r15 uc_mcontext.mc_r15
+# define context_flags uc_mcontext.mc_flags
+# define context_err uc_mcontext.mc_err
+# else
+# define context_pc uc_mcontext.mc_eip
+# define context_sp uc_mcontext.mc_esp
+# define context_fp uc_mcontext.mc_ebp
+# define context_eip uc_mcontext.mc_eip
+# define context_esp uc_mcontext.mc_esp
+# define context_eax uc_mcontext.mc_eax
+# define context_ebx uc_mcontext.mc_ebx
+# define context_ecx uc_mcontext.mc_ecx
+# define context_edx uc_mcontext.mc_edx
+# define context_ebp uc_mcontext.mc_ebp
+# define context_esi uc_mcontext.mc_esi
+# define context_edi uc_mcontext.mc_edi
+# define context_eflags uc_mcontext.mc_eflags
+# define context_trapno uc_mcontext.mc_trapno
+# endif
+#endif
+
+#ifdef __APPLE__
+# if __DARWIN_UNIX03 && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
+ // 10.5 UNIX03 member name prefixes
+ #define DU3_PREFIX(s, m) __ ## s.__ ## m
+# else
+ #define DU3_PREFIX(s, m) s ## . ## m
+# endif
+
+# ifdef AMD64
+# define context_pc context_rip
+# define context_sp context_rsp
+# define context_fp context_rbp
+# define context_rip uc_mcontext->DU3_PREFIX(ss,rip)
+# define context_rsp uc_mcontext->DU3_PREFIX(ss,rsp)
+# define context_rax uc_mcontext->DU3_PREFIX(ss,rax)
+# define context_rbx uc_mcontext->DU3_PREFIX(ss,rbx)
+# define context_rcx uc_mcontext->DU3_PREFIX(ss,rcx)
+# define context_rdx uc_mcontext->DU3_PREFIX(ss,rdx)
+# define context_rbp uc_mcontext->DU3_PREFIX(ss,rbp)
+# define context_rsi uc_mcontext->DU3_PREFIX(ss,rsi)
+# define context_rdi uc_mcontext->DU3_PREFIX(ss,rdi)
+# define context_r8 uc_mcontext->DU3_PREFIX(ss,r8)
+# define context_r9 uc_mcontext->DU3_PREFIX(ss,r9)
+# define context_r10 uc_mcontext->DU3_PREFIX(ss,r10)
+# define context_r11 uc_mcontext->DU3_PREFIX(ss,r11)
+# define context_r12 uc_mcontext->DU3_PREFIX(ss,r12)
+# define context_r13 uc_mcontext->DU3_PREFIX(ss,r13)
+# define context_r14 uc_mcontext->DU3_PREFIX(ss,r14)
+# define context_r15 uc_mcontext->DU3_PREFIX(ss,r15)
+# define context_flags uc_mcontext->DU3_PREFIX(ss,rflags)
+# define context_trapno uc_mcontext->DU3_PREFIX(es,trapno)
+# define context_err uc_mcontext->DU3_PREFIX(es,err)
+# else
+# define context_pc context_eip
+# define context_sp context_esp
+# define context_fp context_ebp
+# define context_eip uc_mcontext->DU3_PREFIX(ss,eip)
+# define context_esp uc_mcontext->DU3_PREFIX(ss,esp)
+# define context_eax uc_mcontext->DU3_PREFIX(ss,eax)
+# define context_ebx uc_mcontext->DU3_PREFIX(ss,ebx)
+# define context_ecx uc_mcontext->DU3_PREFIX(ss,ecx)
+# define context_edx uc_mcontext->DU3_PREFIX(ss,edx)
+# define context_ebp uc_mcontext->DU3_PREFIX(ss,ebp)
+# define context_esi uc_mcontext->DU3_PREFIX(ss,esi)
+# define context_edi uc_mcontext->DU3_PREFIX(ss,edi)
+# define context_eflags uc_mcontext->DU3_PREFIX(ss,eflags)
+# define context_trapno uc_mcontext->DU3_PREFIX(es,trapno)
+# endif
+#endif
+
+#ifdef __OpenBSD__
+# define context_trapno sc_trapno
+# ifdef AMD64
+# define context_pc sc_rip
+# define context_sp sc_rsp
+# define context_fp sc_rbp
+# define context_rip sc_rip
+# define context_rsp sc_rsp
+# define context_rbp sc_rbp
+# define context_rax sc_rax
+# define context_rbx sc_rbx
+# define context_rcx sc_rcx
+# define context_rdx sc_rdx
+# define context_rsi sc_rsi
+# define context_rdi sc_rdi
+# define context_r8 sc_r8
+# define context_r9 sc_r9
+# define context_r10 sc_r10
+# define context_r11 sc_r11
+# define context_r12 sc_r12
+# define context_r13 sc_r13
+# define context_r14 sc_r14
+# define context_r15 sc_r15
+# define context_flags sc_rflags
+# define context_err sc_err
+# else
+# define context_pc sc_eip
+# define context_sp sc_esp
+# define context_fp sc_ebp
+# define context_eip sc_eip
+# define context_esp sc_esp
+# define context_eax sc_eax
+# define context_ebx sc_ebx
+# define context_ecx sc_ecx
+# define context_edx sc_edx
+# define context_ebp sc_ebp
+# define context_esi sc_esi
+# define context_edi sc_edi
+# define context_eflags sc_eflags
+# define context_trapno sc_trapno
+# endif
+#endif
+
+#ifdef __NetBSD__
+# define context_trapno uc_mcontext.__gregs[_REG_TRAPNO]
+# ifdef AMD64
+# define __register_t __greg_t
+# define context_pc uc_mcontext.__gregs[_REG_RIP]
+# define context_sp uc_mcontext.__gregs[_REG_URSP]
+# define context_fp uc_mcontext.__gregs[_REG_RBP]
+# define context_rip uc_mcontext.__gregs[_REG_RIP]
+# define context_rsp uc_mcontext.__gregs[_REG_URSP]
+# define context_rax uc_mcontext.__gregs[_REG_RAX]
+# define context_rbx uc_mcontext.__gregs[_REG_RBX]
+# define context_rcx uc_mcontext.__gregs[_REG_RCX]
+# define context_rdx uc_mcontext.__gregs[_REG_RDX]
+# define context_rbp uc_mcontext.__gregs[_REG_RBP]
+# define context_rsi uc_mcontext.__gregs[_REG_RSI]
+# define context_rdi uc_mcontext.__gregs[_REG_RDI]
+# define context_r8 uc_mcontext.__gregs[_REG_R8]
+# define context_r9 uc_mcontext.__gregs[_REG_R9]
+# define context_r10 uc_mcontext.__gregs[_REG_R10]
+# define context_r11 uc_mcontext.__gregs[_REG_R11]
+# define context_r12 uc_mcontext.__gregs[_REG_R12]
+# define context_r13 uc_mcontext.__gregs[_REG_R13]
+# define context_r14 uc_mcontext.__gregs[_REG_R14]
+# define context_r15 uc_mcontext.__gregs[_REG_R15]
+# define context_flags uc_mcontext.__gregs[_REG_RFL]
+# define context_err uc_mcontext.__gregs[_REG_ERR]
+# else
+# define context_pc uc_mcontext.__gregs[_REG_EIP]
+# define context_sp uc_mcontext.__gregs[_REG_UESP]
+# define context_fp uc_mcontext.__gregs[_REG_EBP]
+# define context_eip uc_mcontext.__gregs[_REG_EIP]
+# define context_esp uc_mcontext.__gregs[_REG_UESP]
+# define context_eax uc_mcontext.__gregs[_REG_EAX]
+# define context_ebx uc_mcontext.__gregs[_REG_EBX]
+# define context_ecx uc_mcontext.__gregs[_REG_ECX]
+# define context_edx uc_mcontext.__gregs[_REG_EDX]
+# define context_ebp uc_mcontext.__gregs[_REG_EBP]
+# define context_esi uc_mcontext.__gregs[_REG_ESI]
+# define context_edi uc_mcontext.__gregs[_REG_EDI]
+# define context_eflags uc_mcontext.__gregs[_REG_EFL]
+# define context_trapno uc_mcontext.__gregs[_REG_TRAPNO]
+# endif
+#endif
+
+address os::current_stack_pointer() {
+#ifdef SPARC_WORKS
+ register void *esp;
+ __asm__("mov %%"SPELL_REG_SP", %0":"=r"(esp));
+ return (address) ((char*)esp + sizeof(long)*2);
+#else
+ register void *esp __asm__ (SPELL_REG_SP);
+ return (address) esp;
+#endif
+}
+
+char* os::non_memory_address_word() {
+ // Must never look like an address returned by reserve_memory,
+ // even in its subfields (as defined by the CPU immediate fields,
+ // if the CPU splits constants across multiple instructions).
+
+ return (char*) -1;
+}
+
+void os::initialize_thread() {
+// Nothing to do.
+}
+
+address os::Bsd::ucontext_get_pc(ucontext_t * uc) {
+ return (address)uc->context_pc;
+}
+
+intptr_t* os::Bsd::ucontext_get_sp(ucontext_t * uc) {
+ return (intptr_t*)uc->context_sp;
+}
+
+intptr_t* os::Bsd::ucontext_get_fp(ucontext_t * uc) {
+ return (intptr_t*)uc->context_fp;
+}
+
+// For Forte Analyzer AsyncGetCallTrace profiling support - thread
+// is currently interrupted by SIGPROF.
+// os::Solaris::fetch_frame_from_ucontext() tries to skip nested signal
+// frames. Currently we don't do that on Bsd, so it's the same as
+// os::fetch_frame_from_context().
+ExtendedPC os::Bsd::fetch_frame_from_ucontext(Thread* thread,
+ ucontext_t* uc, intptr_t** ret_sp, intptr_t** ret_fp) {
+
+ assert(thread != NULL, "just checking");
+ assert(ret_sp != NULL, "just checking");
+ assert(ret_fp != NULL, "just checking");
+
+ return os::fetch_frame_from_context(uc, ret_sp, ret_fp);
+}
+
+ExtendedPC os::fetch_frame_from_context(void* ucVoid,
+ intptr_t** ret_sp, intptr_t** ret_fp) {
+
+ ExtendedPC epc;
+ ucontext_t* uc = (ucontext_t*)ucVoid;
+
+ if (uc != NULL) {
+ epc = ExtendedPC(os::Bsd::ucontext_get_pc(uc));
+ if (ret_sp) *ret_sp = os::Bsd::ucontext_get_sp(uc);
+ if (ret_fp) *ret_fp = os::Bsd::ucontext_get_fp(uc);
+ } else {
+ // construct empty ExtendedPC for return value checking
+ epc = ExtendedPC(NULL);
+ if (ret_sp) *ret_sp = (intptr_t *)NULL;
+ if (ret_fp) *ret_fp = (intptr_t *)NULL;
+ }
+
+ return epc;
+}
+
+frame os::fetch_frame_from_context(void* ucVoid) {
+ intptr_t* sp;
+ intptr_t* fp;
+ ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, &fp);
+ return frame(sp, fp, epc.pc());
+}
+
+// By default, gcc always save frame pointer (%ebp/%rbp) on stack. It may get
+// turned off by -fomit-frame-pointer,
+frame os::get_sender_for_C_frame(frame* fr) {
+ return frame(fr->sender_sp(), fr->link(), fr->sender_pc());
+}
+
+intptr_t* _get_previous_fp() {
+#ifdef SPARC_WORKS
+ register intptr_t **ebp;
+ __asm__("mov %%"SPELL_REG_FP", %0":"=r"(ebp));
+#else
+ register intptr_t **ebp __asm__ (SPELL_REG_FP);
+#endif
+ return (intptr_t*) *ebp; // we want what it points to.
+}
+
+
+frame os::current_frame() {
+ intptr_t* fp = _get_previous_fp();
+ frame myframe((intptr_t*)os::current_stack_pointer(),
+ (intptr_t*)fp,
+ CAST_FROM_FN_PTR(address, os::current_frame));
+ if (os::is_first_C_frame(&myframe)) {
+ // stack is not walkable
+ return frame(NULL, NULL, NULL);
+ } else {
+ return os::get_sender_for_C_frame(&myframe);
+ }
+}
+
+// Utility functions
+
+// From IA32 System Programming Guide
+enum {
+ trap_page_fault = 0xE
+};
+
+extern "C" void Fetch32PFI () ;
+extern "C" void Fetch32Resume () ;
+#ifdef AMD64
+extern "C" void FetchNPFI () ;
+extern "C" void FetchNResume () ;
+#endif // AMD64
+
+extern "C" JNIEXPORT int
+JVM_handle_bsd_signal(int sig,
+ siginfo_t* info,
+ void* ucVoid,
+ int abort_if_unrecognized) {
+ ucontext_t* uc = (ucontext_t*) ucVoid;
+
+ Thread* t = ThreadLocalStorage::get_thread_slow();
+
+ SignalHandlerMark shm(t);
+
+ // Note: it's not uncommon that JNI code uses signal/sigset to install
+ // then restore certain signal handler (e.g. to temporarily block SIGPIPE,
+ // or have a SIGILL handler when detecting CPU type). When that happens,
+ // JVM_handle_bsd_signal() might be invoked with junk info/ucVoid. To
+ // avoid unnecessary crash when libjsig is not preloaded, try handle signals
+ // that do not require siginfo/ucontext first.
+
+ if (sig == SIGPIPE || sig == SIGXFSZ) {
+ // allow chained handler to go first
+ if (os::Bsd::chained_handler(sig, info, ucVoid)) {
+ return true;
+ } else {
+ if (PrintMiscellaneous && (WizardMode || Verbose)) {
+ char buf[64];
+ warning("Ignoring %s - see bugs 4229104 or 646499219",
+ os::exception_name(sig, buf, sizeof(buf)));
+ }
+ return true;
+ }
+ }
+
+ JavaThread* thread = NULL;
+ VMThread* vmthread = NULL;
+ if (os::Bsd::signal_handlers_are_installed) {
+ if (t != NULL ){
+ if(t->is_Java_thread()) {
+ thread = (JavaThread*)t;
+ }
+ else if(t->is_VM_thread()){
+ vmthread = (VMThread *)t;
+ }
+ }
+ }
+/*
+ NOTE: does not seem to work on bsd.
+ if (info == NULL || info->si_code <= 0 || info->si_code == SI_NOINFO) {
+ // can't decode this kind of signal
+ info = NULL;
+ } else {
+ assert(sig == info->si_signo, "bad siginfo");
+ }
+*/
+ // decide if this trap can be handled by a stub
+ address stub = NULL;
+
+ address pc = NULL;
+
+ //%note os_trap_1
+ if (info != NULL && uc != NULL && thread != NULL) {
+ pc = (address) os::Bsd::ucontext_get_pc(uc);
+
+ if (pc == (address) Fetch32PFI) {
+ uc->context_pc = intptr_t(Fetch32Resume) ;
+ return 1 ;
+ }
+#ifdef AMD64
+ if (pc == (address) FetchNPFI) {
+ uc->context_pc = intptr_t (FetchNResume) ;
+ return 1 ;
+ }
+#endif // AMD64
+
+ // Handle ALL stack overflow variations here
+ if (sig == SIGSEGV || sig == SIGBUS) {
+ address addr = (address) info->si_addr;
+
+ // check if fault address is within thread stack
+ if (addr < thread->stack_base() &&
+ addr >= thread->stack_base() - thread->stack_size()) {
+ // stack overflow
+ if (thread->in_stack_yellow_zone(addr)) {
+ thread->disable_stack_yellow_zone();
+ if (thread->thread_state() == _thread_in_Java) {
+ // Throw a stack overflow exception. Guard pages will be reenabled
+ // while unwinding the stack.
+ stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW);
+ } else {
+ // Thread was in the vm or native code. Return and try to finish.
+ return 1;
+ }
+ } else if (thread->in_stack_red_zone(addr)) {
+ // Fatal red zone violation. Disable the guard pages and fall through
+ // to handle_unexpected_exception way down below.
+ thread->disable_stack_red_zone();
+ tty->print_raw_cr("An irrecoverable stack overflow has occurred.");
+#ifndef _ALLBSD_SOURCE
+ } else {
+ // Accessing stack address below sp may cause SEGV if current
+ // thread has MAP_GROWSDOWN stack. This should only happen when
+ // current thread was created by user code with MAP_GROWSDOWN flag
+ // and then attached to VM. See notes in os_bsd.cpp.
+ if (thread->osthread()->expanding_stack() == 0) {
+ thread->osthread()->set_expanding_stack();
+ if (os::Bsd::manually_expand_stack(thread, addr)) {
+ thread->osthread()->clear_expanding_stack();
+ return 1;
+ }
+ thread->osthread()->clear_expanding_stack();
+ } else {
+ fatal("recursive segv. expanding stack.");
+ }
+#endif
+ }
+ }
+ }
+
+ if (thread->thread_state() == _thread_in_Java) {
+ // Java thread running in Java code => find exception handler if any
+ // a fault inside compiled code, the interpreter, or a stub
+
+ if ((sig == SIGSEGV || sig == SIGBUS) && os::is_poll_address((address)info->si_addr)) {
+ stub = SharedRuntime::get_poll_stub(pc);
+#if defined(__APPLE__) && !defined(AMD64)
+ // 32-bit Darwin reports a SIGBUS for nearly all memory access exceptions.
+ // Catching SIGBUS here prevents the implicit SIGBUS NULL check below from
+ // being called, so only do so if the implicit NULL check is not necessary.
+ } else if (sig == SIGBUS && MacroAssembler::needs_explicit_null_check((int)info->si_addr)) {
+#else
+ } else if (sig == SIGBUS /* && info->si_code == BUS_OBJERR */) {
+#endif
+ // BugId 4454115: A read from a MappedByteBuffer can fault
+ // here if the underlying file has been truncated.
+ // Do not crash the VM in such a case.
+ CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
+ nmethod* nm = cb->is_nmethod() ? (nmethod*)cb : NULL;
+ if (nm != NULL && nm->has_unsafe_access()) {
+ stub = StubRoutines::handler_for_unsafe_access();
+ }
+ }
+ else
+
+#ifdef AMD64
+ if (sig == SIGFPE &&
+ (info->si_code == FPE_INTDIV || info->si_code == FPE_FLTDIV)) {
+ stub =
+ SharedRuntime::
+ continuation_for_implicit_exception(thread,
+ pc,
+ SharedRuntime::
+ IMPLICIT_DIVIDE_BY_ZERO);
+#ifdef __APPLE__
+ } else if (sig == SIGFPE && info->si_code == FPE_NOOP) {
+ int op = pc[0];
+
+ // Skip REX
+ if ((pc[0] & 0xf0) == 0x40) {
+ op = pc[1];
+ } else {
+ op = pc[0];
+ }
+
+ // Check for IDIV
+ if (op == 0xF7) {
+ stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime:: IMPLICIT_DIVIDE_BY_ZERO);
+ } else {
+ // TODO: handle more cases if we are using other x86 instructions
+ // that can generate SIGFPE signal.
+ tty->print_cr("unknown opcode 0x%X with SIGFPE.", op);
+ fatal("please update this code.");
+ }
+#endif /* __APPLE__ */
+
+#else
+ if (sig == SIGFPE /* && info->si_code == FPE_INTDIV */) {
+ // HACK: si_code does not work on bsd 2.2.12-20!!!
+ int op = pc[0];
+ if (op == 0xDB) {
+ // FIST
+ // TODO: The encoding of D2I in i486.ad can cause an exception
+ // prior to the fist instruction if there was an invalid operation
+ // pending. We want to dismiss that exception. From the win_32
+ // side it also seems that if it really was the fist causing
+ // the exception that we do the d2i by hand with different
+ // rounding. Seems kind of weird.
+ // NOTE: that we take the exception at the NEXT floating point instruction.
+ assert(pc[0] == 0xDB, "not a FIST opcode");
+ assert(pc[1] == 0x14, "not a FIST opcode");
+ assert(pc[2] == 0x24, "not a FIST opcode");
+ return true;
+ } else if (op == 0xF7) {
+ // IDIV
+ stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_DIVIDE_BY_ZERO);
+ } else {
+ // TODO: handle more cases if we are using other x86 instructions
+ // that can generate SIGFPE signal on bsd.
+ tty->print_cr("unknown opcode 0x%X with SIGFPE.", op);
+ fatal("please update this code.");
+ }
+#endif // AMD64
+ } else if ((sig == SIGSEGV || sig == SIGBUS) &&
+ !MacroAssembler::needs_explicit_null_check((intptr_t)info->si_addr)) {
+ // Determination of interpreter/vtable stub/compiled code null exception
+ stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL);
+ }
+ } else if (thread->thread_state() == _thread_in_vm &&
+ sig == SIGBUS && /* info->si_code == BUS_OBJERR && */
+ thread->doing_unsafe_access()) {
+ stub = StubRoutines::handler_for_unsafe_access();
+ }
+
+ // jni_fast_Get<Primitive>Field can trap at certain pc's if a GC kicks in
+ // and the heap gets shrunk before the field access.
+ if ((sig == SIGSEGV) || (sig == SIGBUS)) {
+ address addr = JNI_FastGetField::find_slowcase_pc(pc);
+ if (addr != (address)-1) {
+ stub = addr;
+ }
+ }
+
+ // Check to see if we caught the safepoint code in the
+ // process of write protecting the memory serialization page.
+ // It write enables the page immediately after protecting it
+ // so we can just return to retry the write.
+ if ((sig == SIGSEGV || sig == SIGBUS) &&
+ os::is_memory_serialize_page(thread, (address) info->si_addr)) {
+ // Block current thread until the memory serialize page permission restored.
+ os::block_on_serialize_page_trap();
+ return true;
+ }
+ }
+
+#ifndef AMD64
+ // Execution protection violation
+ //
+ // This should be kept as the last step in the triage. We don't
+ // have a dedicated trap number for a no-execute fault, so be
+ // conservative and allow other handlers the first shot.
+ //
+ // Note: We don't test that info->si_code == SEGV_ACCERR here.
+ // this si_code is so generic that it is almost meaningless; and
+ // the si_code for this condition may change in the future.
+ // Furthermore, a false-positive should be harmless.
+ if (UnguardOnExecutionViolation > 0 &&
+ (sig == SIGSEGV || sig == SIGBUS) &&
+ uc->context_trapno == trap_page_fault) {
+ int page_size = os::vm_page_size();
+ address addr = (address) info->si_addr;
+ address pc = os::Bsd::ucontext_get_pc(uc);
+ // Make sure the pc and the faulting address are sane.
+ //
+ // If an instruction spans a page boundary, and the page containing
+ // the beginning of the instruction is executable but the following
+ // page is not, the pc and the faulting address might be slightly
+ // different - we still want to unguard the 2nd page in this case.
+ //
+ // 15 bytes seems to be a (very) safe value for max instruction size.
+ bool pc_is_near_addr =
+ (pointer_delta((void*) addr, (void*) pc, sizeof(char)) < 15);
+ bool instr_spans_page_boundary =
+ (align_size_down((intptr_t) pc ^ (intptr_t) addr,
+ (intptr_t) page_size) > 0);
+
+ if (pc == addr || (pc_is_near_addr && instr_spans_page_boundary)) {
+ static volatile address last_addr =
+ (address) os::non_memory_address_word();
+
+ // In conservative mode, don't unguard unless the address is in the VM
+ if (addr != last_addr &&
+ (UnguardOnExecutionViolation > 1 || os::address_is_in_vm(addr))) {
+
+ // Set memory to RWX and retry
+ address page_start =
+ (address) align_size_down((intptr_t) addr, (intptr_t) page_size);
+ bool res = os::protect_memory((char*) page_start, page_size,
+ os::MEM_PROT_RWX);
+
+ if (PrintMiscellaneous && Verbose) {
+ char buf[256];
+ jio_snprintf(buf, sizeof(buf), "Execution protection violation "
+ "at " INTPTR_FORMAT
+ ", unguarding " INTPTR_FORMAT ": %s, errno=%d", addr,
+ page_start, (res ? "success" : "failed"), errno);
+ tty->print_raw_cr(buf);
+ }
+ stub = pc;
+
+ // Set last_addr so if we fault again at the same address, we don't end
+ // up in an endless loop.
+ //
+ // There are two potential complications here. Two threads trapping at
+ // the same address at the same time could cause one of the threads to
+ // think it already unguarded, and abort the VM. Likely very rare.
+ //
+ // The other race involves two threads alternately trapping at
+ // different addresses and failing to unguard the page, resulting in
+ // an endless loop. This condition is probably even more unlikely than
+ // the first.
+ //
+ // Although both cases could be avoided by using locks or thread local
+ // last_addr, these solutions are unnecessary complication: this
+ // handler is a best-effort safety net, not a complete solution. It is
+ // disabled by default and should only be used as a workaround in case
+ // we missed any no-execute-unsafe VM code.
+
+ last_addr = addr;
+ }
+ }
+ }
+#endif // !AMD64
+
+ if (stub != NULL) {
+ // save all thread context in case we need to restore it
+ if (thread != NULL) thread->set_saved_exception_pc(pc);
+
+ uc->context_pc = (intptr_t)stub;
+ return true;
+ }
+
+ // signal-chaining
+ if (os::Bsd::chained_handler(sig, info, ucVoid)) {
+ return true;
+ }
+
+ if (!abort_if_unrecognized) {
+ // caller wants another chance, so give it to him
+ return false;
+ }
+
+ if (pc == NULL && uc != NULL) {
+ pc = os::Bsd::ucontext_get_pc(uc);
+ }
+
+ // unmask current signal
+ sigset_t newset;
+ sigemptyset(&newset);
+ sigaddset(&newset, sig);
+ sigprocmask(SIG_UNBLOCK, &newset, NULL);
+
+ VMError err(t, sig, pc, info, ucVoid);
+ err.report_and_die();
+
+ ShouldNotReachHere();
+}
+
+#ifdef _ALLBSD_SOURCE
+// From solaris_i486.s ported to bsd_i486.s
+extern "C" void fixcw();
+#endif
+
+void os::Bsd::init_thread_fpu_state(void) {
+#ifndef AMD64
+# ifdef _ALLBSD_SOURCE
+ // Set fpu to 53 bit precision. This happens too early to use a stub.
+ fixcw();
+# else
+ // set fpu to 53 bit precision
+ set_fpu_control_word(0x27f);
+# endif
+#endif // !AMD64
+}
+
+#ifndef _ALLBSD_SOURCE
+int os::Bsd::get_fpu_control_word(void) {
+#ifdef AMD64
+ return 0;
+#else
+ int fpu_control;
+ _FPU_GETCW(fpu_control);
+ return fpu_control & 0xffff;
+#endif // AMD64
+}
+
+void os::Bsd::set_fpu_control_word(int fpu_control) {
+#ifndef AMD64
+ _FPU_SETCW(fpu_control);
+#endif // !AMD64
+}
+#endif
+
+// Check that the bsd kernel version is 2.4 or higher since earlier
+// versions do not support SSE without patches.
+bool os::supports_sse() {
+#if defined(AMD64) || defined(_ALLBSD_SOURCE)
+ return true;
+#else
+ struct utsname uts;
+ if( uname(&uts) != 0 ) return false; // uname fails?
+ char *minor_string;
+ int major = strtol(uts.release,&minor_string,10);
+ int minor = strtol(minor_string+1,NULL,10);
+ bool result = (major > 2 || (major==2 && minor >= 4));
+#ifndef PRODUCT
+ if (PrintMiscellaneous && Verbose) {
+ tty->print("OS version is %d.%d, which %s support SSE/SSE2\n",
+ major,minor, result ? "DOES" : "does NOT");
+ }
+#endif
+ return result;
+#endif // AMD64
+}
+
+bool os::is_allocatable(size_t bytes) {
+#ifdef AMD64
+ // unused on amd64?
+ return true;
+#else
+
+ if (bytes < 2 * G) {
+ return true;
+ }
+
+ char* addr = reserve_memory(bytes, NULL);
+
+ if (addr != NULL) {
+ release_memory(addr, bytes);
+ }
+
+ return addr != NULL;
+#endif // AMD64
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// thread stack
+
+#ifdef AMD64
+size_t os::Bsd::min_stack_allowed = 64 * K;
+
+// amd64: pthread on amd64 is always in floating stack mode
+bool os::Bsd::supports_variable_stack_size() { return true; }
+#else
+size_t os::Bsd::min_stack_allowed = (48 DEBUG_ONLY(+4))*K;
+
+#ifdef __GNUC__
+#define GET_GS() ({int gs; __asm__ volatile("movw %%gs, %w0":"=q"(gs)); gs&0xffff;})
+#endif
+
+#ifdef _ALLBSD_SOURCE
+bool os::Bsd::supports_variable_stack_size() { return true; }
+#else
+// Test if pthread library can support variable thread stack size. BsdThreads
+// in fixed stack mode allocates 2M fixed slot for each thread. BsdThreads
+// in floating stack mode and NPTL support variable stack size.
+bool os::Bsd::supports_variable_stack_size() {
+ if (os::Bsd::is_NPTL()) {
+ // NPTL, yes
+ return true;
+
+ } else {
+ // Note: We can't control default stack size when creating a thread.
+ // If we use non-default stack size (pthread_attr_setstacksize), both
+ // floating stack and non-floating stack BsdThreads will return the
+ // same value. This makes it impossible to implement this function by
+ // detecting thread stack size directly.
+ //
+ // An alternative approach is to check %gs. Fixed-stack BsdThreads
+ // do not use %gs, so its value is 0. Floating-stack BsdThreads use
+ // %gs (either as LDT selector or GDT selector, depending on kernel)
+ // to access thread specific data.
+ //
+ // Note that %gs is a reserved glibc register since early 2001, so
+ // applications are not allowed to change its value (Ulrich Drepper from
+ // Redhat confirmed that all known offenders have been modified to use
+ // either %fs or TSD). In the worst case scenario, when VM is embedded in
+ // a native application that plays with %gs, we might see non-zero %gs
+ // even BsdThreads is running in fixed stack mode. As the result, we'll
+ // return true and skip _thread_safety_check(), so we may not be able to
+ // detect stack-heap collisions. But otherwise it's harmless.
+ //
+#ifdef __GNUC__
+ return (GET_GS() != 0);
+#else
+ return false;
+#endif
+ }
+}
+#endif
+#endif // AMD64
+
+// return default stack size for thr_type
+size_t os::Bsd::default_stack_size(os::ThreadType thr_type) {
+ // default stack size (compiler thread needs larger stack)
+#ifdef AMD64
+ size_t s = (thr_type == os::compiler_thread ? 4 * M : 1 * M);
+#else
+ size_t s = (thr_type == os::compiler_thread ? 2 * M : 512 * K);
+#endif // AMD64
+ return s;
+}
+
+size_t os::Bsd::default_guard_size(os::ThreadType thr_type) {
+ // Creating guard page is very expensive. Java thread has HotSpot
+ // guard page, only enable glibc guard page for non-Java threads.
+ return (thr_type == java_thread ? 0 : page_size());
+}
+
+// Java thread:
+//
+// Low memory addresses
+// +------------------------+
+// | |\ JavaThread created by VM does not have glibc
+// | glibc guard page | - guard, attached Java thread usually has
+// | |/ 1 page glibc guard.
+// P1 +------------------------+ Thread::stack_base() - Thread::stack_size()
+// | |\
+// | HotSpot Guard Pages | - red and yellow pages
+// | |/
+// +------------------------+ JavaThread::stack_yellow_zone_base()
+// | |\
+// | Normal Stack | -
+// | |/
+// P2 +------------------------+ Thread::stack_base()
+//
+// Non-Java thread:
+//
+// Low memory addresses
+// +------------------------+
+// | |\
+// | glibc guard page | - usually 1 page
+// | |/
+// P1 +------------------------+ Thread::stack_base() - Thread::stack_size()
+// | |\
+// | Normal Stack | -
+// | |/
+// P2 +------------------------+ Thread::stack_base()
+//
+// ** P1 (aka bottom) and size ( P2 = P1 - size) are the address and stack size returned from
+// pthread_attr_getstack()
+
+static void current_stack_region(address * bottom, size_t * size) {
+#ifdef __APPLE__
+ pthread_t self = pthread_self();
+ void *stacktop = pthread_get_stackaddr_np(self);
+ *size = pthread_get_stacksize_np(self);
+ *bottom = (address) stacktop - *size;
+#elif defined(__OpenBSD__)
+ stack_t ss;
+ int rslt = pthread_stackseg_np(pthread_self(), &ss);
+
+ if (rslt != 0)
+ fatal(err_msg("pthread_stackseg_np failed with err = %d", rslt));
+
+ *bottom = (address)((char *)ss.ss_sp - ss.ss_size);
+ *size = ss.ss_size;
+#elif defined(_ALLBSD_SOURCE)
+ pthread_attr_t attr;
+
+ int rslt = pthread_attr_init(&attr);
+
+ // JVM needs to know exact stack location, abort if it fails
+ if (rslt != 0)
+ fatal(err_msg("pthread_attr_init failed with err = %d", rslt));
+
+ rslt = pthread_attr_get_np(pthread_self(), &attr);
+
+ if (rslt != 0)
+ fatal(err_msg("pthread_attr_get_np failed with err = %d", rslt));
+
+ if (pthread_attr_getstackaddr(&attr, (void **)bottom) != 0 ||
+ pthread_attr_getstacksize(&attr, size) != 0) {
+ fatal("Can not locate current stack attributes!");
+ }
+
+ pthread_attr_destroy(&attr);
+#else
+ if (os::Bsd::is_initial_thread()) {
+ // initial thread needs special handling because pthread_getattr_np()
+ // may return bogus value.
+ *bottom = os::Bsd::initial_thread_stack_bottom();
+ *size = os::Bsd::initial_thread_stack_size();
+ } else {
+ pthread_attr_t attr;
+
+ int rslt = pthread_getattr_np(pthread_self(), &attr);
+
+ // JVM needs to know exact stack location, abort if it fails
+ if (rslt != 0) {
+ if (rslt == ENOMEM) {
+ vm_exit_out_of_memory(0, "pthread_getattr_np");
+ } else {
+ fatal(err_msg("pthread_getattr_np failed with errno = %d", rslt));
+ }
+ }
+
+ if (pthread_attr_getstack(&attr, (void **)bottom, size) != 0) {
+ fatal("Can not locate current stack attributes!");
+ }
+
+ pthread_attr_destroy(&attr);
+
+ }
+#endif
+ assert(os::current_stack_pointer() >= *bottom &&
+ os::current_stack_pointer() < *bottom + *size, "just checking");
+}
+
+address os::current_stack_base() {
+ address bottom;
+ size_t size;
+ current_stack_region(&bottom, &size);
+ return (bottom + size);
+}
+
+size_t os::current_stack_size() {
+ // stack size includes normal stack and HotSpot guard pages
+ address bottom;
+ size_t size;
+ current_stack_region(&bottom, &size);
+ return size;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// helper functions for fatal error handler
+
+void os::print_context(outputStream *st, void *context) {
+ if (context == NULL) return;
+
+ ucontext_t *uc = (ucontext_t*)context;
+ st->print_cr("Registers:");
+#ifdef AMD64
+ st->print( "RAX=" INTPTR_FORMAT, uc->context_rax);
+ st->print(", RBX=" INTPTR_FORMAT, uc->context_rbx);
+ st->print(", RCX=" INTPTR_FORMAT, uc->context_rcx);
+ st->print(", RDX=" INTPTR_FORMAT, uc->context_rdx);
+ st->cr();
+ st->print( "RSP=" INTPTR_FORMAT, uc->context_rsp);
+ st->print(", RBP=" INTPTR_FORMAT, uc->context_rbp);
+ st->print(", RSI=" INTPTR_FORMAT, uc->context_rsi);
+ st->print(", RDI=" INTPTR_FORMAT, uc->context_rdi);
+ st->cr();
+ st->print( "R8 =" INTPTR_FORMAT, uc->context_r8);
+ st->print(", R9 =" INTPTR_FORMAT, uc->context_r9);
+ st->print(", R10=" INTPTR_FORMAT, uc->context_r10);
+ st->print(", R11=" INTPTR_FORMAT, uc->context_r11);
+ st->cr();
+ st->print( "R12=" INTPTR_FORMAT, uc->context_r12);
+ st->print(", R13=" INTPTR_FORMAT, uc->context_r13);
+ st->print(", R14=" INTPTR_FORMAT, uc->context_r14);
+ st->print(", R15=" INTPTR_FORMAT, uc->context_r15);
+ st->cr();
+ st->print( "RIP=" INTPTR_FORMAT, uc->context_rip);
+ st->print(", EFLAGS=" INTPTR_FORMAT, uc->context_flags);
+ st->print(", ERR=" INTPTR_FORMAT, uc->context_err);
+ st->cr();
+ st->print(" TRAPNO=" INTPTR_FORMAT, uc->context_trapno);
+#else
+ st->print( "EAX=" INTPTR_FORMAT, uc->context_eax);
+ st->print(", EBX=" INTPTR_FORMAT, uc->context_ebx);
+ st->print(", ECX=" INTPTR_FORMAT, uc->context_ecx);
+ st->print(", EDX=" INTPTR_FORMAT, uc->context_edx);
+ st->cr();
+ st->print( "ESP=" INTPTR_FORMAT, uc->context_esp);
+ st->print(", EBP=" INTPTR_FORMAT, uc->context_ebp);
+ st->print(", ESI=" INTPTR_FORMAT, uc->context_esi);
+ st->print(", EDI=" INTPTR_FORMAT, uc->context_edi);
+ st->cr();
+ st->print( "EIP=" INTPTR_FORMAT, uc->context_eip);
+ st->print(", EFLAGS=" INTPTR_FORMAT, uc->context_eflags);
+#endif // AMD64
+ st->cr();
+ st->cr();
+
+ intptr_t *sp = (intptr_t *)os::Bsd::ucontext_get_sp(uc);
+ st->print_cr("Top of Stack: (sp=" PTR_FORMAT ")", sp);
+ print_hex_dump(st, (address)sp, (address)(sp + 8*sizeof(intptr_t)), sizeof(intptr_t));
+ st->cr();
+
+ // Note: it may be unsafe to inspect memory near pc. For example, pc may
+ // point to garbage if entry point in an nmethod is corrupted. Leave
+ // this at the end, and hope for the best.
+ address pc = os::Bsd::ucontext_get_pc(uc);
+ st->print_cr("Instructions: (pc=" PTR_FORMAT ")", pc);
+ print_hex_dump(st, pc - 32, pc + 32, sizeof(char));
+}
+
+void os::print_register_info(outputStream *st, void *context) {
+ if (context == NULL) return;
+
+ ucontext_t *uc = (ucontext_t*)context;
+
+ st->print_cr("Register to memory mapping:");
+ st->cr();
+
+ // this is horrendously verbose but the layout of the registers in the
+ // context does not match how we defined our abstract Register set, so
+ // we can't just iterate through the gregs area
+
+ // this is only for the "general purpose" registers
+
+#ifdef AMD64
+ st->print("RAX="); print_location(st, uc->context_rax);
+ st->print("RBX="); print_location(st, uc->context_rbx);
+ st->print("RCX="); print_location(st, uc->context_rcx);
+ st->print("RDX="); print_location(st, uc->context_rdx);
+ st->print("RSP="); print_location(st, uc->context_rsp);
+ st->print("RBP="); print_location(st, uc->context_rbp);
+ st->print("RSI="); print_location(st, uc->context_rsi);
+ st->print("RDI="); print_location(st, uc->context_rdi);
+ st->print("R8 ="); print_location(st, uc->context_r8);
+ st->print("R9 ="); print_location(st, uc->context_r9);
+ st->print("R10="); print_location(st, uc->context_r10);
+ st->print("R11="); print_location(st, uc->context_r11);
+ st->print("R12="); print_location(st, uc->context_r12);
+ st->print("R13="); print_location(st, uc->context_r13);
+ st->print("R14="); print_location(st, uc->context_r14);
+ st->print("R15="); print_location(st, uc->context_r15);
+#else
+ st->print("EAX="); print_location(st, uc->context_eax);
+ st->print("EBX="); print_location(st, uc->context_ebx);
+ st->print("ECX="); print_location(st, uc->context_ecx);
+ st->print("EDX="); print_location(st, uc->context_edx);
+ st->print("ESP="); print_location(st, uc->context_esp);
+ st->print("EBP="); print_location(st, uc->context_ebp);
+ st->print("ESI="); print_location(st, uc->context_esi);
+ st->print("EDI="); print_location(st, uc->context_edi);
+#endif // AMD64
+
+ st->cr();
+}
+
+void os::setup_fpu() {
+#ifndef AMD64
+ address fpu_cntrl = StubRoutines::addr_fpu_cntrl_wrd_std();
+ __asm__ volatile ( "fldcw (%0)" :
+ : "r" (fpu_cntrl) : "memory");
+#endif // !AMD64
+}
diff --git a/src/os_cpu/bsd_x86/vm/os_bsd_x86.hpp b/src/os_cpu/bsd_x86/vm/os_bsd_x86.hpp
new file mode 100644
index 000000000..7a4e71081
--- /dev/null
+++ b/src/os_cpu/bsd_x86/vm/os_bsd_x86.hpp
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ *
+ * 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 OS_CPU_BSD_X86_VM_OS_BSD_X86_HPP
+#define OS_CPU_BSD_X86_VM_OS_BSD_X86_HPP
+
+ static void setup_fpu();
+ static bool supports_sse();
+
+ static bool is_allocatable(size_t bytes);
+
+ // Used to register dynamic code cache area with the OS
+ // Note: Currently only used in 64 bit Windows implementations
+ static bool register_code_area(char *low, char *high) { return true; }
+
+#endif // OS_CPU_BSD_X86_VM_OS_BSD_X86_HPP
diff --git a/src/os_cpu/bsd_x86/vm/prefetch_bsd_x86.inline.hpp b/src/os_cpu/bsd_x86/vm/prefetch_bsd_x86.inline.hpp
new file mode 100644
index 000000000..6da429be0
--- /dev/null
+++ b/src/os_cpu/bsd_x86/vm/prefetch_bsd_x86.inline.hpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef OS_CPU_BSD_X86_VM_PREFETCH_BSD_X86_INLINE_HPP
+#define OS_CPU_BSD_X86_VM_PREFETCH_BSD_X86_INLINE_HPP
+
+#include "runtime/prefetch.hpp"
+
+
+inline void Prefetch::read (void *loc, intx interval) {
+#ifdef AMD64
+ __asm__ ("prefetcht0 (%0,%1,1)" : : "r" (loc), "r" (interval));
+#endif // AMD64
+}
+
+inline void Prefetch::write(void *loc, intx interval) {
+#ifdef AMD64
+
+ // Do not use the 3dnow prefetchw instruction. It isn't supported on em64t.
+ // __asm__ ("prefetchw (%0,%1,1)" : : "r" (loc), "r" (interval));
+ __asm__ ("prefetcht0 (%0,%1,1)" : : "r" (loc), "r" (interval));
+
+#endif // AMD64
+}
+
+#endif // OS_CPU_BSD_X86_VM_PREFETCH_BSD_X86_INLINE_HPP
diff --git a/src/os_cpu/bsd_x86/vm/threadLS_bsd_x86.cpp b/src/os_cpu/bsd_x86/vm/threadLS_bsd_x86.cpp
new file mode 100644
index 000000000..3c76437cc
--- /dev/null
+++ b/src/os_cpu/bsd_x86/vm/threadLS_bsd_x86.cpp
@@ -0,0 +1,92 @@
+/*
+ * 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.
+ *
+ * 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 "precompiled.hpp"
+#include "runtime/threadLocalStorage.hpp"
+#include "thread_bsd.inline.hpp"
+
+// Map stack pointer (%esp) to thread pointer for faster TLS access
+//
+// Here we use a flat table for better performance. Getting current thread
+// is down to one memory access (read _sp_map[%esp>>12]) in generated code
+// and two in runtime code (-fPIC code needs an extra load for _sp_map).
+//
+// This code assumes stack page is not shared by different threads. It works
+// in 32-bit VM when page size is 4K (or a multiple of 4K, if that matters).
+//
+// Notice that _sp_map is allocated in the bss segment, which is ZFOD
+// (zero-fill-on-demand). While it reserves 4M address space upfront,
+// actual memory pages are committed on demand.
+//
+// If an application creates and destroys a lot of threads, usually the
+// stack space freed by a thread will soon get reused by new thread
+// (this is especially true in NPTL or BsdThreads in fixed-stack mode).
+// No memory page in _sp_map is wasted.
+//
+// However, it's still possible that we might end up populating &
+// committing a large fraction of the 4M table over time, but the actual
+// amount of live data in the table could be quite small. The max wastage
+// is less than 4M bytes. If it becomes an issue, we could use madvise()
+// with MADV_DONTNEED to reclaim unused (i.e. all-zero) pages in _sp_map.
+// MADV_DONTNEED on Bsd keeps the virtual memory mapping, but zaps the
+// physical memory page (i.e. similar to MADV_FREE on Solaris).
+
+#ifndef AMD64
+Thread* ThreadLocalStorage::_sp_map[1UL << (SP_BITLENGTH - PAGE_SHIFT)];
+#endif // !AMD64
+
+void ThreadLocalStorage::generate_code_for_get_thread() {
+ // nothing we can do here for user-level thread
+}
+
+void ThreadLocalStorage::pd_init() {
+#ifndef AMD64
+ assert(align_size_down(os::vm_page_size(), PAGE_SIZE) == os::vm_page_size(),
+ "page size must be multiple of PAGE_SIZE");
+#endif // !AMD64
+}
+
+void ThreadLocalStorage::pd_set_thread(Thread* thread) {
+ os::thread_local_storage_at_put(ThreadLocalStorage::thread_index(), thread);
+
+#ifndef AMD64
+ address stack_top = os::current_stack_base();
+ size_t stack_size = os::current_stack_size();
+
+ for (address p = stack_top - stack_size; p < stack_top; p += PAGE_SIZE) {
+ // pd_set_thread() is called with non-NULL value when a new thread is
+ // created/attached, or with NULL value when a thread is about to exit.
+ // If both "thread" and the corresponding _sp_map[] entry are non-NULL,
+ // they should have the same value. Otherwise it might indicate that the
+ // stack page is shared by multiple threads. However, a more likely cause
+ // for this assertion to fail is that an attached thread exited without
+ // detaching itself from VM, which is a program error and could cause VM
+ // to crash.
+ assert(thread == NULL || _sp_map[(uintptr_t)p >> PAGE_SHIFT] == NULL ||
+ thread == _sp_map[(uintptr_t)p >> PAGE_SHIFT],
+ "thread exited without detaching from VM??");
+ _sp_map[(uintptr_t)p >> PAGE_SHIFT] = thread;
+ }
+#endif // !AMD64
+}
diff --git a/src/os_cpu/bsd_x86/vm/threadLS_bsd_x86.hpp b/src/os_cpu/bsd_x86/vm/threadLS_bsd_x86.hpp
new file mode 100644
index 000000000..7fedb95f6
--- /dev/null
+++ b/src/os_cpu/bsd_x86/vm/threadLS_bsd_x86.hpp
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ *
+ * 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 OS_CPU_BSD_X86_VM_THREADLS_BSD_X86_HPP
+#define OS_CPU_BSD_X86_VM_THREADLS_BSD_X86_HPP
+
+ // Processor dependent parts of ThreadLocalStorage
+
+#ifndef AMD64
+ // map stack pointer to thread pointer - see notes in threadLS_bsd_x86.cpp
+ #define SP_BITLENGTH 32
+#ifndef PAGE_SHIFT
+ #define PAGE_SHIFT 12
+ #define PAGE_SIZE (1UL << PAGE_SHIFT)
+#endif
+ static Thread* _sp_map[1UL << (SP_BITLENGTH - PAGE_SHIFT)];
+#endif // !AMD64
+
+public:
+
+#ifndef AMD64
+ static Thread** sp_map_addr() { return _sp_map; }
+#endif // !AMD64
+
+ static Thread* thread() {
+#ifdef AMD64
+ return (Thread*) os::thread_local_storage_at(thread_index());
+#else
+ uintptr_t sp;
+ __asm__ volatile ("movl %%esp, %0" : "=r" (sp));
+ return _sp_map[sp >> PAGE_SHIFT];
+#endif // AMD64
+ }
+
+#endif // OS_CPU_BSD_X86_VM_THREADLS_BSD_X86_HPP
diff --git a/src/os_cpu/bsd_x86/vm/thread_bsd_x86.cpp b/src/os_cpu/bsd_x86/vm/thread_bsd_x86.cpp
new file mode 100644
index 000000000..e63c46e97
--- /dev/null
+++ b/src/os_cpu/bsd_x86/vm/thread_bsd_x86.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "runtime/frame.inline.hpp"
+#include "thread_bsd.inline.hpp"
+
+// For Forte Analyzer AsyncGetCallTrace profiling support - thread is
+// currently interrupted by SIGPROF
+bool JavaThread::pd_get_top_frame_for_signal_handler(frame* fr_addr,
+ void* ucontext, bool isInJava) {
+
+ assert(Thread::current() == this, "caller must be current thread");
+ assert(this->is_Java_thread(), "must be JavaThread");
+
+ JavaThread* jt = (JavaThread *)this;
+
+ // If we have a last_Java_frame, then we should use it even if
+ // isInJava == true. It should be more reliable than ucontext info.
+ if (jt->has_last_Java_frame()) {
+ *fr_addr = jt->pd_last_frame();
+ return true;
+ }
+
+ // At this point, we don't have a last_Java_frame, so
+ // we try to glean some information out of the ucontext
+ // if we were running Java code when SIGPROF came in.
+ if (isInJava) {
+ ucontext_t* uc = (ucontext_t*) ucontext;
+
+ intptr_t* ret_fp;
+ intptr_t* ret_sp;
+ ExtendedPC addr = os::Bsd::fetch_frame_from_ucontext(this, uc,
+ &ret_sp, &ret_fp);
+ if (addr.pc() == NULL || ret_sp == NULL ) {
+ // ucontext wasn't useful
+ return false;
+ }
+
+ frame ret_frame(ret_sp, ret_fp, addr.pc());
+ if (!ret_frame.safe_for_sender(jt)) {
+#ifdef COMPILER2
+ // C2 uses ebp as a general register see if NULL fp helps
+ frame ret_frame2(ret_sp, NULL, addr.pc());
+ if (!ret_frame2.safe_for_sender(jt)) {
+ // nothing else to try if the frame isn't good
+ return false;
+ }
+ ret_frame = ret_frame2;
+#else
+ // nothing else to try if the frame isn't good
+ return false;
+#endif /* COMPILER2 */
+ }
+ *fr_addr = ret_frame;
+ return true;
+ }
+
+ // nothing else to try
+ return false;
+}
+
+void JavaThread::cache_global_variables() { }
diff --git a/src/os_cpu/bsd_x86/vm/thread_bsd_x86.hpp b/src/os_cpu/bsd_x86/vm/thread_bsd_x86.hpp
new file mode 100644
index 000000000..69dba9b3a
--- /dev/null
+++ b/src/os_cpu/bsd_x86/vm/thread_bsd_x86.hpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef OS_CPU_BSD_X86_VM_THREAD_BSD_X86_HPP
+#define OS_CPU_BSD_X86_VM_THREAD_BSD_X86_HPP
+
+ private:
+ void pd_initialize() {
+ _anchor.clear();
+ }
+
+ frame pd_last_frame() {
+ assert(has_last_Java_frame(), "must have last_Java_sp() when suspended");
+ if (_anchor.last_Java_pc() != NULL) {
+ return frame(_anchor.last_Java_sp(), _anchor.last_Java_fp(), _anchor.last_Java_pc());
+ } else {
+ // This will pick up pc from sp
+ return frame(_anchor.last_Java_sp(), _anchor.last_Java_fp());
+ }
+ }
+
+ public:
+ // Mutators are highly dangerous....
+ intptr_t* last_Java_fp() { return _anchor.last_Java_fp(); }
+ void set_last_Java_fp(intptr_t* fp) { _anchor.set_last_Java_fp(fp); }
+
+ void set_base_of_stack_pointer(intptr_t* base_sp) {
+ }
+
+ static ByteSize last_Java_fp_offset() {
+ return byte_offset_of(JavaThread, _anchor) + JavaFrameAnchor::last_Java_fp_offset();
+ }
+
+ intptr_t* base_of_stack_pointer() {
+ return NULL;
+ }
+ void record_base_of_stack_pointer() {
+ }
+
+ bool pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext,
+ bool isInJava);
+
+ // These routines are only used on cpu architectures that
+ // have separate register stacks (Itanium).
+ static bool register_stack_overflow() { return false; }
+ static void enable_register_stack_guard() {}
+ static void disable_register_stack_guard() {}
+
+#endif // OS_CPU_BSD_X86_VM_THREAD_BSD_X86_HPP
diff --git a/src/os_cpu/bsd_x86/vm/vmStructs_bsd_x86.hpp b/src/os_cpu/bsd_x86/vm/vmStructs_bsd_x86.hpp
new file mode 100644
index 000000000..210d5d97b
--- /dev/null
+++ b/src/os_cpu/bsd_x86/vm/vmStructs_bsd_x86.hpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef OS_CPU_BSD_X86_VM_VMSTRUCTS_BSD_X86_HPP
+#define OS_CPU_BSD_X86_VM_VMSTRUCTS_BSD_X86_HPP
+
+// These are the OS and CPU-specific fields, types and integer
+// constants required by the Serviceability Agent. This file is
+// referenced by vmStructs.cpp.
+
+#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field, last_entry) \
+ \
+ /******************************/ \
+ /* Threads (NOTE: incomplete) */ \
+ /******************************/ \
+ nonstatic_field(OSThread, _thread_id, pthread_t) \
+ nonstatic_field(OSThread, _pthread_id, pthread_t) \
+ /* This must be the last entry, and must be present */ \
+ last_entry()
+
+
+#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type, last_entry) \
+ \
+ /**********************/ \
+ /* Posix Thread IDs */ \
+ /**********************/ \
+ \
+ declare_integer_type(pid_t) \
+ declare_unsigned_integer_type(pthread_t) \
+ \
+ /* This must be the last entry, and must be present */ \
+ last_entry()
+
+#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \
+ \
+ /* This must be the last entry, and must be present */ \
+ last_entry()
+
+#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \
+ \
+ /* This must be the last entry, and must be present */ \
+ last_entry()
+
+#endif // OS_CPU_BSD_X86_VM_VMSTRUCTS_BSD_X86_HPP
diff --git a/src/os_cpu/bsd_x86/vm/vm_version_bsd_x86.cpp b/src/os_cpu/bsd_x86/vm/vm_version_bsd_x86.cpp
new file mode 100644
index 000000000..d1c8c6be5
--- /dev/null
+++ b/src/os_cpu/bsd_x86/vm/vm_version_bsd_x86.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "runtime/os.hpp"
+#include "vm_version_x86.hpp"
diff --git a/src/os_cpu/bsd_zero/vm/assembler_bsd_zero.cpp b/src/os_cpu/bsd_zero/vm/assembler_bsd_zero.cpp
new file mode 100644
index 000000000..ec56a35cd
--- /dev/null
+++ b/src/os_cpu/bsd_zero/vm/assembler_bsd_zero.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "asm/assembler.hpp"
+#include "assembler_zero.inline.hpp"
+#include "runtime/os.hpp"
+#include "runtime/threadLocalStorage.hpp"
+
+// This file is intentionally empty
diff --git a/src/os_cpu/bsd_zero/vm/atomic_bsd_zero.inline.hpp b/src/os_cpu/bsd_zero/vm/atomic_bsd_zero.inline.hpp
new file mode 100644
index 000000000..19027bd15
--- /dev/null
+++ b/src/os_cpu/bsd_zero/vm/atomic_bsd_zero.inline.hpp
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2007, 2008, 2011 Red Hat, Inc.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef OS_CPU_BSD_ZERO_VM_ATOMIC_BSD_ZERO_INLINE_HPP
+#define OS_CPU_BSD_ZERO_VM_ATOMIC_BSD_ZERO_INLINE_HPP
+
+#include "orderAccess_bsd_zero.inline.hpp"
+#include "runtime/atomic.hpp"
+#include "runtime/os.hpp"
+#include "vm_version_zero.hpp"
+
+// Implementation of class atomic
+
+#ifdef M68K
+
+/*
+ * __m68k_cmpxchg
+ *
+ * Atomically store newval in *ptr if *ptr is equal to oldval for user space.
+ * Returns newval on success and oldval if no exchange happened.
+ * This implementation is processor specific and works on
+ * 68020 68030 68040 and 68060.
+ *
+ * It will not work on ColdFire, 68000 and 68010 since they lack the CAS
+ * instruction.
+ * Using a kernelhelper would be better for arch complete implementation.
+ *
+ */
+
+static inline int __m68k_cmpxchg(int oldval, int newval, volatile int *ptr) {
+ int ret;
+ __asm __volatile ("cas%.l %0,%2,%1"
+ : "=d" (ret), "+m" (*(ptr))
+ : "d" (newval), "0" (oldval));
+ return ret;
+}
+
+/* Perform an atomic compare and swap: if the current value of `*PTR'
+ is OLDVAL, then write NEWVAL into `*PTR'. Return the contents of
+ `*PTR' before the operation.*/
+static inline int m68k_compare_and_swap(volatile int *ptr,
+ int oldval,
+ int newval) {
+ for (;;) {
+ int prev = *ptr;
+ if (prev != oldval)
+ return prev;
+
+ if (__m68k_cmpxchg (prev, newval, ptr) == newval)
+ // Success.
+ return prev;
+
+ // We failed even though prev == oldval. Try again.
+ }
+}
+
+/* Atomically add an int to memory. */
+static inline int m68k_add_and_fetch(volatile int *ptr, int add_value) {
+ for (;;) {
+ // Loop until success.
+
+ int prev = *ptr;
+
+ if (__m68k_cmpxchg (prev, prev + add_value, ptr) == prev + add_value)
+ return prev + add_value;
+ }
+}
+
+/* Atomically write VALUE into `*PTR' and returns the previous
+ contents of `*PTR'. */
+static inline int m68k_lock_test_and_set(volatile int *ptr, int newval) {
+ for (;;) {
+ // Loop until success.
+ int prev = *ptr;
+
+ if (__m68k_cmpxchg (prev, newval, ptr) == prev)
+ return prev;
+ }
+}
+#endif // M68K
+
+#ifdef ARM
+
+/*
+ * __kernel_cmpxchg
+ *
+ * Atomically store newval in *ptr if *ptr is equal to oldval for user space.
+ * Return zero if *ptr was changed or non-zero if no exchange happened.
+ * The C flag is also set if *ptr was changed to allow for assembly
+ * optimization in the calling code.
+ *
+ */
+
+typedef int (__kernel_cmpxchg_t)(int oldval, int newval, volatile int *ptr);
+#define __kernel_cmpxchg (*(__kernel_cmpxchg_t *) 0xffff0fc0)
+
+
+
+/* Perform an atomic compare and swap: if the current value of `*PTR'
+ is OLDVAL, then write NEWVAL into `*PTR'. Return the contents of
+ `*PTR' before the operation.*/
+static inline int arm_compare_and_swap(volatile int *ptr,
+ int oldval,
+ int newval) {
+ for (;;) {
+ int prev = *ptr;
+ if (prev != oldval)
+ return prev;
+
+ if (__kernel_cmpxchg (prev, newval, ptr) == 0)
+ // Success.
+ return prev;
+
+ // We failed even though prev == oldval. Try again.
+ }
+}
+
+/* Atomically add an int to memory. */
+static inline int arm_add_and_fetch(volatile int *ptr, int add_value) {
+ for (;;) {
+ // Loop until a __kernel_cmpxchg succeeds.
+
+ int prev = *ptr;
+
+ if (__kernel_cmpxchg (prev, prev + add_value, ptr) == 0)
+ return prev + add_value;
+ }
+}
+
+/* Atomically write VALUE into `*PTR' and returns the previous
+ contents of `*PTR'. */
+static inline int arm_lock_test_and_set(volatile int *ptr, int newval) {
+ for (;;) {
+ // Loop until a __kernel_cmpxchg succeeds.
+ int prev = *ptr;
+
+ if (__kernel_cmpxchg (prev, newval, ptr) == 0)
+ return prev;
+ }
+}
+#endif // ARM
+
+inline void Atomic::store(jint store_value, volatile jint* dest) {
+#if !defined(ARM) && !defined(M68K)
+ __sync_synchronize();
+#endif
+ *dest = store_value;
+}
+
+inline void Atomic::store_ptr(intptr_t store_value, intptr_t* dest) {
+#if !defined(ARM) && !defined(M68K)
+ __sync_synchronize();
+#endif
+ *dest = store_value;
+}
+
+inline jint Atomic::add(jint add_value, volatile jint* dest) {
+#ifdef ARM
+ return arm_add_and_fetch(dest, add_value);
+#else
+#ifdef M68K
+ return m68k_add_and_fetch(dest, add_value);
+#else
+ return __sync_add_and_fetch(dest, add_value);
+#endif // M68K
+#endif // ARM
+}
+
+inline intptr_t Atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest) {
+#ifdef ARM
+ return arm_add_and_fetch(dest, add_value);
+#else
+#ifdef M68K
+ return m68k_add_and_fetch(dest, add_value);
+#else
+ return __sync_add_and_fetch(dest, add_value);
+#endif // M68K
+#endif // ARM
+}
+
+inline void* Atomic::add_ptr(intptr_t add_value, volatile void* dest) {
+ return (void *) add_ptr(add_value, (volatile intptr_t *) dest);
+}
+
+inline void Atomic::inc(volatile jint* dest) {
+ add(1, dest);
+}
+
+inline void Atomic::inc_ptr(volatile intptr_t* dest) {
+ add_ptr(1, dest);
+}
+
+inline void Atomic::inc_ptr(volatile void* dest) {
+ add_ptr(1, dest);
+}
+
+inline void Atomic::dec(volatile jint* dest) {
+ add(-1, dest);
+}
+
+inline void Atomic::dec_ptr(volatile intptr_t* dest) {
+ add_ptr(-1, dest);
+}
+
+inline void Atomic::dec_ptr(volatile void* dest) {
+ add_ptr(-1, dest);
+}
+
+inline jint Atomic::xchg(jint exchange_value, volatile jint* dest) {
+#ifdef ARM
+ return arm_lock_test_and_set(dest, exchange_value);
+#else
+#ifdef M68K
+ return m68k_lock_test_and_set(dest, exchange_value);
+#else
+ // __sync_lock_test_and_set is a bizarrely named atomic exchange
+ // operation. Note that some platforms only support this with the
+ // limitation that the only valid value to store is the immediate
+ // constant 1. There is a test for this in JNI_CreateJavaVM().
+ return __sync_lock_test_and_set (dest, exchange_value);
+#endif // M68K
+#endif // ARM
+}
+
+inline intptr_t Atomic::xchg_ptr(intptr_t exchange_value,
+ volatile intptr_t* dest) {
+#ifdef ARM
+ return arm_lock_test_and_set(dest, exchange_value);
+#else
+#ifdef M68K
+ return m68k_lock_test_and_set(dest, exchange_value);
+#else
+ return __sync_lock_test_and_set (dest, exchange_value);
+#endif // M68K
+#endif // ARM
+}
+
+inline void* Atomic::xchg_ptr(void* exchange_value, volatile void* dest) {
+ return (void *) xchg_ptr((intptr_t) exchange_value,
+ (volatile intptr_t*) dest);
+}
+
+inline jint Atomic::cmpxchg(jint exchange_value,
+ volatile jint* dest,
+ jint compare_value) {
+#ifdef ARM
+ return arm_compare_and_swap(dest, compare_value, exchange_value);
+#else
+#ifdef M68K
+ return m68k_compare_and_swap(dest, compare_value, exchange_value);
+#else
+ return __sync_val_compare_and_swap(dest, compare_value, exchange_value);
+#endif // M68K
+#endif // ARM
+}
+
+inline jlong Atomic::cmpxchg(jlong exchange_value,
+ volatile jlong* dest,
+ jlong compare_value) {
+
+ return __sync_val_compare_and_swap(dest, compare_value, exchange_value);
+}
+
+inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value,
+ volatile intptr_t* dest,
+ intptr_t compare_value) {
+#ifdef ARM
+ return arm_compare_and_swap(dest, compare_value, exchange_value);
+#else
+#ifdef M68K
+ return m68k_compare_and_swap(dest, compare_value, exchange_value);
+#else
+ return __sync_val_compare_and_swap(dest, compare_value, exchange_value);
+#endif // M68K
+#endif // ARM
+}
+
+inline void* Atomic::cmpxchg_ptr(void* exchange_value,
+ volatile void* dest,
+ void* compare_value) {
+
+ return (void *) cmpxchg_ptr((intptr_t) exchange_value,
+ (volatile intptr_t*) dest,
+ (intptr_t) compare_value);
+}
+
+inline jlong Atomic::load(volatile jlong* src) {
+ volatile jlong dest;
+ os::atomic_copy64(src, &dest);
+ return dest;
+}
+
+inline void Atomic::store(jlong store_value, jlong* dest) {
+ os::atomic_copy64((volatile jlong*)&store_value, (volatile jlong*)dest);
+}
+
+inline void Atomic::store(jlong store_value, volatile jlong* dest) {
+ os::atomic_copy64((volatile jlong*)&store_value, dest);
+}
+
+#endif // OS_CPU_BSD_ZERO_VM_ATOMIC_BSD_ZERO_INLINE_HPP
diff --git a/src/os_cpu/bsd_zero/vm/bytes_bsd_zero.inline.hpp b/src/os_cpu/bsd_zero/vm/bytes_bsd_zero.inline.hpp
new file mode 100644
index 000000000..b8217b494
--- /dev/null
+++ b/src/os_cpu/bsd_zero/vm/bytes_bsd_zero.inline.hpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef OS_CPU_BSD_ZERO_VM_BYTES_BSD_ZERO_INLINE_HPP
+#define OS_CPU_BSD_ZERO_VM_BYTES_BSD_ZERO_INLINE_HPP
+
+// Efficient swapping of data bytes from Java byte
+// ordering to native byte ordering and vice versa.
+
+#ifdef __APPLE__
+#include <libkern/OSByteOrder.h>
+#else
+# include <sys/endian.h>
+#endif
+
+#if defined(__APPLE__)
+# define bswap_16(x) OSSwapInt16(x)
+# define bswap_32(x) OSSwapInt32(x)
+# define bswap_64(x) OSSwapInt64(x)
+#elif defined(__OpenBSD__)
+# define bswap_16(x) swap16(x)
+# define bswap_32(x) swap32(x)
+# define bswap_64(x) swap64(x)
+#elif defined(__NetBSD__)
+# define bswap_16(x) bswap16(x)
+# define bswap_32(x) bswap32(x)
+# define bswap_64(x) bswap64(x)
+#else
+# define bswap_16(x) __bswap16(x)
+# define bswap_32(x) __bswap32(x)
+# define bswap_64(x) __bswap64(x)
+#endif
+
+inline u2 Bytes::swap_u2(u2 x) {
+ return bswap_16(x);
+}
+
+inline u4 Bytes::swap_u4(u4 x) {
+ return bswap_32(x);
+}
+
+inline u8 Bytes::swap_u8(u8 x) {
+ return bswap_64(x);
+}
+
+#endif // OS_CPU_BSD_ZERO_VM_BYTES_BSD_ZERO_INLINE_HPP
diff --git a/src/os_cpu/bsd_zero/vm/globals_bsd_zero.hpp b/src/os_cpu/bsd_zero/vm/globals_bsd_zero.hpp
new file mode 100644
index 000000000..57e27597b
--- /dev/null
+++ b/src/os_cpu/bsd_zero/vm/globals_bsd_zero.hpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2007, 2008, 2010 Red Hat, Inc.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef OS_CPU_BSD_ZERO_VM_GLOBALS_BSD_ZERO_HPP
+#define OS_CPU_BSD_ZERO_VM_GLOBALS_BSD_ZERO_HPP
+
+//
+// Set the default values for platform dependent flags used by the
+// runtime system. See globals.hpp for details of what they do.
+//
+
+define_pd_global(bool, DontYieldALot, false);
+define_pd_global(intx, ThreadStackSize, 1536);
+#ifdef _LP64
+define_pd_global(intx, VMThreadStackSize, 1024);
+#else
+define_pd_global(intx, VMThreadStackSize, 512);
+#endif // _LP64
+define_pd_global(intx, CompilerThreadStackSize, 0);
+define_pd_global(uintx, JVMInvokeMethodSlack, 8192);
+
+define_pd_global(bool, UseVectoredExceptions, false);
+// Only used on 64 bit platforms
+define_pd_global(uintx, HeapBaseMinAddress, 2*G);
+
+#endif // OS_CPU_BSD_ZERO_VM_GLOBALS_BSD_ZERO_HPP
diff --git a/src/os_cpu/bsd_zero/vm/orderAccess_bsd_zero.inline.hpp b/src/os_cpu/bsd_zero/vm/orderAccess_bsd_zero.inline.hpp
new file mode 100644
index 000000000..7f8e78bbf
--- /dev/null
+++ b/src/os_cpu/bsd_zero/vm/orderAccess_bsd_zero.inline.hpp
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2007, 2008, 2009 Red Hat, Inc.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef OS_CPU_BSD_ZERO_VM_ORDERACCESS_BSD_ZERO_INLINE_HPP
+#define OS_CPU_BSD_ZERO_VM_ORDERACCESS_BSD_ZERO_INLINE_HPP
+
+#include "runtime/orderAccess.hpp"
+#include "vm_version_zero.hpp"
+
+#ifdef ARM
+
+/*
+ * ARM Kernel helper for memory barrier.
+ * Using __asm __volatile ("":::"memory") does not work reliable on ARM
+ * and gcc __sync_synchronize(); implementation does not use the kernel
+ * helper for all gcc versions so it is unreliable to use as well.
+ */
+typedef void (__kernel_dmb_t) (void);
+#define __kernel_dmb (*(__kernel_dmb_t *) 0xffff0fa0)
+
+#define FULL_MEM_BARRIER __kernel_dmb()
+#define READ_MEM_BARRIER __kernel_dmb()
+#define WRITE_MEM_BARRIER __kernel_dmb()
+
+#else // ARM
+
+#define FULL_MEM_BARRIER __sync_synchronize()
+
+#ifdef PPC
+
+#ifdef __NO_LWSYNC__
+#define READ_MEM_BARRIER __asm __volatile ("sync":::"memory")
+#define WRITE_MEM_BARRIER __asm __volatile ("sync":::"memory")
+#else
+#define READ_MEM_BARRIER __asm __volatile ("lwsync":::"memory")
+#define WRITE_MEM_BARRIER __asm __volatile ("lwsync":::"memory")
+#endif
+
+#else // PPC
+
+#define READ_MEM_BARRIER __asm __volatile ("":::"memory")
+#define WRITE_MEM_BARRIER __asm __volatile ("":::"memory")
+
+#endif // PPC
+
+#endif // ARM
+
+
+inline void OrderAccess::loadload() { acquire(); }
+inline void OrderAccess::storestore() { release(); }
+inline void OrderAccess::loadstore() { acquire(); }
+inline void OrderAccess::storeload() { fence(); }
+
+inline void OrderAccess::acquire() {
+ READ_MEM_BARRIER;
+}
+
+inline void OrderAccess::release() {
+ WRITE_MEM_BARRIER;
+}
+
+inline void OrderAccess::fence() {
+ FULL_MEM_BARRIER;
+}
+
+inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { jbyte data = *p; acquire(); return data; }
+inline jshort OrderAccess::load_acquire(volatile jshort* p) { jshort data = *p; acquire(); return data; }
+inline jint OrderAccess::load_acquire(volatile jint* p) { jint data = *p; acquire(); return data; }
+inline jlong OrderAccess::load_acquire(volatile jlong* p) {
+ jlong tmp;
+ os::atomic_copy64(p, &tmp);
+ acquire();
+ return tmp;
+}
+inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { jubyte data = *p; acquire(); return data; }
+inline jushort OrderAccess::load_acquire(volatile jushort* p) { jushort data = *p; acquire(); return data; }
+inline juint OrderAccess::load_acquire(volatile juint* p) { juint data = *p; acquire(); return data; }
+inline julong OrderAccess::load_acquire(volatile julong* p) {
+ julong tmp;
+ os::atomic_copy64(p, &tmp);
+ acquire();
+ return tmp;
+}
+inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { jfloat data = *p; acquire(); return data; }
+inline jdouble OrderAccess::load_acquire(volatile jdouble* p) {
+ jdouble tmp;
+ os::atomic_copy64(p, &tmp);
+ acquire();
+ return tmp;
+}
+
+inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t* p) {
+ intptr_t data = *p;
+ acquire();
+ return data;
+}
+inline void* OrderAccess::load_ptr_acquire(volatile void* p) {
+ void *data = *(void* volatile *)p;
+ acquire();
+ return data;
+}
+inline void* OrderAccess::load_ptr_acquire(const volatile void* p) {
+ void *data = *(void* const volatile *)p;
+ acquire();
+ return data;
+}
+
+inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { release(); *p = v; }
+inline void OrderAccess::release_store(volatile jshort* p, jshort v) { release(); *p = v; }
+inline void OrderAccess::release_store(volatile jint* p, jint v) { release(); *p = v; }
+inline void OrderAccess::release_store(volatile jlong* p, jlong v)
+{ release(); os::atomic_copy64(&v, p); }
+inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { release(); *p = v; }
+inline void OrderAccess::release_store(volatile jushort* p, jushort v) { release(); *p = v; }
+inline void OrderAccess::release_store(volatile juint* p, juint v) { release(); *p = v; }
+inline void OrderAccess::release_store(volatile julong* p, julong v)
+{ release(); os::atomic_copy64(&v, p); }
+inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { release(); *p = v; }
+inline void OrderAccess::release_store(volatile jdouble* p, jdouble v)
+{ release(); os::atomic_copy64(&v, p); }
+
+inline void OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { release(); *p = v; }
+inline void OrderAccess::release_store_ptr(volatile void* p, void* v)
+{ release(); *(void* volatile *)p = v; }
+
+inline void OrderAccess::store_fence(jbyte* p, jbyte v) { *p = v; fence(); }
+inline void OrderAccess::store_fence(jshort* p, jshort v) { *p = v; fence(); }
+inline void OrderAccess::store_fence(jint* p, jint v) { *p = v; fence(); }
+inline void OrderAccess::store_fence(jlong* p, jlong v) { os::atomic_copy64(&v, p); fence(); }
+inline void OrderAccess::store_fence(jubyte* p, jubyte v) { *p = v; fence(); }
+inline void OrderAccess::store_fence(jushort* p, jushort v) { *p = v; fence(); }
+inline void OrderAccess::store_fence(juint* p, juint v) { *p = v; fence(); }
+inline void OrderAccess::store_fence(julong* p, julong v) { os::atomic_copy64(&v, p); fence(); }
+inline void OrderAccess::store_fence(jfloat* p, jfloat v) { *p = v; fence(); }
+inline void OrderAccess::store_fence(jdouble* p, jdouble v) { os::atomic_copy64(&v, p); fence(); }
+
+inline void OrderAccess::store_ptr_fence(intptr_t* p, intptr_t v) { *p = v; fence(); }
+inline void OrderAccess::store_ptr_fence(void** p, void* v) { *p = v; fence(); }
+
+inline void OrderAccess::release_store_fence(volatile jbyte* p, jbyte v) { release_store(p, v); fence(); }
+inline void OrderAccess::release_store_fence(volatile jshort* p, jshort v) { release_store(p, v); fence(); }
+inline void OrderAccess::release_store_fence(volatile jint* p, jint v) { release_store(p, v); fence(); }
+inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { release_store(p, v); fence(); }
+inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { release_store(p, v); fence(); }
+inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { release_store(p, v); fence(); }
+inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { release_store(p, v); fence(); }
+inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { release_store(p, v); fence(); }
+inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { release_store(p, v); fence(); }
+inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { release_store(p, v); fence(); }
+
+inline void OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) { release_store_ptr(p, v); fence(); }
+inline void OrderAccess::release_store_ptr_fence(volatile void* p, void* v) { release_store_ptr(p, v); fence(); }
+
+#endif // OS_CPU_BSD_ZERO_VM_ORDERACCESS_BSD_ZERO_INLINE_HPP
diff --git a/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp b/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp
new file mode 100644
index 000000000..675ee54b8
--- /dev/null
+++ b/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp
@@ -0,0 +1,558 @@
+/*
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2007, 2008, 2009, 2010 Red Hat, Inc.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#if defined(_ALLBSD_SOURCE) && !defined(__APPLE__) && !defined(__NetBSD__)
+#include <pthread.h>
+# include <pthread_np.h> /* For pthread_attr_get_np */
+#endif
+
+// no precompiled headers
+#include "assembler_zero.inline.hpp"
+#include "classfile/classLoader.hpp"
+#include "classfile/systemDictionary.hpp"
+#include "classfile/vmSymbols.hpp"
+#include "code/icBuffer.hpp"
+#include "code/vtableStubs.hpp"
+#include "interpreter/interpreter.hpp"
+#include "jvm_bsd.h"
+#include "memory/allocation.inline.hpp"
+#include "mutex_bsd.inline.hpp"
+#include "nativeInst_zero.hpp"
+#include "os_share_bsd.hpp"
+#include "prims/jniFastGetField.hpp"
+#include "prims/jvm.h"
+#include "prims/jvm_misc.hpp"
+#include "runtime/arguments.hpp"
+#include "runtime/extendedPC.hpp"
+#include "runtime/frame.inline.hpp"
+#include "runtime/interfaceSupport.hpp"
+#include "runtime/java.hpp"
+#include "runtime/javaCalls.hpp"
+#include "runtime/mutexLocker.hpp"
+#include "runtime/osThread.hpp"
+#include "runtime/sharedRuntime.hpp"
+#include "runtime/stubRoutines.hpp"
+#include "runtime/timer.hpp"
+#include "thread_bsd.inline.hpp"
+#include "utilities/events.hpp"
+#include "utilities/vmError.hpp"
+#ifdef COMPILER1
+#include "c1/c1_Runtime1.hpp"
+#endif
+#ifdef COMPILER2
+#include "opto/runtime.hpp"
+#endif
+
+address os::current_stack_pointer() {
+ address dummy = (address) &dummy;
+ return dummy;
+}
+
+frame os::get_sender_for_C_frame(frame* fr) {
+ ShouldNotCallThis();
+}
+
+frame os::current_frame() {
+ // The only thing that calls this is the stack printing code in
+ // VMError::report:
+ // - Step 110 (printing stack bounds) uses the sp in the frame
+ // to determine the amount of free space on the stack. We
+ // set the sp to a close approximation of the real value in
+ // order to allow this step to complete.
+ // - Step 120 (printing native stack) tries to walk the stack.
+ // The frame we create has a NULL pc, which is ignored as an
+ // invalid frame.
+ frame dummy = frame();
+ dummy.set_sp((intptr_t *) current_stack_pointer());
+ return dummy;
+}
+
+char* os::non_memory_address_word() {
+ // Must never look like an address returned by reserve_memory,
+ // even in its subfields (as defined by the CPU immediate fields,
+ // if the CPU splits constants across multiple instructions).
+#ifdef SPARC
+ // On SPARC, 0 != %hi(any real address), because there is no
+ // allocation in the first 1Kb of the virtual address space.
+ return (char *) 0;
+#else
+ // This is the value for x86; works pretty well for PPC too.
+ return (char *) -1;
+#endif // SPARC
+}
+
+void os::initialize_thread() {
+ // Nothing to do.
+}
+
+address os::Bsd::ucontext_get_pc(ucontext_t* uc) {
+ ShouldNotCallThis();
+}
+
+ExtendedPC os::fetch_frame_from_context(void* ucVoid,
+ intptr_t** ret_sp,
+ intptr_t** ret_fp) {
+ ShouldNotCallThis();
+}
+
+frame os::fetch_frame_from_context(void* ucVoid) {
+ ShouldNotCallThis();
+}
+
+extern "C" JNIEXPORT int
+JVM_handle_bsd_signal(int sig,
+ siginfo_t* info,
+ void* ucVoid,
+ int abort_if_unrecognized) {
+ ucontext_t* uc = (ucontext_t*) ucVoid;
+
+ Thread* t = ThreadLocalStorage::get_thread_slow();
+
+ SignalHandlerMark shm(t);
+
+ // Note: it's not uncommon that JNI code uses signal/sigset to
+ // install then restore certain signal handler (e.g. to temporarily
+ // block SIGPIPE, or have a SIGILL handler when detecting CPU
+ // type). When that happens, JVM_handle_bsd_signal() might be
+ // invoked with junk info/ucVoid. To avoid unnecessary crash when
+ // libjsig is not preloaded, try handle signals that do not require
+ // siginfo/ucontext first.
+
+ if (sig == SIGPIPE || sig == SIGXFSZ) {
+ // allow chained handler to go first
+ if (os::Bsd::chained_handler(sig, info, ucVoid)) {
+ return true;
+ } else {
+ if (PrintMiscellaneous && (WizardMode || Verbose)) {
+ char buf[64];
+ warning("Ignoring %s - see bugs 4229104 or 646499219",
+ os::exception_name(sig, buf, sizeof(buf)));
+ }
+ return true;
+ }
+ }
+
+ JavaThread* thread = NULL;
+ VMThread* vmthread = NULL;
+ if (os::Bsd::signal_handlers_are_installed) {
+ if (t != NULL ){
+ if(t->is_Java_thread()) {
+ thread = (JavaThread*)t;
+ }
+ else if(t->is_VM_thread()){
+ vmthread = (VMThread *)t;
+ }
+ }
+ }
+
+ if (info != NULL && thread != NULL) {
+ // Handle ALL stack overflow variations here
+ if (sig == SIGSEGV) {
+ address addr = (address) info->si_addr;
+
+ // check if fault address is within thread stack
+ if (addr < thread->stack_base() &&
+ addr >= thread->stack_base() - thread->stack_size()) {
+ // stack overflow
+ if (thread->in_stack_yellow_zone(addr)) {
+ thread->disable_stack_yellow_zone();
+ ShouldNotCallThis();
+ }
+ else if (thread->in_stack_red_zone(addr)) {
+ thread->disable_stack_red_zone();
+ ShouldNotCallThis();
+ }
+#ifndef _ALLBSD_SOURCE
+ else {
+ // Accessing stack address below sp may cause SEGV if
+ // current thread has MAP_GROWSDOWN stack. This should
+ // only happen when current thread was created by user
+ // code with MAP_GROWSDOWN flag and then attached to VM.
+ // See notes in os_bsd.cpp.
+ if (thread->osthread()->expanding_stack() == 0) {
+ thread->osthread()->set_expanding_stack();
+ if (os::Bsd::manually_expand_stack(thread, addr)) {
+ thread->osthread()->clear_expanding_stack();
+ return true;
+ }
+ thread->osthread()->clear_expanding_stack();
+ }
+ else {
+ fatal("recursive segv. expanding stack.");
+ }
+ }
+#endif
+ }
+ }
+
+ /*if (thread->thread_state() == _thread_in_Java) {
+ ShouldNotCallThis();
+ }
+ else*/ if (thread->thread_state() == _thread_in_vm &&
+ sig == SIGBUS && thread->doing_unsafe_access()) {
+ ShouldNotCallThis();
+ }
+
+ // jni_fast_Get<Primitive>Field can trap at certain pc's if a GC
+ // kicks in and the heap gets shrunk before the field access.
+ /*if (sig == SIGSEGV || sig == SIGBUS) {
+ address addr = JNI_FastGetField::find_slowcase_pc(pc);
+ if (addr != (address)-1) {
+ stub = addr;
+ }
+ }*/
+
+ // Check to see if we caught the safepoint code in the process
+ // of write protecting the memory serialization page. It write
+ // enables the page immediately after protecting it so we can
+ // just return to retry the write.
+ if (sig == SIGSEGV &&
+ os::is_memory_serialize_page(thread, (address) info->si_addr)) {
+ // Block current thread until permission is restored.
+ os::block_on_serialize_page_trap();
+ return true;
+ }
+ }
+
+ // signal-chaining
+ if (os::Bsd::chained_handler(sig, info, ucVoid)) {
+ return true;
+ }
+
+ if (!abort_if_unrecognized) {
+ // caller wants another chance, so give it to him
+ return false;
+ }
+
+#ifndef PRODUCT
+ if (sig == SIGSEGV) {
+ fatal("\n#"
+ "\n# /--------------------\\"
+ "\n# | segmentation fault |"
+ "\n# \\---\\ /--------------/"
+ "\n# /"
+ "\n# [-] |\\_/| "
+ "\n# (+)=C |o o|__ "
+ "\n# | | =-*-=__\\ "
+ "\n# OOO c_c_(___)");
+ }
+#endif // !PRODUCT
+
+ const char *fmt = "caught unhandled signal %d";
+ char buf[64];
+
+ sprintf(buf, fmt, sig);
+ fatal(buf);
+}
+
+void os::Bsd::init_thread_fpu_state(void) {
+ // Nothing to do
+}
+
+#ifndef _ALLBSD_SOURCE
+int os::Bsd::get_fpu_control_word() {
+ ShouldNotCallThis();
+}
+
+void os::Bsd::set_fpu_control_word(int fpu) {
+ ShouldNotCallThis();
+}
+#endif
+
+bool os::is_allocatable(size_t bytes) {
+#ifdef _LP64
+ return true;
+#else
+ if (bytes < 2 * G) {
+ return true;
+ }
+
+ char* addr = reserve_memory(bytes, NULL);
+
+ if (addr != NULL) {
+ release_memory(addr, bytes);
+ }
+
+ return addr != NULL;
+#endif // _LP64
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// thread stack
+
+size_t os::Bsd::min_stack_allowed = 64 * K;
+
+bool os::Bsd::supports_variable_stack_size() {
+ return true;
+}
+
+size_t os::Bsd::default_stack_size(os::ThreadType thr_type) {
+#ifdef _LP64
+ size_t s = (thr_type == os::compiler_thread ? 4 * M : 1 * M);
+#else
+ size_t s = (thr_type == os::compiler_thread ? 2 * M : 512 * K);
+#endif // _LP64
+ return s;
+}
+
+size_t os::Bsd::default_guard_size(os::ThreadType thr_type) {
+ // Only enable glibc guard pages for non-Java threads
+ // (Java threads have HotSpot guard pages)
+ return (thr_type == java_thread ? 0 : page_size());
+}
+
+static void current_stack_region(address *bottom, size_t *size) {
+ address stack_bottom;
+ address stack_top;
+ size_t stack_bytes;
+
+#ifdef __APPLE__
+ pthread_t self = pthread_self();
+ stack_top = (address) pthread_get_stackaddr_np(self);
+ stack_bytes = pthread_get_stacksize_np(self);
+ stack_bottom = stack_top - stack_bytes;
+#elif defined(__OpenBSD__)
+ stack_t ss;
+ int rslt = pthread_stackseg_np(pthread_self(), &ss);
+
+ if (rslt != 0)
+ fatal(err_msg("pthread_stackseg_np failed with err = %d", rslt));
+
+ stack_top = (address) ss.ss_sp;
+ stack_bytes = ss.ss_size;
+ stack_bottom = stack_top - stack_bytes;
+#elif defined(_ALLBSD_SOURCE)
+ pthread_attr_t attr;
+
+ int rslt = pthread_attr_init(&attr);
+
+ // JVM needs to know exact stack location, abort if it fails
+ if (rslt != 0)
+ fatal(err_msg("pthread_attr_init failed with err = %d", rslt));
+
+ rslt = pthread_attr_get_np(pthread_self(), &attr);
+
+ if (rslt != 0)
+ fatal(err_msg("pthread_attr_get_np failed with err = %d", rslt));
+
+ if (pthread_attr_getstackaddr(&attr, (void **) &stack_bottom) != 0 ||
+ pthread_attr_getstacksize(&attr, &stack_bytes) != 0) {
+ fatal("Can not locate current stack attributes!");
+ }
+
+ pthread_attr_destroy(&attr);
+
+ stack_top = stack_bottom + stack_bytes;
+#else /* Linux */
+ pthread_attr_t attr;
+ int res = pthread_getattr_np(pthread_self(), &attr);
+ if (res != 0) {
+ if (res == ENOMEM) {
+ vm_exit_out_of_memory(0, "pthread_getattr_np");
+ }
+ else {
+ fatal(err_msg("pthread_getattr_np failed with errno = %d", res));
+ }
+ }
+
+ res = pthread_attr_getstack(&attr, (void **) &stack_bottom, &stack_bytes);
+ if (res != 0) {
+ fatal(err_msg("pthread_attr_getstack failed with errno = %d", res));
+ }
+ stack_top = stack_bottom + stack_bytes;
+
+ // The block of memory returned by pthread_attr_getstack() includes
+ // guard pages where present. We need to trim these off.
+ size_t page_bytes = os::Bsd::page_size();
+ assert(((intptr_t) stack_bottom & (page_bytes - 1)) == 0, "unaligned stack");
+
+ size_t guard_bytes;
+ res = pthread_attr_getguardsize(&attr, &guard_bytes);
+ if (res != 0) {
+ fatal(err_msg("pthread_attr_getguardsize failed with errno = %d", res));
+ }
+ int guard_pages = align_size_up(guard_bytes, page_bytes) / page_bytes;
+ assert(guard_bytes == guard_pages * page_bytes, "unaligned guard");
+
+#ifdef IA64
+ // IA64 has two stacks sharing the same area of memory, a normal
+ // stack growing downwards and a register stack growing upwards.
+ // Guard pages, if present, are in the centre. This code splits
+ // the stack in two even without guard pages, though in theory
+ // there's nothing to stop us allocating more to the normal stack
+ // or more to the register stack if one or the other were found
+ // to grow faster.
+ int total_pages = align_size_down(stack_bytes, page_bytes) / page_bytes;
+ stack_bottom += (total_pages - guard_pages) / 2 * page_bytes;
+#endif // IA64
+
+ stack_bottom += guard_bytes;
+
+ pthread_attr_destroy(&attr);
+
+ // The initial thread has a growable stack, and the size reported
+ // by pthread_attr_getstack is the maximum size it could possibly
+ // be given what currently mapped. This can be huge, so we cap it.
+ if (os::Bsd::is_initial_thread()) {
+ stack_bytes = stack_top - stack_bottom;
+
+ if (stack_bytes > JavaThread::stack_size_at_create())
+ stack_bytes = JavaThread::stack_size_at_create();
+
+ stack_bottom = stack_top - stack_bytes;
+ }
+#endif
+
+ assert(os::current_stack_pointer() >= stack_bottom, "should do");
+ assert(os::current_stack_pointer() < stack_top, "should do");
+
+ *bottom = stack_bottom;
+ *size = stack_top - stack_bottom;
+}
+
+address os::current_stack_base() {
+ address bottom;
+ size_t size;
+ current_stack_region(&bottom, &size);
+ return bottom + size;
+}
+
+size_t os::current_stack_size() {
+ // stack size includes normal stack and HotSpot guard pages
+ address bottom;
+ size_t size;
+ current_stack_region(&bottom, &size);
+ return size;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// helper functions for fatal error handler
+
+void os::print_context(outputStream* st, void* context) {
+ ShouldNotCallThis();
+}
+
+void os::print_register_info(outputStream *st, void *context) {
+ ShouldNotCallThis();
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Stubs for things that would be in bsd_zero.s if it existed.
+// You probably want to disassemble these monkeys to check they're ok.
+
+extern "C" {
+ int SpinPause() {
+ }
+
+ int SafeFetch32(int *adr, int errValue) {
+ int value = errValue;
+ value = *adr;
+ return value;
+ }
+ intptr_t SafeFetchN(intptr_t *adr, intptr_t errValue) {
+ intptr_t value = errValue;
+ value = *adr;
+ return value;
+ }
+
+ void _Copy_conjoint_jshorts_atomic(jshort* from, jshort* to, size_t count) {
+ if (from > to) {
+ jshort *end = from + count;
+ while (from < end)
+ *(to++) = *(from++);
+ }
+ else if (from < to) {
+ jshort *end = from;
+ from += count - 1;
+ to += count - 1;
+ while (from >= end)
+ *(to--) = *(from--);
+ }
+ }
+ void _Copy_conjoint_jints_atomic(jint* from, jint* to, size_t count) {
+ if (from > to) {
+ jint *end = from + count;
+ while (from < end)
+ *(to++) = *(from++);
+ }
+ else if (from < to) {
+ jint *end = from;
+ from += count - 1;
+ to += count - 1;
+ while (from >= end)
+ *(to--) = *(from--);
+ }
+ }
+ void _Copy_conjoint_jlongs_atomic(jlong* from, jlong* to, size_t count) {
+ if (from > to) {
+ jlong *end = from + count;
+ while (from < end)
+ os::atomic_copy64(from++, to++);
+ }
+ else if (from < to) {
+ jlong *end = from;
+ from += count - 1;
+ to += count - 1;
+ while (from >= end)
+ os::atomic_copy64(from--, to--);
+ }
+ }
+
+ void _Copy_arrayof_conjoint_bytes(HeapWord* from,
+ HeapWord* to,
+ size_t count) {
+ memmove(to, from, count);
+ }
+ void _Copy_arrayof_conjoint_jshorts(HeapWord* from,
+ HeapWord* to,
+ size_t count) {
+ memmove(to, from, count * 2);
+ }
+ void _Copy_arrayof_conjoint_jints(HeapWord* from,
+ HeapWord* to,
+ size_t count) {
+ memmove(to, from, count * 4);
+ }
+ void _Copy_arrayof_conjoint_jlongs(HeapWord* from,
+ HeapWord* to,
+ size_t count) {
+ memmove(to, from, count * 8);
+ }
+};
+
+/////////////////////////////////////////////////////////////////////////////
+// Implementations of atomic operations not supported by processors.
+// -- http://gcc.gnu.org/onlinedocs/gcc-4.2.1/gcc/Atomic-Builtins.html
+
+#ifndef _LP64
+extern "C" {
+ long long unsigned int __sync_val_compare_and_swap_8(
+ volatile void *ptr,
+ long long unsigned int oldval,
+ long long unsigned int newval) {
+ ShouldNotCallThis();
+ }
+};
+#endif // !_LP64
diff --git a/src/os_cpu/bsd_zero/vm/os_bsd_zero.hpp b/src/os_cpu/bsd_zero/vm/os_bsd_zero.hpp
new file mode 100644
index 000000000..873e598ab
--- /dev/null
+++ b/src/os_cpu/bsd_zero/vm/os_bsd_zero.hpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2007, 2008, 2010 Red Hat, Inc.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef OS_CPU_BSD_ZERO_VM_OS_BSD_ZERO_HPP
+#define OS_CPU_BSD_ZERO_VM_OS_BSD_ZERO_HPP
+
+ static void setup_fpu() {}
+
+ static bool is_allocatable(size_t bytes);
+
+ // Used to register dynamic code cache area with the OS
+ // Note: Currently only used in 64 bit Windows implementations
+ static bool register_code_area(char *low, char *high) { return true; }
+
+ // Atomically copy 64 bits of data
+ static void atomic_copy64(volatile void *src, volatile void *dst) {
+#if defined(PPC) && !defined(_LP64)
+ double tmp;
+ asm volatile ("lfd %0, 0(%1)\n"
+ "stfd %0, 0(%2)\n"
+ : "=f"(tmp)
+ : "b"(src), "b"(dst));
+#elif defined(S390) && !defined(_LP64)
+ double tmp;
+ asm volatile ("ld %0, 0(%1)\n"
+ "std %0, 0(%2)\n"
+ : "=r"(tmp)
+ : "a"(src), "a"(dst));
+#else
+ *(jlong *) dst = *(jlong *) src;
+#endif
+ }
+
+#endif // OS_CPU_BSD_ZERO_VM_OS_BSD_ZERO_HPP
diff --git a/src/os_cpu/bsd_zero/vm/prefetch_bsd_zero.inline.hpp b/src/os_cpu/bsd_zero/vm/prefetch_bsd_zero.inline.hpp
new file mode 100644
index 000000000..7c4f7867c
--- /dev/null
+++ b/src/os_cpu/bsd_zero/vm/prefetch_bsd_zero.inline.hpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2007, 2008 Red Hat, Inc.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef OS_CPU_BSD_ZERO_VM_PREFETCH_BSD_ZERO_INLINE_HPP
+#define OS_CPU_BSD_ZERO_VM_PREFETCH_BSD_ZERO_INLINE_HPP
+
+#include "runtime/prefetch.hpp"
+
+inline void Prefetch::read(void* loc, intx interval) {
+}
+
+inline void Prefetch::write(void* loc, intx interval) {
+}
+
+#endif // OS_CPU_BSD_ZERO_VM_PREFETCH_BSD_ZERO_INLINE_HPP
diff --git a/src/os_cpu/bsd_zero/vm/threadLS_bsd_zero.cpp b/src/os_cpu/bsd_zero/vm/threadLS_bsd_zero.cpp
new file mode 100644
index 000000000..cd6e0f797
--- /dev/null
+++ b/src/os_cpu/bsd_zero/vm/threadLS_bsd_zero.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2007 Red Hat, Inc.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "runtime/threadLocalStorage.hpp"
+#include "thread_bsd.inline.hpp"
+
+void ThreadLocalStorage::generate_code_for_get_thread() {
+ // nothing to do
+}
+
+void ThreadLocalStorage::pd_init() {
+ // nothing to do
+}
+
+void ThreadLocalStorage::pd_set_thread(Thread* thread) {
+ os::thread_local_storage_at_put(ThreadLocalStorage::thread_index(), thread);
+}
diff --git a/src/os_cpu/bsd_zero/vm/threadLS_bsd_zero.hpp b/src/os_cpu/bsd_zero/vm/threadLS_bsd_zero.hpp
new file mode 100644
index 000000000..0360b581a
--- /dev/null
+++ b/src/os_cpu/bsd_zero/vm/threadLS_bsd_zero.hpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef OS_CPU_BSD_ZERO_VM_THREADLS_BSD_ZERO_HPP
+#define OS_CPU_BSD_ZERO_VM_THREADLS_BSD_ZERO_HPP
+
+// Processor dependent parts of ThreadLocalStorage
+
+ public:
+ static Thread* thread() {
+ return (Thread*) os::thread_local_storage_at(thread_index());
+ }
+
+#endif // OS_CPU_BSD_ZERO_VM_THREADLS_BSD_ZERO_HPP
diff --git a/src/os_cpu/bsd_zero/vm/thread_bsd_zero.cpp b/src/os_cpu/bsd_zero/vm/thread_bsd_zero.cpp
new file mode 100644
index 000000000..eb0abaa72
--- /dev/null
+++ b/src/os_cpu/bsd_zero/vm/thread_bsd_zero.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2009, 2010 Red Hat, Inc.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "runtime/frame.inline.hpp"
+#include "thread_bsd.inline.hpp"
+
+void JavaThread::cache_global_variables() {
+ // nothing to do
+}
diff --git a/src/os_cpu/bsd_zero/vm/thread_bsd_zero.hpp b/src/os_cpu/bsd_zero/vm/thread_bsd_zero.hpp
new file mode 100644
index 000000000..12971a6a8
--- /dev/null
+++ b/src/os_cpu/bsd_zero/vm/thread_bsd_zero.hpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2007, 2008, 2009, 2010 Red Hat, Inc.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef OS_CPU_BSD_ZERO_VM_THREAD_BSD_ZERO_HPP
+#define OS_CPU_BSD_ZERO_VM_THREAD_BSD_ZERO_HPP
+
+ private:
+ ZeroStack _zero_stack;
+ ZeroFrame* _top_zero_frame;
+
+ void pd_initialize() {
+ _top_zero_frame = NULL;
+ }
+
+ public:
+ ZeroStack *zero_stack() {
+ return &_zero_stack;
+ }
+
+ public:
+ ZeroFrame *top_zero_frame() {
+ return _top_zero_frame;
+ }
+ void push_zero_frame(ZeroFrame *frame) {
+ *(ZeroFrame **) frame = _top_zero_frame;
+ _top_zero_frame = frame;
+ }
+ void pop_zero_frame() {
+ zero_stack()->set_sp((intptr_t *) _top_zero_frame + 1);
+ _top_zero_frame = *(ZeroFrame **) _top_zero_frame;
+ }
+
+ public:
+ static ByteSize zero_stack_offset() {
+ return byte_offset_of(JavaThread, _zero_stack);
+ }
+ static ByteSize top_zero_frame_offset() {
+ return byte_offset_of(JavaThread, _top_zero_frame);
+ }
+
+ public:
+ void record_base_of_stack_pointer() {
+ assert(top_zero_frame() == NULL, "junk on stack prior to Java call");
+ }
+ void set_base_of_stack_pointer(intptr_t* base_sp) {
+ assert(base_sp == NULL, "should be");
+ assert(top_zero_frame() == NULL, "junk on stack after Java call");
+ }
+
+ public:
+ void set_last_Java_frame() {
+ set_last_Java_frame(top_zero_frame(), zero_stack()->sp());
+ }
+ void reset_last_Java_frame() {
+ frame_anchor()->zap();
+ }
+ void set_last_Java_frame(ZeroFrame* fp, intptr_t* sp) {
+ frame_anchor()->set(sp, NULL, fp);
+ }
+
+ public:
+ ZeroFrame* last_Java_fp() {
+ return frame_anchor()->last_Java_fp();
+ }
+
+ private:
+ frame pd_last_frame() {
+ assert(has_last_Java_frame(), "must have last_Java_sp() when suspended");
+ return frame(last_Java_fp(), last_Java_sp());
+ }
+
+ public:
+ static ByteSize last_Java_fp_offset() {
+ return byte_offset_of(JavaThread, _anchor) +
+ JavaFrameAnchor::last_Java_fp_offset();
+ }
+
+ public:
+ // Check for pending suspend requests and pending asynchronous
+ // exceptions. There are separate accessors for these, but
+ // _suspend_flags is volatile so using them would be unsafe.
+ bool has_special_condition_for_native_trans() {
+ return _suspend_flags != 0;
+ }
+
+ public:
+ bool pd_get_top_frame_for_signal_handler(frame* fr_addr,
+ void* ucontext,
+ bool isInJava) {
+ ShouldNotCallThis();
+ }
+
+ // These routines are only used on cpu architectures that
+ // have separate register stacks (Itanium).
+ static bool register_stack_overflow() { return false; }
+ static void enable_register_stack_guard() {}
+ static void disable_register_stack_guard() {}
+
+#endif // OS_CPU_BSD_ZERO_VM_THREAD_BSD_ZERO_HPP
diff --git a/src/os_cpu/bsd_zero/vm/vmStructs_bsd_zero.hpp b/src/os_cpu/bsd_zero/vm/vmStructs_bsd_zero.hpp
new file mode 100644
index 000000000..17165cc9d
--- /dev/null
+++ b/src/os_cpu/bsd_zero/vm/vmStructs_bsd_zero.hpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2007 Red Hat, Inc.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef OS_CPU_BSD_ZERO_VM_VMSTRUCTS_BSD_ZERO_HPP
+#define OS_CPU_BSD_ZERO_VM_VMSTRUCTS_BSD_ZERO_HPP
+
+// These are the OS and CPU-specific fields, types and integer
+// constants required by the Serviceability Agent. This file is
+// referenced by vmStructs.cpp.
+
+#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field, last_entry) \
+ /* This must be the last entry, and must be present */ \
+ last_entry()
+
+
+#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type, last_entry) \
+ /* This must be the last entry, and must be present */ \
+ last_entry()
+
+#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \
+ /* This must be the last entry, and must be present */ \
+ last_entry()
+
+#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \
+ /* This must be the last entry, and must be present */ \
+ last_entry()
+
+#endif // OS_CPU_BSD_ZERO_VM_VMSTRUCTS_BSD_ZERO_HPP
diff --git a/src/os_cpu/bsd_zero/vm/vm_version_bsd_zero.cpp b/src/os_cpu/bsd_zero/vm/vm_version_bsd_zero.cpp
new file mode 100644
index 000000000..f2ca79f38
--- /dev/null
+++ b/src/os_cpu/bsd_zero/vm/vm_version_bsd_zero.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2009 Red Hat, Inc.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "runtime/os.hpp"
+#include "vm_version_zero.hpp"
+
+// This file is intentionally empty
diff --git a/src/os_cpu/linux_zero/vm/globals_linux_zero.hpp b/src/os_cpu/linux_zero/vm/globals_linux_zero.hpp
index f12bec986..d952cb7a8 100644
--- a/src/os_cpu/linux_zero/vm/globals_linux_zero.hpp
+++ b/src/os_cpu/linux_zero/vm/globals_linux_zero.hpp
@@ -38,7 +38,6 @@ define_pd_global(intx, VMThreadStackSize, 1024);
#else
define_pd_global(intx, VMThreadStackSize, 512);
#endif // _LP64
-define_pd_global(intx, SurvivorRatio, 8);
define_pd_global(intx, CompilerThreadStackSize, 0);
define_pd_global(uintx, JVMInvokeMethodSlack, 8192);
diff --git a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java
index c72d77714..354b32a99 100644
--- a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java
+++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -37,6 +37,8 @@ public class CallSite {
private int receiver_count;
private String reason;
private List<CallSite> calls;
+ private int endNodes;
+ private double timeStamp;
CallSite() {
}
@@ -93,18 +95,22 @@ public class CallSite {
emit(stream, indent);
String m = getMethod().getHolder().replace('/', '.') + "::" + getMethod().getName();
if (getReason() == null) {
- stream.println(" @ " + getBci() + " " + m + " (" + getMethod().getBytes() + " bytes)");
+ stream.print(" @ " + getBci() + " " + m + " (" + getMethod().getBytes() + " bytes)");
} else {
if (isCompat()) {
- stream.println(" @ " + getBci() + " " + m + " " + getReason());
+ stream.print(" @ " + getBci() + " " + m + " " + getReason());
} else {
- stream.println("- @ " + getBci() + " " + m +
+ stream.print("- @ " + getBci() + " " + m +
" (" + getMethod().getBytes() + " bytes) " + getReason());
}
}
+ if (getEndNodes() > 0) {
+ stream.printf(" (end time: %6.4f nodes: %d)", getTimeStamp(), getEndNodes());
+ }
+ stream.println("");
if (getReceiver() != null) {
- emit(stream, indent + 3);
+ emit(stream, indent + 4);
// stream.println("type profile " + method.holder + " -> " + receiver + " (" +
// receiver_count + "/" + count + "," + (receiver_count * 100 / count) + "%)");
stream.println("type profile " + getMethod().getHolder() + " -> " + getReceiver() + " (" +
@@ -180,4 +186,21 @@ public class CallSite {
public static void setCompat(boolean aCompat) {
compat = aCompat;
}
+
+ void setEndNodes(int n) {
+ endNodes = n;
+ }
+
+ public int getEndNodes() {
+ return endNodes;
+ }
+
+ void setTimeStamp(double time) {
+ timeStamp = time;
+ }
+
+ public double getTimeStamp() {
+ return timeStamp;
+ }
+
}
diff --git a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCompilation.java b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCompilation.java
index 57058882f..12689b0d3 100644
--- a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCompilation.java
+++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCompilation.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -126,7 +126,6 @@ public class LogCompilation extends DefaultHandler implements ErrorHandler, Cons
maxattempts = Math.max(maxattempts,c.getAttempts());
elapsed += c.getElapsedTime();
for (Phase phase : c.getPhases()) {
- out.printf("\t%s %6.4f\n", phase.getName(), phase.getElapsedTime());
Double v = phaseTime.get(phase.getName());
if (v == null) {
v = Double.valueOf(0.0);
@@ -138,6 +137,7 @@ public class LogCompilation extends DefaultHandler implements ErrorHandler, Cons
v2 = Integer.valueOf(0);
}
phaseNodes.put(phase.getName(), Integer.valueOf(v2.intValue() + phase.getNodes()));
+ out.printf("\t%s %6.4f %d %d\n", phase.getName(), phase.getElapsedTime(), phase.getStartNodes(), phase.getNodes());
}
} else if (e instanceof MakeNotEntrantEvent) {
MakeNotEntrantEvent mne = (MakeNotEntrantEvent) e;
diff --git a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java
index 265e92e0d..d864db0ff 100644
--- a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java
+++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -365,7 +365,7 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants
if (currentTrap != null) {
currentTrap.addJVMS(atts.getValue("method"), Integer.parseInt(atts.getValue("bci")));
} else {
- System.err.println("Missing uncommon_trap for jvms");
+ // Ignore <eliminate_allocation type='667'> and <eliminate_lock lock='1'>
}
} else if (qname.equals("nmethod")) {
String id = makeId(atts);
@@ -391,6 +391,11 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants
throw new InternalError("call site and parse don't match");
}
}
+ } else if (qname.equals("parse_done")) {
+ CallSite call = scopes.pop();
+ call.setEndNodes(Integer.parseInt(search(atts, "nodes")));
+ call.setTimeStamp(Double.parseDouble(search(atts, "stamp")));
+ scopes.push(call);
}
}
diff --git a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Phase.java b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Phase.java
index 4dc50ca4e..b448f457b 100644
--- a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Phase.java
+++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Phase.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -37,7 +37,7 @@ public class Phase extends BasicLogEvent {
}
int getNodes() {
- return getStartNodes();
+ return getEndNodes() - getStartNodes();
}
void setEndNodes(int n) {
diff --git a/src/share/vm/adlc/adlc.hpp b/src/share/vm/adlc/adlc.hpp
index 0ed4b77ed..8d48ed601 100644
--- a/src/share/vm/adlc/adlc.hpp
+++ b/src/share/vm/adlc/adlc.hpp
@@ -67,9 +67,9 @@ typedef unsigned int uintptr_t;
#endif
#endif // _WIN32
-#ifdef LINUX
+#if defined(LINUX) || defined(_ALLBSD_SOURCE)
#include <inttypes.h>
-#endif // LINUX
+#endif // LINUX || _ALLBSD_SOURCE
// Macros
#define uint32 unsigned int
diff --git a/src/share/vm/adlc/formssel.cpp b/src/share/vm/adlc/formssel.cpp
index 85118e87f..d3817ed4a 100644
--- a/src/share/vm/adlc/formssel.cpp
+++ b/src/share/vm/adlc/formssel.cpp
@@ -1225,7 +1225,7 @@ void InstructForm::rep_var_format(FILE *fp, const char *rep_var) {
// Handle special constant table variables.
if (strcmp(rep_var, "constanttablebase") == 0) {
fprintf(fp, "char reg[128]; ra->dump_register(in(mach_constant_base_node_input()), reg);\n");
- fprintf(fp, "st->print(\"%%s\");\n");
+ fprintf(fp, " st->print(\"%%s\", reg);\n");
return;
}
if (strcmp(rep_var, "constantoffset") == 0) {
diff --git a/src/share/vm/c1/c1_LIR.cpp b/src/share/vm/c1/c1_LIR.cpp
index 44f2b62a7..267b96664 100644
--- a/src/share/vm/c1/c1_LIR.cpp
+++ b/src/share/vm/c1/c1_LIR.cpp
@@ -1394,8 +1394,15 @@ void LIR_List::instanceof(LIR_Opr result, LIR_Opr object, ciKlass* klass, LIR_Op
}
-void LIR_List::store_check(LIR_Opr object, LIR_Opr array, LIR_Opr tmp1, LIR_Opr tmp2, LIR_Opr tmp3, CodeEmitInfo* info_for_exception) {
- append(new LIR_OpTypeCheck(lir_store_check, object, array, tmp1, tmp2, tmp3, info_for_exception));
+void LIR_List::store_check(LIR_Opr object, LIR_Opr array, LIR_Opr tmp1, LIR_Opr tmp2, LIR_Opr tmp3,
+ CodeEmitInfo* info_for_exception, ciMethod* profiled_method, int profiled_bci) {
+ LIR_OpTypeCheck* c = new LIR_OpTypeCheck(lir_store_check, object, array, tmp1, tmp2, tmp3, info_for_exception);
+ if (profiled_method != NULL) {
+ c->set_profiled_method(profiled_method);
+ c->set_profiled_bci(profiled_bci);
+ c->set_should_profile(true);
+ }
+ append(c);
}
diff --git a/src/share/vm/c1/c1_LIR.hpp b/src/share/vm/c1/c1_LIR.hpp
index a2770e402..c440b7137 100644
--- a/src/share/vm/c1/c1_LIR.hpp
+++ b/src/share/vm/c1/c1_LIR.hpp
@@ -2100,7 +2100,7 @@ class LIR_List: public CompilationResourceObj {
void fpop_raw() { append(new LIR_Op0(lir_fpop_raw)); }
void instanceof(LIR_Opr result, LIR_Opr object, ciKlass* klass, LIR_Opr tmp1, LIR_Opr tmp2, LIR_Opr tmp3, bool fast_check, CodeEmitInfo* info_for_patch, ciMethod* profiled_method, int profiled_bci);
- void store_check(LIR_Opr object, LIR_Opr array, LIR_Opr tmp1, LIR_Opr tmp2, LIR_Opr tmp3, CodeEmitInfo* info_for_exception);
+ void store_check(LIR_Opr object, LIR_Opr array, LIR_Opr tmp1, LIR_Opr tmp2, LIR_Opr tmp3, CodeEmitInfo* info_for_exception, ciMethod* profiled_method, int profiled_bci);
void checkcast (LIR_Opr result, LIR_Opr object, ciKlass* klass,
LIR_Opr tmp1, LIR_Opr tmp2, LIR_Opr tmp3, bool fast_check,
diff --git a/src/share/vm/c1/c1_LIRGenerator.cpp b/src/share/vm/c1/c1_LIRGenerator.cpp
index 676efe3f7..c2c2f7c7f 100644
--- a/src/share/vm/c1/c1_LIRGenerator.cpp
+++ b/src/share/vm/c1/c1_LIRGenerator.cpp
@@ -2970,8 +2970,8 @@ void LIRGenerator::do_ProfileInvoke(ProfileInvoke* x) {
// accessors are also always mature.
if (!x->inlinee()->is_accessor()) {
CodeEmitInfo* info = state_for(x, x->state(), true);
- // Increment invocation counter, don't notify the runtime, because we don't inline loops,
- increment_event_counter_impl(info, x->inlinee(), 0, InvocationEntryBci, false, false);
+ // Notify the runtime very infrequently only to take care of counter overflows
+ increment_event_counter_impl(info, x->inlinee(), (1 << Tier23InlineeNotifyFreqLog) - 1, InvocationEntryBci, false, true);
}
}
diff --git a/src/share/vm/c1/c1_globals.hpp b/src/share/vm/c1/c1_globals.hpp
index 60fe6d080..15f3cc10f 100644
--- a/src/share/vm/c1/c1_globals.hpp
+++ b/src/share/vm/c1/c1_globals.hpp
@@ -47,6 +47,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "c1_globals_windows.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "c1_globals_bsd.hpp"
+#endif
//
// Defines all global flags used by the client compiler.
diff --git a/src/share/vm/ci/ciEnv.cpp b/src/share/vm/ci/ciEnv.cpp
index 2fd712d06..82492a08e 100644
--- a/src/share/vm/ci/ciEnv.cpp
+++ b/src/share/vm/ci/ciEnv.cpp
@@ -910,27 +910,37 @@ void ciEnv::validate_compile_task_dependencies(ciMethod* target) {
// dependencies were inserted. Any violated dependences in this
// case are dumped to the tty.
bool counter_changed = system_dictionary_modification_counter_changed();
- bool test_deps = counter_changed;
- DEBUG_ONLY(test_deps = true);
- if (!test_deps) return;
- bool print_failures = false;
- DEBUG_ONLY(print_failures = !counter_changed);
- bool keep_going = (print_failures || xtty != NULL);
- int klass_violations = 0;
+ bool verify_deps = trueInDebug;
+ if (!counter_changed && !verify_deps) return;
+ int klass_violations = 0;
for (Dependencies::DepStream deps(dependencies()); deps.next(); ) {
if (!deps.is_klass_type()) continue; // skip non-klass dependencies
klassOop witness = deps.check_dependency();
if (witness != NULL) {
klass_violations++;
- if (print_failures) deps.print_dependency(witness, /*verbose=*/ true);
+ if (!counter_changed) {
+ // Dependence failed but counter didn't change. Log a message
+ // describing what failed and allow the assert at the end to
+ // trigger.
+ deps.print_dependency(witness);
+ } else if (xtty == NULL) {
+ // If we're not logging then a single violation is sufficient,
+ // otherwise we want to log all the dependences which were
+ // violated.
+ break;
+ }
}
- // If there's no log and we're not sanity-checking, we're done.
- if (!keep_going) break;
}
if (klass_violations != 0) {
+#ifdef ASSERT
+ if (!counter_changed && !PrintCompilation) {
+ // Print out the compile task that failed
+ _task->print_line();
+ }
+#endif
assert(counter_changed, "failed dependencies, but counter didn't change");
record_failure("concurrent class loading");
}
diff --git a/src/share/vm/classfile/classLoader.cpp b/src/share/vm/classfile/classLoader.cpp
index 0a3b5caf1..df42dc75d 100644
--- a/src/share/vm/classfile/classLoader.cpp
+++ b/src/share/vm/classfile/classLoader.cpp
@@ -68,6 +68,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "os_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "os_bsd.inline.hpp"
+#endif
// Entry points in zip.dll for loading zip/jar file entries
diff --git a/src/share/vm/classfile/javaClasses.cpp b/src/share/vm/classfile/javaClasses.cpp
index 542ed3f2e..385899a55 100644
--- a/src/share/vm/classfile/javaClasses.cpp
+++ b/src/share/vm/classfile/javaClasses.cpp
@@ -58,6 +58,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
#define INJECTED_FIELD_COMPUTE_OFFSET(klass, name, signature, may_be_java) \
klass::_##name##_offset = JavaClasses::compute_injected_offset(JavaClasses::klass##_##name##_enum);
@@ -1145,7 +1148,7 @@ char* java_lang_Throwable::print_stack_element_to_buffer(methodOop method, int b
}
nmethod* nm = method->code();
if (WizardMode && nm != NULL) {
- sprintf(buf + (int)strlen(buf), "(nmethod " PTR_FORMAT ")", (intptr_t)nm);
+ sprintf(buf + (int)strlen(buf), "(nmethod " INTPTR_FORMAT ")", (intptr_t)nm);
}
}
diff --git a/src/share/vm/classfile/vmSymbols.hpp b/src/share/vm/classfile/vmSymbols.hpp
index a5c5781fe..16652e5ef 100644
--- a/src/share/vm/classfile/vmSymbols.hpp
+++ b/src/share/vm/classfile/vmSymbols.hpp
@@ -967,7 +967,8 @@
// Class vmSymbols
class vmSymbols: AllStatic {
- friend class vmIntrinsics;
+ friend class vmIntrinsics;
+ friend class VMStructs;
public:
// enum for figuring positions and size of array holding Symbol*s
enum SID {
diff --git a/src/share/vm/code/stubs.hpp b/src/share/vm/code/stubs.hpp
index ed5380f6e..328ad8bf7 100644
--- a/src/share/vm/code/stubs.hpp
+++ b/src/share/vm/code/stubs.hpp
@@ -35,6 +35,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "os_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "os_bsd.inline.hpp"
+#endif
// The classes in this file provide a simple framework for the
// management of little pieces of machine code - or stubs -
diff --git a/src/share/vm/compiler/disassembler.hpp b/src/share/vm/compiler/disassembler.hpp
index 376154075..a70b8ccd3 100644
--- a/src/share/vm/compiler/disassembler.hpp
+++ b/src/share/vm/compiler/disassembler.hpp
@@ -35,6 +35,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "os_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "os_bsd.inline.hpp"
+#endif
class decode_env;
diff --git a/src/share/vm/gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.cpp b/src/share/vm/gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.cpp
index 5bee77ef2..5edd8ccc9 100644
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.cpp
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.cpp
@@ -37,6 +37,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "os_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "os_bsd.inline.hpp"
+#endif
elapsedTimer CMSAdaptiveSizePolicy::_concurrent_timer;
elapsedTimer CMSAdaptiveSizePolicy::_STW_timer;
diff --git a/src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.cpp b/src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.cpp
index cbe5953a3..0566f38a0 100644
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.cpp
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.cpp
@@ -50,6 +50,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
//
// ConcurrentMarkSweepPolicy methods
diff --git a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp
index a299c32e2..63e5cb457 100644
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp
@@ -36,6 +36,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
class ConcurrentMarkSweepGeneration;
class CMSCollector;
diff --git a/src/share/vm/gc_implementation/concurrentMarkSweep/freeBlockDictionary.cpp b/src/share/vm/gc_implementation/concurrentMarkSweep/freeBlockDictionary.cpp
index 1c1b3ffe5..1870c1f1b 100644
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/freeBlockDictionary.cpp
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/freeBlockDictionary.cpp
@@ -33,6 +33,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
#ifndef PRODUCT
Mutex* FreeBlockDictionary::par_lock() const {
diff --git a/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp b/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp
index 2a7f51380..915ee25ef 100644
--- a/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp
+++ b/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp
@@ -39,6 +39,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
bool DirtyCardQueue::apply_closure(CardTableEntryClosure* cl,
bool consume,
diff --git a/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp b/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp
index 59d259065..e54956c75 100644
--- a/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp
+++ b/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp
@@ -37,6 +37,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
G1SATBCardTableModRefBS::G1SATBCardTableModRefBS(MemRegion whole_heap,
int max_covered_regions) :
diff --git a/src/share/vm/gc_implementation/g1/ptrQueue.cpp b/src/share/vm/gc_implementation/g1/ptrQueue.cpp
index 4186b42b7..7bf8fec64 100644
--- a/src/share/vm/gc_implementation/g1/ptrQueue.cpp
+++ b/src/share/vm/gc_implementation/g1/ptrQueue.cpp
@@ -37,6 +37,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
PtrQueue::PtrQueue(PtrQueueSet* qset, bool perm, bool active) :
_qset(qset), _buf(NULL), _index(0), _active(active),
diff --git a/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp b/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp
index f43fffce1..4496a6987 100644
--- a/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp
+++ b/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp
@@ -38,6 +38,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "os_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "os_bsd.inline.hpp"
+#endif
bool
ParMarkBitMap::initialize(MemRegion covered_region)
diff --git a/src/share/vm/gc_implementation/parallelScavenge/psVirtualspace.cpp b/src/share/vm/gc_implementation/parallelScavenge/psVirtualspace.cpp
index 8eba89397..e19476707 100644
--- a/src/share/vm/gc_implementation/parallelScavenge/psVirtualspace.cpp
+++ b/src/share/vm/gc_implementation/parallelScavenge/psVirtualspace.cpp
@@ -35,6 +35,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "os_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "os_bsd.inline.hpp"
+#endif
// PSVirtualSpace
diff --git a/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp b/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp
index aacaf3553..e38556db7 100644
--- a/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp
+++ b/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp
@@ -37,6 +37,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
MutableNUMASpace::MutableNUMASpace(size_t alignment) : MutableSpace(alignment) {
diff --git a/src/share/vm/gc_interface/collectedHeap.cpp b/src/share/vm/gc_interface/collectedHeap.cpp
index d5b045436..0a4b42c42 100644
--- a/src/share/vm/gc_interface/collectedHeap.cpp
+++ b/src/share/vm/gc_interface/collectedHeap.cpp
@@ -39,6 +39,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
#ifdef ASSERT
diff --git a/src/share/vm/gc_interface/collectedHeap.hpp b/src/share/vm/gc_interface/collectedHeap.hpp
index 36fcb40a8..5761ea554 100644
--- a/src/share/vm/gc_interface/collectedHeap.hpp
+++ b/src/share/vm/gc_interface/collectedHeap.hpp
@@ -322,6 +322,7 @@ class CollectedHeap : public CHeapObj {
// General obj/array allocation facilities.
inline static oop obj_allocate(KlassHandle klass, int size, TRAPS);
inline static oop array_allocate(KlassHandle klass, int size, int length, TRAPS);
+ inline static oop array_allocate_nozero(KlassHandle klass, int size, int length, TRAPS);
// Special obj/array allocation facilities.
// Some heaps may want to manage "permanent" data uniquely. These default
diff --git a/src/share/vm/gc_interface/collectedHeap.inline.hpp b/src/share/vm/gc_interface/collectedHeap.inline.hpp
index cf9946d79..adced061d 100644
--- a/src/share/vm/gc_interface/collectedHeap.inline.hpp
+++ b/src/share/vm/gc_interface/collectedHeap.inline.hpp
@@ -43,6 +43,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
// Inline allocation implementations.
@@ -271,6 +274,23 @@ oop CollectedHeap::array_allocate(KlassHandle klass,
return (oop)obj;
}
+oop CollectedHeap::array_allocate_nozero(KlassHandle klass,
+ int size,
+ int length,
+ TRAPS) {
+ debug_only(check_for_valid_allocation_state());
+ assert(!Universe::heap()->is_gc_active(), "Allocation during gc not allowed");
+ assert(size >= 0, "int won't convert to size_t");
+ HeapWord* obj = common_mem_allocate_noinit(size, CHECK_NULL);
+ ((oop)obj)->set_klass_gap(0);
+ post_allocation_setup_array(klass, obj, size, length);
+#ifndef PRODUCT
+ const size_t hs = oopDesc::header_size()+1;
+ Universe::heap()->check_for_non_bad_heap_word_value(obj+hs, size-hs);
+#endif
+ return (oop)obj;
+}
+
oop CollectedHeap::permanent_obj_allocate(KlassHandle klass, int size, TRAPS) {
oop obj = permanent_obj_allocate_no_klass_install(klass, size, CHECK_NULL);
post_allocation_install_obj_klass(klass, obj, size);
diff --git a/src/share/vm/interpreter/abstractInterpreter.hpp b/src/share/vm/interpreter/abstractInterpreter.hpp
index a79281295..a68fac1d6 100644
--- a/src/share/vm/interpreter/abstractInterpreter.hpp
+++ b/src/share/vm/interpreter/abstractInterpreter.hpp
@@ -56,6 +56,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
// This file contains the platform-independent parts
// of the abstract interpreter and the abstract interpreter generator.
diff --git a/src/share/vm/interpreter/bytecodeInterpreter.cpp b/src/share/vm/interpreter/bytecodeInterpreter.cpp
index 7da054dfb..68bd1c73e 100644
--- a/src/share/vm/interpreter/bytecodeInterpreter.cpp
+++ b/src/share/vm/interpreter/bytecodeInterpreter.cpp
@@ -65,6 +65,12 @@
#ifdef TARGET_OS_ARCH_linux_ppc
# include "orderAccess_linux_ppc.inline.hpp"
#endif
+#ifdef TARGET_OS_ARCH_bsd_x86
+# include "orderAccess_bsd_x86.inline.hpp"
+#endif
+#ifdef TARGET_OS_ARCH_bsd_zero
+# include "orderAccess_bsd_zero.inline.hpp"
+#endif
// no precompiled headers
diff --git a/src/share/vm/interpreter/bytecodeTracer.cpp b/src/share/vm/interpreter/bytecodeTracer.cpp
index 292e19c1e..b9f64ed8c 100644
--- a/src/share/vm/interpreter/bytecodeTracer.cpp
+++ b/src/share/vm/interpreter/bytecodeTracer.cpp
@@ -92,7 +92,7 @@ class BytecodePrinter: public BytecodeClosure {
// the incoming method. We could lose a line of trace output.
// This is acceptable in a debug-only feature.
st->cr();
- st->print("[%d] ", (int) Thread::current()->osthread()->thread_id());
+ st->print("[%ld] ", (long) Thread::current()->osthread()->thread_id());
method->print_name(st);
st->cr();
_current_method = method();
@@ -106,7 +106,7 @@ class BytecodePrinter: public BytecodeClosure {
}
_code = code;
int bci = bcp - method->code_base();
- st->print("[%d] ", (int) Thread::current()->osthread()->thread_id());
+ st->print("[%ld] ", (long) Thread::current()->osthread()->thread_id());
if (Verbose) {
st->print("%8d %4d " INTPTR_FORMAT " " INTPTR_FORMAT " %s",
BytecodeCounter::counter_value(), bci, tos, tos2, Bytecodes::name(code));
diff --git a/src/share/vm/interpreter/interpreterRuntime.hpp b/src/share/vm/interpreter/interpreterRuntime.hpp
index d1d14b468..93c1a9eca 100644
--- a/src/share/vm/interpreter/interpreterRuntime.hpp
+++ b/src/share/vm/interpreter/interpreterRuntime.hpp
@@ -41,6 +41,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
// The InterpreterRuntime is called by the interpreter for everything
// that cannot/should not be dealt with in assembly and needs C support.
diff --git a/src/share/vm/interpreter/linkResolver.cpp b/src/share/vm/interpreter/linkResolver.cpp
index 3d655afb4..b7defd751 100644
--- a/src/share/vm/interpreter/linkResolver.cpp
+++ b/src/share/vm/interpreter/linkResolver.cpp
@@ -52,6 +52,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
//------------------------------------------------------------------------------------------------------------------------
// Implementation of FieldAccessInfo
diff --git a/src/share/vm/memory/allocation.cpp b/src/share/vm/memory/allocation.cpp
index 356e8257e..0479e7337 100644
--- a/src/share/vm/memory/allocation.cpp
+++ b/src/share/vm/memory/allocation.cpp
@@ -39,6 +39,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "os_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "os_bsd.inline.hpp"
+#endif
void* CHeapObj::operator new(size_t size){
return (void *) AllocateHeap(size, "CHeapObj-new");
diff --git a/src/share/vm/memory/collectorPolicy.cpp b/src/share/vm/memory/collectorPolicy.cpp
index 7a1a2944f..8412682d1 100644
--- a/src/share/vm/memory/collectorPolicy.cpp
+++ b/src/share/vm/memory/collectorPolicy.cpp
@@ -47,6 +47,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
#ifndef SERIALGC
#include "gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.hpp"
#include "gc_implementation/concurrentMarkSweep/cmsGCAdaptivePolicyCounters.hpp"
diff --git a/src/share/vm/memory/defNewGeneration.cpp b/src/share/vm/memory/defNewGeneration.cpp
index c1a7051d7..5913b2c78 100644
--- a/src/share/vm/memory/defNewGeneration.cpp
+++ b/src/share/vm/memory/defNewGeneration.cpp
@@ -48,6 +48,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
//
// DefNewGeneration functions.
diff --git a/src/share/vm/memory/gcLocker.hpp b/src/share/vm/memory/gcLocker.hpp
index 09135cb49..c9d913abf 100644
--- a/src/share/vm/memory/gcLocker.hpp
+++ b/src/share/vm/memory/gcLocker.hpp
@@ -41,6 +41,10 @@
# include "os_windows.inline.hpp"
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "os_bsd.inline.hpp"
+# include "thread_bsd.inline.hpp"
+#endif
// The direct lock/unlock calls do not force a collection if an unlock
// decrements the count to zero. Avoid calling these if at all possible.
diff --git a/src/share/vm/memory/genMarkSweep.cpp b/src/share/vm/memory/genMarkSweep.cpp
index 802c646e1..94a73dd31 100644
--- a/src/share/vm/memory/genMarkSweep.cpp
+++ b/src/share/vm/memory/genMarkSweep.cpp
@@ -55,6 +55,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
void GenMarkSweep::invoke_at_safepoint(int level, ReferenceProcessor* rp,
bool clear_all_softrefs) {
diff --git a/src/share/vm/memory/oopFactory.cpp b/src/share/vm/memory/oopFactory.cpp
index 08f9825b3..c6e644c96 100644
--- a/src/share/vm/memory/oopFactory.cpp
+++ b/src/share/vm/memory/oopFactory.cpp
@@ -77,7 +77,14 @@ typeArrayOop oopFactory::new_permanent_intArray(int length, TRAPS) {
typeArrayOop oopFactory::new_typeArray(BasicType type, int length, TRAPS) {
klassOop type_asKlassOop = Universe::typeArrayKlassObj(type);
typeArrayKlass* type_asArrayKlass = typeArrayKlass::cast(type_asKlassOop);
- typeArrayOop result = type_asArrayKlass->allocate(length, THREAD);
+ typeArrayOop result = type_asArrayKlass->allocate_common(length, true, THREAD);
+ return result;
+}
+
+typeArrayOop oopFactory::new_typeArray_nozero(BasicType type, int length, TRAPS) {
+ klassOop type_asKlassOop = Universe::typeArrayKlassObj(type);
+ typeArrayKlass* type_asArrayKlass = typeArrayKlass::cast(type_asKlassOop);
+ typeArrayOop result = type_asArrayKlass->allocate_common(length, false, THREAD);
return result;
}
diff --git a/src/share/vm/memory/oopFactory.hpp b/src/share/vm/memory/oopFactory.hpp
index 32e50fb40..dbb42f053 100644
--- a/src/share/vm/memory/oopFactory.hpp
+++ b/src/share/vm/memory/oopFactory.hpp
@@ -63,6 +63,7 @@ class oopFactory: AllStatic {
static typeArrayOop new_permanent_intArray (int length, TRAPS); // used for class file structures
static typeArrayOop new_typeArray(BasicType type, int length, TRAPS);
+ static typeArrayOop new_typeArray_nozero(BasicType type, int length, TRAPS);
// Constant pools
static constantPoolOop new_constantPool (int length,
diff --git a/src/share/vm/memory/resourceArea.cpp b/src/share/vm/memory/resourceArea.cpp
index 90c1e6e3e..28d5943b5 100644
--- a/src/share/vm/memory/resourceArea.cpp
+++ b/src/share/vm/memory/resourceArea.cpp
@@ -35,6 +35,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
//------------------------------ResourceMark-----------------------------------
debug_only(int ResourceArea::_warned;) // to suppress multiple warnings
diff --git a/src/share/vm/memory/resourceArea.hpp b/src/share/vm/memory/resourceArea.hpp
index 3bb84b5e1..3d3124897 100644
--- a/src/share/vm/memory/resourceArea.hpp
+++ b/src/share/vm/memory/resourceArea.hpp
@@ -35,6 +35,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
// The resource area holds temporary data structures in the VM.
// The actual allocation areas are thread local. Typical usage:
diff --git a/src/share/vm/memory/space.hpp b/src/share/vm/memory/space.hpp
index 3693b64ea..ef7e2312e 100644
--- a/src/share/vm/memory/space.hpp
+++ b/src/share/vm/memory/space.hpp
@@ -44,6 +44,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "os_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "os_bsd.inline.hpp"
+#endif
// A space is an abstraction for the "storage units" backing
// up the generation abstraction. It includes specific
diff --git a/src/share/vm/memory/threadLocalAllocBuffer.cpp b/src/share/vm/memory/threadLocalAllocBuffer.cpp
index 74f2c44d4..03d6e6b83 100644
--- a/src/share/vm/memory/threadLocalAllocBuffer.cpp
+++ b/src/share/vm/memory/threadLocalAllocBuffer.cpp
@@ -38,6 +38,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
// Thread-Local Edens support
diff --git a/src/share/vm/memory/universe.cpp b/src/share/vm/memory/universe.cpp
index 355341c43..4652b40cf 100644
--- a/src/share/vm/memory/universe.cpp
+++ b/src/share/vm/memory/universe.cpp
@@ -89,6 +89,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
#ifndef SERIALGC
#include "gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.hpp"
#include "gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.hpp"
diff --git a/src/share/vm/oops/constantPoolKlass.cpp b/src/share/vm/oops/constantPoolKlass.cpp
index 362e275c2..0b3a67afa 100644
--- a/src/share/vm/oops/constantPoolKlass.cpp
+++ b/src/share/vm/oops/constantPoolKlass.cpp
@@ -44,6 +44,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
#ifndef SERIALGC
#include "gc_implementation/parNew/parOopClosures.inline.hpp"
#include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp"
diff --git a/src/share/vm/oops/constantPoolOop.cpp b/src/share/vm/oops/constantPoolOop.cpp
index a46f4ebeb..87280c671 100644
--- a/src/share/vm/oops/constantPoolOop.cpp
+++ b/src/share/vm/oops/constantPoolOop.cpp
@@ -1355,7 +1355,7 @@ static void print_cpool_bytes(jint cnt, u1 *bytes) {
}
case JVM_CONSTANT_Long: {
u8 val = Bytes::get_Java_u8(bytes);
- printf("long "INT64_FORMAT, *(jlong *) &val);
+ printf("long "INT64_FORMAT, (int64_t) *(jlong *) &val);
ent_size = 8;
idx++; // Long takes two cpool slots
break;
diff --git a/src/share/vm/oops/instanceKlass.cpp b/src/share/vm/oops/instanceKlass.cpp
index 692dbc742..20b0a96d0 100644
--- a/src/share/vm/oops/instanceKlass.cpp
+++ b/src/share/vm/oops/instanceKlass.cpp
@@ -61,6 +61,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
#ifndef SERIALGC
#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
#include "gc_implementation/g1/g1OopClosures.inline.hpp"
diff --git a/src/share/vm/oops/markOop.cpp b/src/share/vm/oops/markOop.cpp
index 5be365e72..5e85944a1 100644
--- a/src/share/vm/oops/markOop.cpp
+++ b/src/share/vm/oops/markOop.cpp
@@ -33,6 +33,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
void markOopDesc::print_on(outputStream* st) const {
diff --git a/src/share/vm/oops/oop.cpp b/src/share/vm/oops/oop.cpp
index d8fa9b023..f836fb792 100644
--- a/src/share/vm/oops/oop.cpp
+++ b/src/share/vm/oops/oop.cpp
@@ -36,6 +36,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
bool always_do_update_barrier = false;
diff --git a/src/share/vm/oops/oopsHierarchy.cpp b/src/share/vm/oops/oopsHierarchy.cpp
index 950980673..b7d2c3599 100644
--- a/src/share/vm/oops/oopsHierarchy.cpp
+++ b/src/share/vm/oops/oopsHierarchy.cpp
@@ -37,6 +37,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
#ifdef CHECK_UNHANDLED_OOPS
diff --git a/src/share/vm/oops/typeArrayKlass.cpp b/src/share/vm/oops/typeArrayKlass.cpp
index 633841711..a3c58cd0e 100644
--- a/src/share/vm/oops/typeArrayKlass.cpp
+++ b/src/share/vm/oops/typeArrayKlass.cpp
@@ -76,7 +76,7 @@ klassOop typeArrayKlass::create_klass(BasicType type, int scale,
return k();
}
-typeArrayOop typeArrayKlass::allocate(int length, TRAPS) {
+typeArrayOop typeArrayKlass::allocate_common(int length, bool do_zero, TRAPS) {
assert(log2_element_size() >= 0, "bad scale");
if (length >= 0) {
if (length <= max_length()) {
@@ -84,7 +84,11 @@ typeArrayOop typeArrayKlass::allocate(int length, TRAPS) {
KlassHandle h_k(THREAD, as_klassOop());
typeArrayOop t;
CollectedHeap* ch = Universe::heap();
- t = (typeArrayOop)CollectedHeap::array_allocate(h_k, (int)size, length, CHECK_NULL);
+ if (do_zero) {
+ t = (typeArrayOop)CollectedHeap::array_allocate(h_k, (int)size, length, CHECK_NULL);
+ } else {
+ t = (typeArrayOop)CollectedHeap::array_allocate_nozero(h_k, (int)size, length, CHECK_NULL);
+ }
assert(t->is_parsable(), "Don't publish unless parsable");
return t;
} else {
diff --git a/src/share/vm/oops/typeArrayKlass.hpp b/src/share/vm/oops/typeArrayKlass.hpp
index 78a26be09..0f530668c 100644
--- a/src/share/vm/oops/typeArrayKlass.hpp
+++ b/src/share/vm/oops/typeArrayKlass.hpp
@@ -56,7 +56,8 @@ class typeArrayKlass : public arrayKlass {
bool compute_is_subtype_of(klassOop k);
// Allocation
- typeArrayOop allocate(int length, TRAPS);
+ typeArrayOop allocate_common(int length, bool do_zero, TRAPS);
+ typeArrayOop allocate(int length, TRAPS) { return allocate_common(length, true, THREAD); }
typeArrayOop allocate_permanent(int length, TRAPS); // used for class file structures
oop multi_allocate(int rank, jint* sizes, TRAPS);
diff --git a/src/share/vm/oops/typeArrayOop.hpp b/src/share/vm/oops/typeArrayOop.hpp
index e0133fd9d..292609e43 100644
--- a/src/share/vm/oops/typeArrayOop.hpp
+++ b/src/share/vm/oops/typeArrayOop.hpp
@@ -51,6 +51,12 @@
#ifdef TARGET_OS_ARCH_linux_ppc
# include "orderAccess_linux_ppc.inline.hpp"
#endif
+#ifdef TARGET_OS_ARCH_bsd_x86
+# include "orderAccess_bsd_x86.inline.hpp"
+#endif
+#ifdef TARGET_OS_ARCH_bsd_zero
+# include "orderAccess_bsd_zero.inline.hpp"
+#endif
// A typeArrayOop is an array containing basic types (non oop elements).
// It is used for arrays of {characters, singles, doubles, bytes, shorts, integers, longs}
diff --git a/src/share/vm/opto/c2_globals.hpp b/src/share/vm/opto/c2_globals.hpp
index 84a7d020d..827e76ed4 100644
--- a/src/share/vm/opto/c2_globals.hpp
+++ b/src/share/vm/opto/c2_globals.hpp
@@ -44,6 +44,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "c2_globals_windows.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "c2_globals_bsd.hpp"
+#endif
//
// Defines all globals flags used by the server compiler.
diff --git a/src/share/vm/opto/library_call.cpp b/src/share/vm/opto/library_call.cpp
index 8179f379b..d5ad00e16 100644
--- a/src/share/vm/opto/library_call.cpp
+++ b/src/share/vm/opto/library_call.cpp
@@ -4658,6 +4658,7 @@ LibraryCallKit::generate_arraycopy(const TypePtr* adr_type,
// "You break it, you buy it."
InitializeNode* init = alloc->initialization();
assert(init->is_complete(), "we just did this");
+ init->set_complete_with_arraycopy();
assert(dest->is_CheckCastPP(), "sanity");
assert(dest->in(0)->in(0) == init, "dest pinned");
adr_type = TypeRawPtr::BOTTOM; // all initializations are into raw memory
diff --git a/src/share/vm/opto/macro.cpp b/src/share/vm/opto/macro.cpp
index 1e12e3660..b5f645359 100644
--- a/src/share/vm/opto/macro.cpp
+++ b/src/share/vm/opto/macro.cpp
@@ -1685,9 +1685,21 @@ void PhaseMacroExpand::expand_allocate(AllocateNode *alloc) {
void PhaseMacroExpand::expand_allocate_array(AllocateArrayNode *alloc) {
Node* length = alloc->in(AllocateNode::ALength);
+ InitializeNode* init = alloc->initialization();
+ Node* klass_node = alloc->in(AllocateNode::KlassNode);
+ ciKlass* k = _igvn.type(klass_node)->is_klassptr()->klass();
+ address slow_call_address; // Address of slow call
+ if (init != NULL && init->is_complete_with_arraycopy() &&
+ k->is_type_array_klass()) {
+ // Don't zero type array during slow allocation in VM since
+ // it will be initialized later by arraycopy in compiled code.
+ slow_call_address = OptoRuntime::new_array_nozero_Java();
+ } else {
+ slow_call_address = OptoRuntime::new_array_Java();
+ }
expand_allocate_common(alloc, length,
OptoRuntime::new_array_Type(),
- OptoRuntime::new_array_Java());
+ slow_call_address);
}
//-----------------------mark_eliminated_locking_nodes-----------------------
diff --git a/src/share/vm/opto/memnode.cpp b/src/share/vm/opto/memnode.cpp
index ba0960116..4f6dc0851 100644
--- a/src/share/vm/opto/memnode.cpp
+++ b/src/share/vm/opto/memnode.cpp
@@ -2847,7 +2847,7 @@ Node *MemBarNode::match( const ProjNode *proj, const Matcher *m ) {
//---------------------------InitializeNode------------------------------------
InitializeNode::InitializeNode(Compile* C, int adr_type, Node* rawoop)
- : _is_complete(false),
+ : _is_complete(Incomplete),
MemBarNode(C, adr_type, rawoop)
{
init_class_id(Class_Initialize);
@@ -2885,7 +2885,7 @@ bool InitializeNode::is_non_zero() {
void InitializeNode::set_complete(PhaseGVN* phase) {
assert(!is_complete(), "caller responsibility");
- _is_complete = true;
+ _is_complete = Complete;
// After this node is complete, it contains a bunch of
// raw-memory initializations. There is no need for
diff --git a/src/share/vm/opto/memnode.hpp b/src/share/vm/opto/memnode.hpp
index a9eacdd8c..d757b13f3 100644
--- a/src/share/vm/opto/memnode.hpp
+++ b/src/share/vm/opto/memnode.hpp
@@ -942,7 +942,12 @@ public:
class InitializeNode: public MemBarNode {
friend class AllocateNode;
- bool _is_complete;
+ enum {
+ Incomplete = 0,
+ Complete = 1,
+ WithArraycopy = 2
+ };
+ int _is_complete;
public:
enum {
@@ -976,10 +981,12 @@ public:
// An InitializeNode must completed before macro expansion is done.
// Completion requires that the AllocateNode must be followed by
// initialization of the new memory to zero, then to any initializers.
- bool is_complete() { return _is_complete; }
+ bool is_complete() { return _is_complete != Incomplete; }
+ bool is_complete_with_arraycopy() { return (_is_complete & WithArraycopy) != 0; }
// Mark complete. (Must not yet be complete.)
void set_complete(PhaseGVN* phase);
+ void set_complete_with_arraycopy() { _is_complete = Complete | WithArraycopy; }
#ifdef ASSERT
// ensure all non-degenerate stores are ordered and non-overlapping
diff --git a/src/share/vm/opto/phaseX.cpp b/src/share/vm/opto/phaseX.cpp
index 7b5d6cddc..541744ac8 100644
--- a/src/share/vm/opto/phaseX.cpp
+++ b/src/share/vm/opto/phaseX.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -864,6 +864,10 @@ void PhaseIterGVN::optimize() {
// Pull from worklist; transform node;
// If node has changed: update edge info and put uses on worklist.
while( _worklist.size() ) {
+ if (C->check_node_count(NodeLimitFudgeFactor * 2,
+ "out of nodes optimizing method")) {
+ return;
+ }
Node *n = _worklist.pop();
if (++loop_count >= K * C->unique()) {
debug_only(n->dump(4);)
diff --git a/src/share/vm/opto/runtime.cpp b/src/share/vm/opto/runtime.cpp
index 49c55212f..a4495ea74 100644
--- a/src/share/vm/opto/runtime.cpp
+++ b/src/share/vm/opto/runtime.cpp
@@ -102,6 +102,7 @@
// Compiled code entry points
address OptoRuntime::_new_instance_Java = NULL;
address OptoRuntime::_new_array_Java = NULL;
+address OptoRuntime::_new_array_nozero_Java = NULL;
address OptoRuntime::_multianewarray2_Java = NULL;
address OptoRuntime::_multianewarray3_Java = NULL;
address OptoRuntime::_multianewarray4_Java = NULL;
@@ -151,6 +152,7 @@ void OptoRuntime::generate(ciEnv* env) {
// -------------------------------------------------------------------------------------------------------------------------------
gen(env, _new_instance_Java , new_instance_Type , new_instance_C , 0 , true , false, false);
gen(env, _new_array_Java , new_array_Type , new_array_C , 0 , true , false, false);
+ gen(env, _new_array_nozero_Java , new_array_Type , new_array_nozero_C , 0 , true , false, false);
gen(env, _multianewarray2_Java , multianewarray2_Type , multianewarray2_C , 0 , true , false, false);
gen(env, _multianewarray3_Java , multianewarray3_Type , multianewarray3_C , 0 , true , false, false);
gen(env, _multianewarray4_Java , multianewarray4_Type , multianewarray4_C , 0 , true , false, false);
@@ -308,6 +310,36 @@ JRT_BLOCK_ENTRY(void, OptoRuntime::new_array_C(klassOopDesc* array_type, int len
}
JRT_END
+// array allocation without zeroing
+JRT_BLOCK_ENTRY(void, OptoRuntime::new_array_nozero_C(klassOopDesc* array_type, int len, JavaThread *thread))
+ JRT_BLOCK;
+#ifndef PRODUCT
+ SharedRuntime::_new_array_ctr++; // new array requires GC
+#endif
+ assert(check_compiled_frame(thread), "incorrect caller");
+
+ // Scavenge and allocate an instance.
+ oop result;
+
+ assert(Klass::cast(array_type)->oop_is_typeArray(), "should be called only for type array");
+ // The oopFactory likes to work with the element type.
+ BasicType elem_type = typeArrayKlass::cast(array_type)->element_type();
+ result = oopFactory::new_typeArray_nozero(elem_type, len, THREAD);
+
+ // Pass oops back through thread local storage. Our apparent type to Java
+ // is that we return an oop, but we can block on exit from this routine and
+ // a GC can trash the oop in C's return register. The generated stub will
+ // fetch the oop from TLS after any possible GC.
+ deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION);
+ thread->set_vm_result(result);
+ JRT_BLOCK_END;
+
+ if (GraphKit::use_ReduceInitialCardMarks()) {
+ // inform GC that we won't do card marks for initializing writes.
+ new_store_pre_barrier(thread);
+ }
+JRT_END
+
// Note: multianewarray for one dimension is handled inline by GraphKit::new_array.
// multianewarray for 2 dimensions
diff --git a/src/share/vm/opto/runtime.hpp b/src/share/vm/opto/runtime.hpp
index a691da307..f2c538b00 100644
--- a/src/share/vm/opto/runtime.hpp
+++ b/src/share/vm/opto/runtime.hpp
@@ -114,6 +114,7 @@ class OptoRuntime : public AllStatic {
// References to generated stubs
static address _new_instance_Java;
static address _new_array_Java;
+ static address _new_array_nozero_Java;
static address _multianewarray2_Java;
static address _multianewarray3_Java;
static address _multianewarray4_Java;
@@ -143,6 +144,7 @@ class OptoRuntime : public AllStatic {
// Allocate storage for a objArray or typeArray
static void new_array_C(klassOopDesc* array_klass, int len, JavaThread *thread);
+ static void new_array_nozero_C(klassOopDesc* array_klass, int len, JavaThread *thread);
// Post-slow-path-allocation, pre-initializing-stores step for
// implementing ReduceInitialCardMarks
@@ -208,6 +210,7 @@ private:
// access to runtime stubs entry points for java code
static address new_instance_Java() { return _new_instance_Java; }
static address new_array_Java() { return _new_array_Java; }
+ static address new_array_nozero_Java() { return _new_array_nozero_Java; }
static address multianewarray2_Java() { return _multianewarray2_Java; }
static address multianewarray3_Java() { return _multianewarray3_Java; }
static address multianewarray4_Java() { return _multianewarray4_Java; }
diff --git a/src/share/vm/prims/forte.cpp b/src/share/vm/prims/forte.cpp
index f3a08782a..d5eb0a605 100644
--- a/src/share/vm/prims/forte.cpp
+++ b/src/share/vm/prims/forte.cpp
@@ -621,6 +621,11 @@ void AsyncGetCallTrace(ASGCT_CallTrace *trace, jint depth, void* ucontext) {
// Method to let libcollector know about a dynamically loaded function.
// Because it is weakly bound, the calls become NOP's when the library
// isn't present.
+#ifdef __APPLE__
+// XXXDARWIN: Link errors occur even when __attribute__((weak_import))
+// is added
+#define collector_func_load(x0,x1,x2,x3,x4,x5,x6) (0)
+#else
void collector_func_load(char* name,
void* null_argument_1,
void* null_argument_2,
@@ -631,6 +636,7 @@ void collector_func_load(char* name,
#pragma weak collector_func_load
#define collector_func_load(x0,x1,x2,x3,x4,x5,x6) \
( collector_func_load ? collector_func_load(x0,x1,x2,x3,x4,x5,x6),0 : 0 )
+#endif // __APPLE__
#endif // !_WINDOWS
} // end extern "C"
diff --git a/src/share/vm/prims/jni.cpp b/src/share/vm/prims/jni.cpp
index 2134b3e77..4e46f6aaa 100644
--- a/src/share/vm/prims/jni.cpp
+++ b/src/share/vm/prims/jni.cpp
@@ -82,6 +82,10 @@
# include "os_windows.inline.hpp"
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "os_bsd.inline.hpp"
+# include "thread_bsd.inline.hpp"
+#endif
static jint CurrentVersion = JNI_VERSION_1_6;
diff --git a/src/share/vm/prims/jvm.cpp b/src/share/vm/prims/jvm.cpp
index 1e998e32f..37e811f37 100644
--- a/src/share/vm/prims/jvm.cpp
+++ b/src/share/vm/prims/jvm.cpp
@@ -73,6 +73,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "jvm_windows.h"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "jvm_bsd.h"
+#endif
#include <errno.h>
diff --git a/src/share/vm/prims/jvm.h b/src/share/vm/prims/jvm.h
index dc4af4752..a2036e881 100644
--- a/src/share/vm/prims/jvm.h
+++ b/src/share/vm/prims/jvm.h
@@ -35,6 +35,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "jvm_windows.h"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "jvm_bsd.h"
+#endif
#ifndef _JAVASOFT_JVM_H_
#define _JAVASOFT_JVM_H_
diff --git a/src/share/vm/prims/jvmtiEnv.cpp b/src/share/vm/prims/jvmtiEnv.cpp
index f93fdf1bd..652be9ae5 100644
--- a/src/share/vm/prims/jvmtiEnv.cpp
+++ b/src/share/vm/prims/jvmtiEnv.cpp
@@ -68,6 +68,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
diff --git a/src/share/vm/prims/jvmtiImpl.cpp b/src/share/vm/prims/jvmtiImpl.cpp
index f673e92ca..e0d809d45 100644
--- a/src/share/vm/prims/jvmtiImpl.cpp
+++ b/src/share/vm/prims/jvmtiImpl.cpp
@@ -54,6 +54,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
//
// class JvmtiAgentThread
diff --git a/src/share/vm/prims/nativeLookup.cpp b/src/share/vm/prims/nativeLookup.cpp
index af625937e..874c54dbc 100644
--- a/src/share/vm/prims/nativeLookup.cpp
+++ b/src/share/vm/prims/nativeLookup.cpp
@@ -49,6 +49,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "os_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "os_bsd.inline.hpp"
+#endif
static void mangle_name_on(outputStream* st, Symbol* name, int begin, int end) {
diff --git a/src/share/vm/runtime/arguments.cpp b/src/share/vm/runtime/arguments.cpp
index 07e31bf92..89ec60da3 100644
--- a/src/share/vm/runtime/arguments.cpp
+++ b/src/share/vm/runtime/arguments.cpp
@@ -46,6 +46,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "os_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "os_bsd.inline.hpp"
+#endif
#ifndef SERIALGC
#include "gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp"
#endif
diff --git a/src/share/vm/runtime/atomic.cpp b/src/share/vm/runtime/atomic.cpp
index 3b012e0c0..80780d780 100644
--- a/src/share/vm/runtime/atomic.cpp
+++ b/src/share/vm/runtime/atomic.cpp
@@ -33,6 +33,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "os_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "os_bsd.inline.hpp"
+#endif
#ifdef TARGET_OS_ARCH_linux_x86
# include "atomic_linux_x86.inline.hpp"
#endif
@@ -57,6 +60,12 @@
#ifdef TARGET_OS_ARCH_linux_ppc
# include "atomic_linux_ppc.inline.hpp"
#endif
+#ifdef TARGET_OS_ARCH_bsd_x86
+# include "atomic_bsd_x86.inline.hpp"
+#endif
+#ifdef TARGET_OS_ARCH_bsd_zero
+# include "atomic_bsd_zero.inline.hpp"
+#endif
jbyte Atomic::cmpxchg(jbyte exchange_value, volatile jbyte* dest, jbyte compare_value) {
assert(sizeof(jbyte) == 1, "assumption.");
diff --git a/src/share/vm/runtime/fprofiler.hpp b/src/share/vm/runtime/fprofiler.hpp
index 60e51d2eb..2f8d6158c 100644
--- a/src/share/vm/runtime/fprofiler.hpp
+++ b/src/share/vm/runtime/fprofiler.hpp
@@ -35,6 +35,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
// a simple flat profiler for Java
diff --git a/src/share/vm/runtime/globals.hpp b/src/share/vm/runtime/globals.hpp
index 68d30cf6c..e4ba36a56 100644
--- a/src/share/vm/runtime/globals.hpp
+++ b/src/share/vm/runtime/globals.hpp
@@ -50,6 +50,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "globals_windows.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "globals_bsd.hpp"
+#endif
#ifdef TARGET_OS_ARCH_linux_x86
# include "globals_linux_x86.hpp"
#endif
@@ -74,6 +77,12 @@
#ifdef TARGET_OS_ARCH_linux_ppc
# include "globals_linux_ppc.hpp"
#endif
+#ifdef TARGET_OS_ARCH_bsd_x86
+# include "globals_bsd_x86.hpp"
+#endif
+#ifdef TARGET_OS_ARCH_bsd_zero
+# include "globals_bsd_zero.hpp"
+#endif
#ifdef COMPILER1
#ifdef TARGET_ARCH_x86
# include "c1_globals_x86.hpp"
@@ -96,6 +105,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "c1_globals_windows.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "c1_globals_bsd.hpp"
+#endif
#endif
#ifdef COMPILER2
#ifdef TARGET_ARCH_x86
@@ -116,6 +128,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "c2_globals_windows.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "c2_globals_bsd.hpp"
+#endif
#endif
#ifdef SHARK
#ifdef TARGET_ARCH_zero
@@ -3506,6 +3521,9 @@ class CommandLineFlags {
"C1 with MDO profiling (tier 3) invocation notification " \
"frequency.") \
\
+ product(intx, Tier23InlineeNotifyFreqLog, 20, \
+ "Inlinee invocation (tiers 2 and 3) notification frequency") \
+ \
product(intx, Tier0BackedgeNotifyFreqLog, 10, \
"Interpreter (tier 0) invocation notification frequency.") \
\
diff --git a/src/share/vm/runtime/handles.cpp b/src/share/vm/runtime/handles.cpp
index 4a57d2681..3c24f81ce 100644
--- a/src/share/vm/runtime/handles.cpp
+++ b/src/share/vm/runtime/handles.cpp
@@ -38,6 +38,10 @@
# include "os_windows.inline.hpp"
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "os_bsd.inline.hpp"
+# include "thread_bsd.inline.hpp"
+#endif
#ifdef ASSERT
oop* HandleArea::allocate_handle(oop obj) {
diff --git a/src/share/vm/runtime/handles.inline.hpp b/src/share/vm/runtime/handles.inline.hpp
index 01060f591..3bd42fb2e 100644
--- a/src/share/vm/runtime/handles.inline.hpp
+++ b/src/share/vm/runtime/handles.inline.hpp
@@ -35,6 +35,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
// these inline functions are in a separate file to break an include cycle
// between Thread and Handle
diff --git a/src/share/vm/runtime/interfaceSupport.hpp b/src/share/vm/runtime/interfaceSupport.hpp
index b11900603..90c0db34d 100644
--- a/src/share/vm/runtime/interfaceSupport.hpp
+++ b/src/share/vm/runtime/interfaceSupport.hpp
@@ -44,6 +44,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
// Wrapper for all entry points to the virtual machine.
// The HandleMarkCleaner is a faster version of HandleMark.
@@ -115,6 +118,9 @@ class InterfaceSupport: AllStatic {
#ifdef TARGET_OS_FAMILY_windows
# include "interfaceSupport_windows.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "interfaceSupport_bsd.hpp"
+#endif
};
diff --git a/src/share/vm/runtime/java.cpp b/src/share/vm/runtime/java.cpp
index 7f37e073e..76363042c 100644
--- a/src/share/vm/runtime/java.cpp
+++ b/src/share/vm/runtime/java.cpp
@@ -85,6 +85,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
#ifndef SERIALGC
#include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp"
#include "gc_implementation/parallelScavenge/psScavenge.hpp"
diff --git a/src/share/vm/runtime/javaCalls.cpp b/src/share/vm/runtime/javaCalls.cpp
index d422c6c86..edbba9817 100644
--- a/src/share/vm/runtime/javaCalls.cpp
+++ b/src/share/vm/runtime/javaCalls.cpp
@@ -48,6 +48,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
// -----------------------------------------------------
// Implementation of JavaCallWrapper
@@ -557,4 +560,3 @@ void JavaCallArguments::verify(methodHandle method, BasicType return_type,
sc.check_doing_return(true);
sc.iterate_returntype();
}
-
diff --git a/src/share/vm/runtime/javaCalls.hpp b/src/share/vm/runtime/javaCalls.hpp
index af29462dd..d4f85956f 100644
--- a/src/share/vm/runtime/javaCalls.hpp
+++ b/src/share/vm/runtime/javaCalls.hpp
@@ -54,6 +54,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
// A JavaCallWrapper is constructed before each JavaCall and destructed after the call.
// Its purpose is to allocate/deallocate a new handle block and to save/restore the last
diff --git a/src/share/vm/runtime/javaFrameAnchor.hpp b/src/share/vm/runtime/javaFrameAnchor.hpp
index 501e59e1c..8374aa2a9 100644
--- a/src/share/vm/runtime/javaFrameAnchor.hpp
+++ b/src/share/vm/runtime/javaFrameAnchor.hpp
@@ -50,6 +50,13 @@
#ifdef TARGET_OS_ARCH_linux_ppc
# include "orderAccess_linux_ppc.inline.hpp"
#endif
+#ifdef TARGET_OS_ARCH_bsd_x86
+# include "orderAccess_bsd_x86.inline.hpp"
+#endif
+#ifdef TARGET_OS_ARCH_bsd_zero
+# include "orderAccess_bsd_zero.inline.hpp"
+#endif
+
//
// An object for encapsulating the machine/os dependent part of a JavaThread frame state
//
diff --git a/src/share/vm/runtime/jniHandles.cpp b/src/share/vm/runtime/jniHandles.cpp
index e9c791d51..3cbcaca43 100644
--- a/src/share/vm/runtime/jniHandles.cpp
+++ b/src/share/vm/runtime/jniHandles.cpp
@@ -37,6 +37,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
JNIHandleBlock* JNIHandles::_global_handles = NULL;
diff --git a/src/share/vm/runtime/memprofiler.cpp b/src/share/vm/runtime/memprofiler.cpp
index cf49dd3c2..ab53d9218 100644
--- a/src/share/vm/runtime/memprofiler.cpp
+++ b/src/share/vm/runtime/memprofiler.cpp
@@ -46,6 +46,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
#ifndef PRODUCT
diff --git a/src/share/vm/runtime/mutex.cpp b/src/share/vm/runtime/mutex.cpp
index 634ec43c6..80d3d8742 100644
--- a/src/share/vm/runtime/mutex.cpp
+++ b/src/share/vm/runtime/mutex.cpp
@@ -39,6 +39,10 @@
# include "mutex_windows.inline.hpp"
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "mutex_bsd.inline.hpp"
+# include "thread_bsd.inline.hpp"
+#endif
// o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o
//
diff --git a/src/share/vm/runtime/mutexLocker.cpp b/src/share/vm/runtime/mutexLocker.cpp
index b3d082f88..7653b5bef 100644
--- a/src/share/vm/runtime/mutexLocker.cpp
+++ b/src/share/vm/runtime/mutexLocker.cpp
@@ -36,6 +36,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
// Mutexes used in the VM (see comment in mutexLocker.hpp):
//
diff --git a/src/share/vm/runtime/mutexLocker.hpp b/src/share/vm/runtime/mutexLocker.hpp
index 58060b828..37a3d3132 100644
--- a/src/share/vm/runtime/mutexLocker.hpp
+++ b/src/share/vm/runtime/mutexLocker.hpp
@@ -36,6 +36,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "os_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "os_bsd.inline.hpp"
+#endif
// Mutexes used in the VM.
diff --git a/src/share/vm/runtime/objectMonitor.cpp b/src/share/vm/runtime/objectMonitor.cpp
index e2b4bf2d7..3fa0e3284 100644
--- a/src/share/vm/runtime/objectMonitor.cpp
+++ b/src/share/vm/runtime/objectMonitor.cpp
@@ -50,6 +50,10 @@
# include "os_windows.inline.hpp"
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "os_bsd.inline.hpp"
+# include "thread_bsd.inline.hpp"
+#endif
#if defined(__GNUC__) && !defined(IA64)
// Need to inhibit inlining for older versions of GCC to avoid build-time failures
diff --git a/src/share/vm/runtime/os.cpp b/src/share/vm/runtime/os.cpp
index 40ea17530..8c1eaade9 100644
--- a/src/share/vm/runtime/os.cpp
+++ b/src/share/vm/runtime/os.cpp
@@ -60,6 +60,10 @@
# include "os_windows.inline.hpp"
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "os_bsd.inline.hpp"
+# include "thread_bsd.inline.hpp"
+#endif
# include <signal.h>
@@ -116,7 +120,11 @@ char* os::iso8601_time(char* buffer, size_t buffer_length) {
assert(false, "Failed localtime_pd");
return NULL;
}
+#if defined(_ALLBSD_SOURCE)
+ const time_t zone = (time_t) time_struct.tm_gmtoff;
+#else
const time_t zone = timezone;
+#endif
// If daylight savings time is in effect,
// we are 1 hour East of our time zone
@@ -384,6 +392,13 @@ void* os::native_java_library() {
if (_native_java_library == NULL) {
vm_exit_during_initialization("Unable to load native library", ebuf);
}
+
+#if defined(__OpenBSD__)
+ // Work-around OpenBSD's lack of $ORIGIN support by pre-loading libnet.so
+ // ignore errors
+ dll_build_name(buffer, sizeof(buffer), Arguments::get_dll_dir(), "net");
+ dll_load(buffer, ebuf, sizeof(ebuf));
+#endif
}
static jboolean onLoaded = JNI_FALSE;
if (onLoaded) {
diff --git a/src/share/vm/runtime/os.hpp b/src/share/vm/runtime/os.hpp
index b43100d1f..f92d92df5 100644
--- a/src/share/vm/runtime/os.hpp
+++ b/src/share/vm/runtime/os.hpp
@@ -39,6 +39,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "jvm_windows.h"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "jvm_bsd.h"
+#endif
// os defines the interface to operating system; this includes traditional
// OS services (time, I/O) as well as other functionality with system-
@@ -675,6 +678,9 @@ class os: AllStatic {
#ifdef TARGET_OS_FAMILY_windows
# include "os_windows.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "os_bsd.hpp"
+#endif
#ifdef TARGET_OS_ARCH_linux_x86
# include "os_linux_x86.hpp"
#endif
@@ -699,6 +705,12 @@ class os: AllStatic {
#ifdef TARGET_OS_ARCH_linux_ppc
# include "os_linux_ppc.hpp"
#endif
+#ifdef TARGET_OS_ARCH_bsd_x86
+# include "os_bsd_x86.hpp"
+#endif
+#ifdef TARGET_OS_ARCH_bsd_zero
+# include "os_bsd_zero.hpp"
+#endif
// debugging support (mostly used by debug.cpp but also fatal error handler)
diff --git a/src/share/vm/runtime/osThread.hpp b/src/share/vm/runtime/osThread.hpp
index 5df645ad8..984bc9b49 100644
--- a/src/share/vm/runtime/osThread.hpp
+++ b/src/share/vm/runtime/osThread.hpp
@@ -109,6 +109,9 @@ class OSThread: public CHeapObj {
#ifdef TARGET_OS_FAMILY_windows
# include "osThread_windows.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "osThread_bsd.hpp"
+#endif
};
diff --git a/src/share/vm/runtime/safepoint.cpp b/src/share/vm/runtime/safepoint.cpp
index bef8d6c50..d33893120 100644
--- a/src/share/vm/runtime/safepoint.cpp
+++ b/src/share/vm/runtime/safepoint.cpp
@@ -78,6 +78,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
#ifndef SERIALGC
#include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp"
#include "gc_implementation/shared/concurrentGCThread.hpp"
diff --git a/src/share/vm/runtime/synchronizer.cpp b/src/share/vm/runtime/synchronizer.cpp
index d51be5c2b..09bbc1db8 100644
--- a/src/share/vm/runtime/synchronizer.cpp
+++ b/src/share/vm/runtime/synchronizer.cpp
@@ -51,6 +51,10 @@
# include "os_windows.inline.hpp"
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "os_bsd.inline.hpp"
+# include "thread_bsd.inline.hpp"
+#endif
#if defined(__GNUC__) && !defined(IA64)
// Need to inhibit inlining for older versions of GCC to avoid build-time failures
diff --git a/src/share/vm/runtime/task.cpp b/src/share/vm/runtime/task.cpp
index 4c0cff75f..bd45d65fe 100644
--- a/src/share/vm/runtime/task.cpp
+++ b/src/share/vm/runtime/task.cpp
@@ -39,6 +39,10 @@
# include "os_windows.inline.hpp"
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "os_bsd.inline.hpp"
+# include "thread_bsd.inline.hpp"
+#endif
int PeriodicTask::_num_tasks = 0;
PeriodicTask* PeriodicTask::_tasks[PeriodicTask::max_tasks];
diff --git a/src/share/vm/runtime/thread.cpp b/src/share/vm/runtime/thread.cpp
index 5b5138e83..bc70cd326 100644
--- a/src/share/vm/runtime/thread.cpp
+++ b/src/share/vm/runtime/thread.cpp
@@ -89,6 +89,10 @@
# include "os_windows.inline.hpp"
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "os_bsd.inline.hpp"
+# include "thread_bsd.inline.hpp"
+#endif
#ifndef SERIALGC
#include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp"
#include "gc_implementation/g1/concurrentMarkThread.inline.hpp"
diff --git a/src/share/vm/runtime/thread.hpp b/src/share/vm/runtime/thread.hpp
index 4d5478bdc..d507ebd2a 100644
--- a/src/share/vm/runtime/thread.hpp
+++ b/src/share/vm/runtime/thread.hpp
@@ -1607,6 +1607,12 @@ public:
#ifdef TARGET_OS_ARCH_linux_ppc
# include "thread_linux_ppc.hpp"
#endif
+#ifdef TARGET_OS_ARCH_bsd_x86
+# include "thread_bsd_x86.hpp"
+#endif
+#ifdef TARGET_OS_ARCH_bsd_zero
+# include "thread_bsd_zero.hpp"
+#endif
public:
diff --git a/src/share/vm/runtime/threadLocalStorage.cpp b/src/share/vm/runtime/threadLocalStorage.cpp
index 0b35cdad3..0cdc48a0a 100644
--- a/src/share/vm/runtime/threadLocalStorage.cpp
+++ b/src/share/vm/runtime/threadLocalStorage.cpp
@@ -36,6 +36,10 @@
# include "os_windows.inline.hpp"
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "os_bsd.inline.hpp"
+# include "thread_bsd.inline.hpp"
+#endif
// static member initialization
int ThreadLocalStorage::_thread_index = -1;
diff --git a/src/share/vm/runtime/threadLocalStorage.hpp b/src/share/vm/runtime/threadLocalStorage.hpp
index c93621687..c2f7a9e4c 100644
--- a/src/share/vm/runtime/threadLocalStorage.hpp
+++ b/src/share/vm/runtime/threadLocalStorage.hpp
@@ -68,6 +68,12 @@ class ThreadLocalStorage : AllStatic {
#ifdef TARGET_OS_ARCH_linux_ppc
# include "threadLS_linux_ppc.hpp"
#endif
+#ifdef TARGET_OS_ARCH_bsd_x86
+# include "threadLS_bsd_x86.hpp"
+#endif
+#ifdef TARGET_OS_ARCH_bsd_zero
+# include "threadLS_bsd_zero.hpp"
+#endif
public:
diff --git a/src/share/vm/runtime/timer.cpp b/src/share/vm/runtime/timer.cpp
index 8e6bbbef9..ea0553348 100644
--- a/src/share/vm/runtime/timer.cpp
+++ b/src/share/vm/runtime/timer.cpp
@@ -35,6 +35,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "os_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "os_bsd.inline.hpp"
+#endif
void elapsedTimer::add(elapsedTimer t) {
diff --git a/src/share/vm/runtime/virtualspace.cpp b/src/share/vm/runtime/virtualspace.cpp
index f290cf3bc..5eeb1ee93 100644
--- a/src/share/vm/runtime/virtualspace.cpp
+++ b/src/share/vm/runtime/virtualspace.cpp
@@ -35,6 +35,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "os_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "os_bsd.inline.hpp"
+#endif
// ReservedSpace
diff --git a/src/share/vm/runtime/vmStructs.cpp b/src/share/vm/runtime/vmStructs.cpp
index 101d6f92f..0ce636f8e 100644
--- a/src/share/vm/runtime/vmStructs.cpp
+++ b/src/share/vm/runtime/vmStructs.cpp
@@ -133,6 +133,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
#ifdef TARGET_OS_ARCH_linux_x86
# include "vmStructs_linux_x86.hpp"
#endif
@@ -157,6 +160,12 @@
#ifdef TARGET_OS_ARCH_linux_ppc
# include "vmStructs_linux_ppc.hpp"
#endif
+#ifdef TARGET_OS_ARCH_bsd_x86
+# include "vmStructs_bsd_x86.hpp"
+#endif
+#ifdef TARGET_OS_ARCH_bsd_zero
+# include "vmStructs_bsd_zero.hpp"
+#endif
#ifndef SERIALGC
#include "gc_implementation/concurrentMarkSweep/cmsPermGen.hpp"
#include "gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp"
@@ -694,6 +703,12 @@ static inline uint64_t cast_uint64_t(size_t x)
static_field(SystemDictionary, _box_klasses[0], klassOop) \
static_field(SystemDictionary, _java_system_loader, oop) \
\
+ /*************/ \
+ /* vmSymbols */ \
+ /*************/ \
+ \
+ static_field(vmSymbols, _symbols[0], Symbol*) \
+ \
/*******************/ \
/* HashtableBucket */ \
/*******************/ \
@@ -1539,6 +1554,7 @@ static inline uint64_t cast_uint64_t(size_t x)
declare_type(LoaderConstraintEntry, HashtableEntry<klassOop>) \
declare_toplevel_type(HashtableBucket) \
declare_toplevel_type(SystemDictionary) \
+ declare_toplevel_type(vmSymbols) \
declare_toplevel_type(ProtectionDomainEntry) \
\
declare_toplevel_type(GenericGrowableArray) \
@@ -2521,6 +2537,13 @@ static inline uint64_t cast_uint64_t(size_t x)
X86_ONLY(declare_constant(frame::entry_frame_call_wrapper_offset)) \
declare_constant(frame::pc_return_offset) \
\
+ /*************/ \
+ /* vmSymbols */ \
+ /*************/ \
+ \
+ declare_constant(vmSymbols::FIRST_SID) \
+ declare_constant(vmSymbols::SID_LIMIT) \
+ \
/********************************/ \
/* Calling convention constants */ \
/********************************/ \
diff --git a/src/share/vm/runtime/vmThread.cpp b/src/share/vm/runtime/vmThread.cpp
index c50e0a1d7..0013444a9 100644
--- a/src/share/vm/runtime/vmThread.cpp
+++ b/src/share/vm/runtime/vmThread.cpp
@@ -46,6 +46,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
HS_DTRACE_PROBE_DECL3(hotspot, vmops__request, char *, uintptr_t, int);
HS_DTRACE_PROBE_DECL3(hotspot, vmops__begin, char *, uintptr_t, int);
diff --git a/src/share/vm/runtime/vmThread.hpp b/src/share/vm/runtime/vmThread.hpp
index 6698b1275..f78449676 100644
--- a/src/share/vm/runtime/vmThread.hpp
+++ b/src/share/vm/runtime/vmThread.hpp
@@ -36,6 +36,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
//
// Prioritized queue of VM operations.
diff --git a/src/share/vm/runtime/vm_operations.cpp b/src/share/vm/runtime/vm_operations.cpp
index cb5d13814..b010b9acb 100644
--- a/src/share/vm/runtime/vm_operations.cpp
+++ b/src/share/vm/runtime/vm_operations.cpp
@@ -45,6 +45,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
#define VM_OP_NAME_INITIALIZE(name) #name,
diff --git a/src/share/vm/runtime/vm_version.cpp b/src/share/vm/runtime/vm_version.cpp
index 524ec49c8..2a7e91487 100644
--- a/src/share/vm/runtime/vm_version.cpp
+++ b/src/share/vm/runtime/vm_version.cpp
@@ -167,7 +167,8 @@ const char* Abstract_VM_Version::vm_release() {
#define OS LINUX_ONLY("linux") \
WINDOWS_ONLY("windows") \
- SOLARIS_ONLY("solaris")
+ SOLARIS_ONLY("solaris") \
+ BSD_ONLY("bsd")
#ifdef ZERO
#define CPU ZERO_LIBARCH
diff --git a/src/share/vm/utilities/accessFlags.cpp b/src/share/vm/utilities/accessFlags.cpp
index f244d0f8a..0c6ea1b9f 100644
--- a/src/share/vm/utilities/accessFlags.cpp
+++ b/src/share/vm/utilities/accessFlags.cpp
@@ -34,6 +34,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "os_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "os_bsd.inline.hpp"
+#endif
void AccessFlags::atomic_set_bits(jint bits) {
diff --git a/src/share/vm/utilities/array.cpp b/src/share/vm/utilities/array.cpp
index ffea39447..44782ea89 100644
--- a/src/share/vm/utilities/array.cpp
+++ b/src/share/vm/utilities/array.cpp
@@ -34,6 +34,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
#ifdef ASSERT
diff --git a/src/share/vm/utilities/bitMap.cpp b/src/share/vm/utilities/bitMap.cpp
index b7c82eece..17231d355 100644
--- a/src/share/vm/utilities/bitMap.cpp
+++ b/src/share/vm/utilities/bitMap.cpp
@@ -35,6 +35,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "os_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "os_bsd.inline.hpp"
+#endif
BitMap::BitMap(bm_word_t* map, idx_t size_in_bits) :
diff --git a/src/share/vm/utilities/debug.cpp b/src/share/vm/utilities/debug.cpp
index 27eaea8b4..5a6869172 100644
--- a/src/share/vm/utilities/debug.cpp
+++ b/src/share/vm/utilities/debug.cpp
@@ -62,6 +62,10 @@
# include "os_windows.inline.hpp"
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "os_bsd.inline.hpp"
+# include "thread_bsd.inline.hpp"
+#endif
#ifndef ASSERT
# ifdef _DEBUG
diff --git a/src/share/vm/utilities/decoder.cpp b/src/share/vm/utilities/decoder.cpp
index 032a8c27d..ed156de23 100644
--- a/src/share/vm/utilities/decoder.cpp
+++ b/src/share/vm/utilities/decoder.cpp
@@ -29,7 +29,7 @@
Decoder::decoder_status Decoder::_decoder_status = Decoder::no_error;
bool Decoder::_initialized = false;
-#ifndef _WINDOWS
+#if !defined(_WINDOWS) && !defined(__APPLE__)
// Implementation of common functionalities among Solaris and Linux
#include "utilities/elfFile.hpp"
@@ -101,4 +101,3 @@ ElfFile* Decoder::get_elf_file(const char* filepath) {
}
#endif
-
diff --git a/src/share/vm/utilities/decoder.hpp b/src/share/vm/utilities/decoder.hpp
index ade0fc273..70ffe2197 100644
--- a/src/share/vm/utilities/decoder.hpp
+++ b/src/share/vm/utilities/decoder.hpp
@@ -38,6 +38,8 @@ typedef BOOL (WINAPI *pfn_SymInitialize)(HANDLE, PCTSTR, BOOL);
typedef BOOL (WINAPI *pfn_SymGetSymFromAddr64)(HANDLE, DWORD64, PDWORD64, PIMAGEHLP_SYMBOL64);
typedef DWORD (WINAPI *pfn_UndecorateSymbolName)(const char*, char*, DWORD, DWORD);
+#elif defined(__APPLE__)
+
#else
class ElfFile;
@@ -79,7 +81,7 @@ class Decoder: public StackObj {
static decoder_status get_status() { return _decoder_status; };
-#ifndef _WINDOWS
+#if !defined(_WINDOWS) && !defined(__APPLE__)
private:
static ElfFile* get_elf_file(const char* filepath);
#endif // _WINDOWS
@@ -94,6 +96,7 @@ class Decoder: public StackObj {
static bool _can_decode_in_vm;
static pfn_SymGetSymFromAddr64 _pfnSymGetSymFromAddr64;
static pfn_UndecorateSymbolName _pfnUndecorateSymbolName;
+#elif __APPLE__
#else
static ElfFile* _opened_elf_files;
#endif // _WINDOWS
diff --git a/src/share/vm/utilities/elfFile.cpp b/src/share/vm/utilities/elfFile.cpp
index 4614b9427..2db1f71e0 100644
--- a/src/share/vm/utilities/elfFile.cpp
+++ b/src/share/vm/utilities/elfFile.cpp
@@ -24,7 +24,7 @@
#include "precompiled.hpp"
-#ifndef _WINDOWS
+#if !defined(_WINDOWS) && !defined(__APPLE__)
#include <string.h>
#include <stdio.h>
diff --git a/src/share/vm/utilities/elfFile.hpp b/src/share/vm/utilities/elfFile.hpp
index 0a1f965d0..b40b90ae6 100644
--- a/src/share/vm/utilities/elfFile.hpp
+++ b/src/share/vm/utilities/elfFile.hpp
@@ -25,9 +25,13 @@
#ifndef __ELF_FILE_HPP
#define __ELF_FILE_HPP
-#ifndef _WINDOWS
+#if !defined(_WINDOWS) && !defined(__APPLE__)
+#if defined(__OpenBSD__)
+#include <sys/exec_elf.h>
+#else
#include <elf.h>
+#endif
#include <stdio.h>
#ifdef _LP64
@@ -41,7 +45,9 @@ typedef Elf64_Ehdr Elf_Ehdr;
typedef Elf64_Shdr Elf_Shdr;
typedef Elf64_Sym Elf_Sym;
+#if !defined(_ALLBSD_SOURCE) || defined(__APPLE__)
#define ELF_ST_TYPE ELF64_ST_TYPE
+#endif
#else
@@ -55,8 +61,10 @@ typedef Elf32_Ehdr Elf_Ehdr;
typedef Elf32_Shdr Elf_Shdr;
typedef Elf32_Sym Elf_Sym;
+#if !defined(_ALLBSD_SOURCE) || defined(__APPLE__)
#define ELF_ST_TYPE ELF32_ST_TYPE
#endif
+#endif
#include "globalDefinitions.hpp"
#include "memory/allocation.hpp"
@@ -137,4 +145,3 @@ class ElfFile: public CHeapObj {
#endif // _WINDOWS
#endif // __ELF_FILE_HPP
-
diff --git a/src/share/vm/utilities/elfStringTable.cpp b/src/share/vm/utilities/elfStringTable.cpp
index 994b80a3e..905f82bfe 100644
--- a/src/share/vm/utilities/elfStringTable.cpp
+++ b/src/share/vm/utilities/elfStringTable.cpp
@@ -24,7 +24,7 @@
#include "precompiled.hpp"
-#ifndef _WINDOWS
+#if !defined(_WINDOWS) && !defined(__APPLE__)
#include "memory/allocation.inline.hpp"
#include "runtime/os.hpp"
@@ -87,4 +87,3 @@ const char* ElfStringTable::string_at(int pos) {
}
#endif // _WINDOWS
-
diff --git a/src/share/vm/utilities/elfStringTable.hpp b/src/share/vm/utilities/elfStringTable.hpp
index bfafa1a7d..a984e3a33 100644
--- a/src/share/vm/utilities/elfStringTable.hpp
+++ b/src/share/vm/utilities/elfStringTable.hpp
@@ -25,7 +25,7 @@
#ifndef __ELF_STRING_TABLE_HPP
#define __ELF_STRING_TABLE_HPP
-#ifndef _WINDOWS
+#if !defined(_WINDOWS) && !defined(__APPLE__)
#include "memory/allocation.hpp"
#include "utilities/decoder.hpp"
@@ -79,4 +79,3 @@ class ElfStringTable: CHeapObj {
#endif // _WINDOWS
#endif // __ELF_STRING_TABLE_HPP
-
diff --git a/src/share/vm/utilities/elfSymbolTable.cpp b/src/share/vm/utilities/elfSymbolTable.cpp
index 0fa039c4f..d1606010d 100644
--- a/src/share/vm/utilities/elfSymbolTable.cpp
+++ b/src/share/vm/utilities/elfSymbolTable.cpp
@@ -24,7 +24,7 @@
#include "precompiled.hpp"
-#ifndef _WINDOWS
+#if !defined(_WINDOWS) && !defined(__APPLE__)
#include "memory/allocation.inline.hpp"
#include "utilities/elfSymbolTable.hpp"
diff --git a/src/share/vm/utilities/elfSymbolTable.hpp b/src/share/vm/utilities/elfSymbolTable.hpp
index 5ac1c4aad..c8a11fca2 100644
--- a/src/share/vm/utilities/elfSymbolTable.hpp
+++ b/src/share/vm/utilities/elfSymbolTable.hpp
@@ -25,7 +25,7 @@
#ifndef __ELF_SYMBOL_TABLE_HPP
#define __ELF_SYMBOL_TABLE_HPP
-#ifndef _WINDOWS
+#if !defined(_WINDOWS) && !defined(__APPLE__)
#include "memory/allocation.hpp"
@@ -68,6 +68,3 @@ class ElfSymbolTable: public CHeapObj {
#endif // _WINDOWS
#endif // __ELF_SYMBOL_TABLE_HPP
-
-
-
diff --git a/src/share/vm/utilities/events.cpp b/src/share/vm/utilities/events.cpp
index 24e4eb470..62341195d 100644
--- a/src/share/vm/utilities/events.cpp
+++ b/src/share/vm/utilities/events.cpp
@@ -38,6 +38,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
#ifndef PRODUCT
diff --git a/src/share/vm/utilities/exceptions.cpp b/src/share/vm/utilities/exceptions.cpp
index 3d2f3cfea..91960278b 100644
--- a/src/share/vm/utilities/exceptions.cpp
+++ b/src/share/vm/utilities/exceptions.cpp
@@ -42,6 +42,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
// Implementation of ThreadShadow
diff --git a/src/share/vm/utilities/globalDefinitions.hpp b/src/share/vm/utilities/globalDefinitions.hpp
index 8607a3e03..5bacab9f2 100644
--- a/src/share/vm/utilities/globalDefinitions.hpp
+++ b/src/share/vm/utilities/globalDefinitions.hpp
@@ -25,6 +25,8 @@
#ifndef SHARE_VM_UTILITIES_GLOBALDEFINITIONS_HPP
#define SHARE_VM_UTILITIES_GLOBALDEFINITIONS_HPP
+#define __STDC_FORMAT_MACROS
+
#ifdef TARGET_COMPILER_gcc
# include "utilities/globalDefinitions_gcc.hpp"
#endif
@@ -1178,67 +1180,47 @@ inline int build_int_from_shorts( jushort low, jushort high ) {
}
// Printf-style formatters for fixed- and variable-width types as pointers and
-// integers.
-//
-// Each compiler-specific definitions file (e.g., globalDefinitions_gcc.hpp)
-// must define the macro FORMAT64_MODIFIER, which is the modifier for '%x' or
-// '%d' formats to indicate a 64-bit quantity; commonly "l" (in LP64) or "ll"
-// (in ILP32).
+// integers. These are derived from the definitions in inttypes.h. If the platform
+// doesn't provide appropriate definitions, they should be provided in
+// the compiler-specific definitions file (e.g., globalDefinitions_gcc.hpp)
#define BOOL_TO_STR(_b_) ((_b_) ? "true" : "false")
// Format 32-bit quantities.
-#define INT32_FORMAT "%d"
-#define UINT32_FORMAT "%u"
-#define INT32_FORMAT_W(width) "%" #width "d"
-#define UINT32_FORMAT_W(width) "%" #width "u"
+#define INT32_FORMAT "%" PRId32
+#define UINT32_FORMAT "%" PRIu32
+#define INT32_FORMAT_W(width) "%" #width PRId32
+#define UINT32_FORMAT_W(width) "%" #width PRIu32
-#define PTR32_FORMAT "0x%08x"
+#define PTR32_FORMAT "0x%08" PRIx32
// Format 64-bit quantities.
-#define INT64_FORMAT "%" FORMAT64_MODIFIER "d"
-#define UINT64_FORMAT "%" FORMAT64_MODIFIER "u"
-#define PTR64_FORMAT "0x%016" FORMAT64_MODIFIER "x"
+#define INT64_FORMAT "%" PRId64
+#define UINT64_FORMAT "%" PRIu64
+#define INT64_FORMAT_W(width) "%" #width PRId64
+#define UINT64_FORMAT_W(width) "%" #width PRIu64
-#define INT64_FORMAT_W(width) "%" #width FORMAT64_MODIFIER "d"
-#define UINT64_FORMAT_W(width) "%" #width FORMAT64_MODIFIER "u"
+#define PTR64_FORMAT "0x%016" PRIx64
-// Format macros that allow the field width to be specified. The width must be
-// a string literal (e.g., "8") or a macro that evaluates to one.
-#ifdef _LP64
-#define UINTX_FORMAT_W(width) UINT64_FORMAT_W(width)
-#define SSIZE_FORMAT_W(width) INT64_FORMAT_W(width)
-#define SIZE_FORMAT_W(width) UINT64_FORMAT_W(width)
-#else
-#define UINTX_FORMAT_W(width) UINT32_FORMAT_W(width)
-#define SSIZE_FORMAT_W(width) INT32_FORMAT_W(width)
-#define SIZE_FORMAT_W(width) UINT32_FORMAT_W(width)
-#endif // _LP64
-
-// Format pointers and size_t (or size_t-like integer types) which change size
-// between 32- and 64-bit. The pointer format theoretically should be "%p",
-// however, it has different output on different platforms. On Windows, the data
-// will be padded with zeros automatically. On Solaris, we can use "%016p" &
-// "%08p" on 64 bit & 32 bit platforms to make the data padded with extra zeros.
-// On Linux, "%016p" or "%08p" is not be allowed, at least on the latest GCC
-// 4.3.2. So we have to use "%016x" or "%08x" to simulate the printing format.
-// GCC 4.3.2, however requires the data to be converted to "intptr_t" when
-// using "%x".
+// Format pointers which change size between 32- and 64-bit.
#ifdef _LP64
-#define PTR_FORMAT PTR64_FORMAT
-#define UINTX_FORMAT UINT64_FORMAT
-#define INTX_FORMAT INT64_FORMAT
-#define SIZE_FORMAT UINT64_FORMAT
-#define SSIZE_FORMAT INT64_FORMAT
+#define INTPTR_FORMAT "0x%016" PRIxPTR
+#define PTR_FORMAT "0x%016" PRIxPTR
#else // !_LP64
-#define PTR_FORMAT PTR32_FORMAT
-#define UINTX_FORMAT UINT32_FORMAT
-#define INTX_FORMAT INT32_FORMAT
-#define SIZE_FORMAT UINT32_FORMAT
-#define SSIZE_FORMAT INT32_FORMAT
+#define INTPTR_FORMAT "0x%08" PRIxPTR
+#define PTR_FORMAT "0x%08" PRIxPTR
#endif // _LP64
-#define INTPTR_FORMAT PTR_FORMAT
+#define SSIZE_FORMAT "%" PRIdPTR
+#define SIZE_FORMAT "%" PRIuPTR
+#define SSIZE_FORMAT_W(width) "%" #width PRIdPTR
+#define SIZE_FORMAT_W(width) "%" #width PRIuPTR
+
+#define INTX_FORMAT "%" PRIdPTR
+#define UINTX_FORMAT "%" PRIuPTR
+#define INTX_FORMAT_W(width) "%" #width PRIdPTR
+#define UINTX_FORMAT_W(width) "%" #width PRIuPTR
+
// Enable zap-a-lot if in debug version.
diff --git a/src/share/vm/utilities/globalDefinitions_gcc.hpp b/src/share/vm/utilities/globalDefinitions_gcc.hpp
index ac7fdf878..45b5e8fff 100644
--- a/src/share/vm/utilities/globalDefinitions_gcc.hpp
+++ b/src/share/vm/utilities/globalDefinitions_gcc.hpp
@@ -76,15 +76,28 @@
# include <sys/procfs.h>
# endif
-#ifdef LINUX
+#if defined(LINUX) || defined(_ALLBSD_SOURCE)
#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS
#endif // __STDC_LIMIT_MACROS
#include <inttypes.h>
#include <signal.h>
+#ifndef __OpenBSD__
#include <ucontext.h>
+#endif
+#ifdef __APPLE__
+ #include <AvailabilityMacros.h>
+ #if (MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4)
+ // Mac OS X 10.4 defines EFL_AC and EFL_ID,
+ // which conflict with hotspot variable names.
+ //
+ // This has been fixed in Mac OS X 10.5.
+ #undef EFL_AC
+ #undef EFL_ID
+ #endif
+#endif
#include <sys/time.h>
-#endif // LINUX
+#endif // LINUX || _ALLBSD_SOURCE
// 4810578: varargs unsafe on 32-bit integer/64-bit pointer architectures
// When __cplusplus is defined, NULL is defined as 0 (32-bit constant) in
@@ -120,7 +133,7 @@
// pointer is stored as integer value. On some platforms, sizeof(intptr_t) >
// sizeof(void*), so here we want something which is integer type, but has the
// same size as a pointer.
-#ifdef LINUX
+#ifdef __GNUC__
#ifdef _LP64
#define NULL_WORD 0L
#else
@@ -132,7 +145,7 @@
#define NULL_WORD NULL
#endif
-#ifndef LINUX
+#if !defined(LINUX) && !defined(_ALLBSD_SOURCE)
// Compiler-specific primitive types
typedef unsigned short uint16_t;
#ifndef _UINT32_T
@@ -152,7 +165,7 @@ typedef unsigned int uintptr_t;
// prior definition of intptr_t, and add "&& !defined(XXX)" above.
#endif // _SYS_INT_TYPES_H
-#endif // !LINUX
+#endif // !LINUX && !_ALLBSD_SOURCE
// Additional Java basic types
@@ -244,7 +257,9 @@ inline int g_isnan(float f) { return isnanf(f); }
inline int g_isnan(float f) { return isnand(f); }
#endif
inline int g_isnan(double f) { return isnand(f); }
-#elif LINUX
+#elif defined(__APPLE__)
+inline int g_isnan(double f) { return isnan(f); }
+#elif defined(LINUX) || defined(_ALLBSD_SOURCE)
inline int g_isnan(float f) { return isnanf(f); }
inline int g_isnan(double f) { return isnan(f); }
#else
diff --git a/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp b/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp
index fca43e0d7..e91e60780 100644
--- a/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp
+++ b/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp
@@ -74,8 +74,25 @@
# ifdef SOLARIS_MUTATOR_LIBTHREAD
# include <sys/procfs.h>
# endif
+
+#include <inttypes.h>
+
+// Solaris 8 doesn't provide definitions of these
+#ifdef SOLARIS
+#ifndef PRIdPTR
+#if defined(_LP64)
+#define PRIdPTR "ld"
+#define PRIuPTR "lu"
+#define PRIxPTR "lx"
+#else
+#define PRIdPTR "d"
+#define PRIuPTR "u"
+#define PRIxPTR "x"
+#endif
+#endif
+#endif
+
#ifdef LINUX
-# include <inttypes.h>
# include <signal.h>
# include <ucontext.h>
# include <sys/time.h>
diff --git a/src/share/vm/utilities/globalDefinitions_visCPP.hpp b/src/share/vm/utilities/globalDefinitions_visCPP.hpp
index 36549993a..ba54d2290 100644
--- a/src/share/vm/utilities/globalDefinitions_visCPP.hpp
+++ b/src/share/vm/utilities/globalDefinitions_visCPP.hpp
@@ -207,6 +207,20 @@ inline int vsnprintf(char* buf, size_t count, const char* fmt, va_list argptr) {
// Formatting.
#define FORMAT64_MODIFIER "I64"
+// Visual Studio doesn't provide inttypes.h so provide appropriate definitions here.
+// The 32 bits ones might need I32 but seem to work ok without it.
+#define PRId32 "d"
+#define PRIu32 "u"
+#define PRIx32 "x"
+
+#define PRId64 "I64d"
+#define PRIu64 "I64u"
+#define PRIx64 "I64x"
+
+#define PRIdPTR "d"
+#define PRIuPTR "u"
+#define PRIxPTR "x"
+
#define offset_of(klass,field) offsetof(klass,field)
#endif // SHARE_VM_UTILITIES_GLOBALDEFINITIONS_VISCPP_HPP
diff --git a/src/share/vm/utilities/growableArray.cpp b/src/share/vm/utilities/growableArray.cpp
index 00378afce..a6ad8f305 100644
--- a/src/share/vm/utilities/growableArray.cpp
+++ b/src/share/vm/utilities/growableArray.cpp
@@ -34,6 +34,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
#ifdef ASSERT
void GenericGrowableArray::set_nesting() {
if (on_stack()) {
diff --git a/src/share/vm/utilities/histogram.hpp b/src/share/vm/utilities/histogram.hpp
index 9627a07fe..4eaa3d4e2 100644
--- a/src/share/vm/utilities/histogram.hpp
+++ b/src/share/vm/utilities/histogram.hpp
@@ -37,6 +37,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "os_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "os_bsd.inline.hpp"
+#endif
// This class provides a framework for collecting various statistics.
// The current implementation is oriented towards counting invocations
diff --git a/src/share/vm/utilities/macros.hpp b/src/share/vm/utilities/macros.hpp
index 8c8b0f345..27e2a7037 100644
--- a/src/share/vm/utilities/macros.hpp
+++ b/src/share/vm/utilities/macros.hpp
@@ -161,6 +161,14 @@
#define NOT_WINDOWS(code) code
#endif
+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
+#define BSD_ONLY(code) code
+#define NOT_BSD(code)
+#else
+#define BSD_ONLY(code)
+#define NOT_BSD(code) code
+#endif
+
#ifdef _WIN64
#define WIN64_ONLY(code) code
#define NOT_WIN64(code)
diff --git a/src/share/vm/utilities/ostream.cpp b/src/share/vm/utilities/ostream.cpp
index 1e54ba20c..60660002e 100644
--- a/src/share/vm/utilities/ostream.cpp
+++ b/src/share/vm/utilities/ostream.cpp
@@ -39,6 +39,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "os_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "os_bsd.inline.hpp"
+#endif
extern "C" void jio_print(const char* s); // Declarationtion of jvm method
@@ -992,7 +995,7 @@ bufferedStream::~bufferedStream() {
#ifndef PRODUCT
-#if defined(SOLARIS) || defined(LINUX)
+#if defined(SOLARIS) || defined(LINUX) || defined(_ALLBSD_SOURCE)
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
diff --git a/src/share/vm/utilities/preserveException.hpp b/src/share/vm/utilities/preserveException.hpp
index d0e25ae8b..7737a3761 100644
--- a/src/share/vm/utilities/preserveException.hpp
+++ b/src/share/vm/utilities/preserveException.hpp
@@ -35,6 +35,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
// This file provides more support for exception handling; see also exceptions.hpp
class PreserveExceptionMark {
diff --git a/src/share/vm/utilities/taskqueue.cpp b/src/share/vm/utilities/taskqueue.cpp
index 5f93dc0fe..df61a559e 100644
--- a/src/share/vm/utilities/taskqueue.cpp
+++ b/src/share/vm/utilities/taskqueue.cpp
@@ -37,6 +37,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
#ifdef TRACESPINNING
uint ParallelTaskTerminator::_total_yields = 0;
@@ -274,4 +277,3 @@ void ParallelTaskTerminator::reset_for_reuse(int n_threads) {
reset_for_reuse();
_n_threads = n_threads;
}
-
diff --git a/src/share/vm/utilities/taskqueue.hpp b/src/share/vm/utilities/taskqueue.hpp
index 5527e2fb6..545c6dbb5 100644
--- a/src/share/vm/utilities/taskqueue.hpp
+++ b/src/share/vm/utilities/taskqueue.hpp
@@ -53,6 +53,12 @@
#ifdef TARGET_OS_ARCH_linux_ppc
# include "orderAccess_linux_ppc.inline.hpp"
#endif
+#ifdef TARGET_OS_ARCH_bsd_x86
+# include "orderAccess_bsd_x86.inline.hpp"
+#endif
+#ifdef TARGET_OS_ARCH_bsd_zero
+# include "orderAccess_bsd_zero.inline.hpp"
+#endif
// Simple TaskQueue stats that are collected by default in debug builds.
diff --git a/src/share/vm/utilities/vmError.cpp b/src/share/vm/utilities/vmError.cpp
index fa8b82094..bb34fcd63 100644
--- a/src/share/vm/utilities/vmError.cpp
+++ b/src/share/vm/utilities/vmError.cpp
@@ -45,13 +45,18 @@ const char *env_list[] = {
"JAVA_HOME", "JRE_HOME", "JAVA_TOOL_OPTIONS", "_JAVA_OPTIONS", "CLASSPATH",
"JAVA_COMPILER", "PATH", "USERNAME",
- // Env variables that are defined on Solaris/Linux
+ // Env variables that are defined on Solaris/Linux/BSD
"LD_LIBRARY_PATH", "LD_PRELOAD", "SHELL", "DISPLAY",
"HOSTTYPE", "OSTYPE", "ARCH", "MACHTYPE",
// defined on Linux
"LD_ASSUME_KERNEL", "_JAVA_SR_SIGNUM",
+ // defined on Darwin
+ "DYLD_LIBRARY_PATH", "DYLD_FALLBACK_LIBRARY_PATH",
+ "DYLD_FRAMEWORK_PATH", "DYLD_FALLBACK_FRAMEWORK_PATH",
+ "DYLD_INSERT_LIBRARIES",
+
// defined on Windows
"OS", "PROCESSOR_IDENTIFIER", "_ALT_JAVA_HOME_DIR",
@@ -958,7 +963,7 @@ void VMError::report_and_die() {
const char* ptr = OnError;
while ((cmd = next_OnError_command(buffer, sizeof(buffer), &ptr)) != NULL){
out.print_raw ("# Executing ");
-#if defined(LINUX)
+#if defined(LINUX) || defined(_ALLBSD_SOURCE)
out.print_raw ("/bin/sh -c ");
#elif defined(SOLARIS)
out.print_raw ("/usr/bin/sh -c ");
diff --git a/src/share/vm/utilities/workgroup.hpp b/src/share/vm/utilities/workgroup.hpp
index 2bd6e9c05..8e9effebd 100644
--- a/src/share/vm/utilities/workgroup.hpp
+++ b/src/share/vm/utilities/workgroup.hpp
@@ -35,6 +35,9 @@
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
// Task class hierarchy:
// AbstractGangTask
diff --git a/test/Makefile b/test/Makefile
index 9c66ade7e..50818dd01 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -44,6 +44,22 @@ ifeq ($(OSNAME), Linux)
ARCH = i586
endif
endif
+ifeq ($(OSNAME), Darwin)
+ PLATFORM = bsd
+ SLASH_JAVA = /java
+ ARCH = $(shell uname -m)
+ ifeq ($(ARCH), i386)
+ ARCH = i586
+ endif
+endif
+ifeq ($(findstring BSD,$(OSNAME)), BSD)
+ PLATFORM = bsd
+ SLASH_JAVA = /java
+ ARCH = $(shell uname -m)
+ ifeq ($(ARCH), i386)
+ ARCH = i586
+ endif
+endif
ifeq ($(OSNAME), Windows_NT)
PLATFORM = windows
SLASH_JAVA = J:
diff --git a/test/jprt.config b/test/jprt.config
index 53c33fd37..53ffdaecd 100644
--- a/test/jprt.config
+++ b/test/jprt.config
@@ -75,8 +75,8 @@ dirMustExist "${slashjava}" ALT_SLASH_JAVA
# Uses 'uname -s', but only expect SunOS or Linux, assume Windows otherwise.
osname=`uname -s`
-if [ "${osname}" = SunOS ] ; then
-
+case "${osname}" in
+ SunOS )
# SOLARIS: Sparc or X86
osarch=`uname -p`
if [ "${osarch}" = sparc ] ; then
@@ -100,9 +100,9 @@ if [ "${osname}" = SunOS ] ; then
# File creation mask
umask 002
+ ;;
-elif [ "${osname}" = Linux ] ; then
-
+ Linux | Darwin )
# Add basic paths
path4sdk=/usr/bin:/bin:/usr/sbin:/sbin
@@ -111,9 +111,31 @@ elif [ "${osname}" = Linux ] ; then
fileMustExist "${make}" make
umask 002
+ ;;
+
+ FreeBSD | OpenBSD )
+ # Add basic paths
+ path4sdk=/usr/bin:/bin:/usr/sbin:/sbin
-else
+ # Find GNU make
+ make=/usr/local/bin/gmake
+ fileMustExist "${make}" make
+ umask 002
+ ;;
+
+ NetBSD )
+ # Add basic paths
+ path4sdk=/usr/bin:/bin:/usr/sbin:/sbin
+
+ # Find GNU make
+ make=/usr/pkg/bin/gmake
+ fileMustExist "${make}" make
+
+ umask 002
+ ;;
+
+ * )
# Windows: Differs on CYGWIN vs. MKS.
# We need to determine if we are running a CYGWIN shell or an MKS shell
@@ -154,8 +176,8 @@ else
if [ "${unix_toolset}" = CYGWIN ] ; then
path4sdk="`/usr/bin/cygpath -p ${path4sdk}`"
fi
-
-fi
+ ;;
+esac
# Export PATH setting
PATH="${path4sdk}"
diff --git a/test/runtime/6929067/Test6929067.sh b/test/runtime/6929067/Test6929067.sh
index 51af19139..8f9e13a6f 100644
--- a/test/runtime/6929067/Test6929067.sh
+++ b/test/runtime/6929067/Test6929067.sh
@@ -29,7 +29,7 @@ case "$OS" in
PS=":"
FS="/"
;;
- SunOS | Windows_* )
+ SunOS | Windows_* | *BSD)
NULL=NUL
PS=";"
FS="\\"