os_solaris.hpp revision 60:8d84e28e68ba
1254939Sdes/* 2254939Sdes * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. 3254939Sdes * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4254939Sdes * 5254939Sdes * This code is free software; you can redistribute it and/or modify it 6254939Sdes * under the terms of the GNU General Public License version 2 only, as 7254939Sdes * published by the Free Software Foundation. 8254939Sdes * 9254939Sdes * This code is distributed in the hope that it will be useful, but WITHOUT 10255403Sdes * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11255403Sdes * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12254939Sdes * version 2 for more details (a copy is included in the LICENSE file that 13254939Sdes * accompanied this code). 14254939Sdes * 15254939Sdes * You should have received a copy of the GNU General Public License version 16254939Sdes * 2 along with this work; if not, write to the Free Software Foundation, 17254939Sdes * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18255403Sdes * 19255403Sdes * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 20254939Sdes * CA 95054 USA or visit www.sun.com if you need additional information or 21254939Sdes * have any questions. 22254939Sdes * 23254939Sdes */ 24254939Sdes 25254939Sdes// Solaris_OS defines the interface to Solaris operating systems 26254939Sdes 27254939Sdesclass Solaris { 28254939Sdes friend class os; 29254939Sdes 30254939Sdes private: 31254939Sdes 32254939Sdes // Support for "new" libthread APIs for getting & setting thread context (2.8) 33254939Sdes #define TRS_VALID 0 34254939Sdes #define TRS_NONVOLATILE 1 35254939Sdes #define TRS_LWPID 2 36254939Sdes #define TRS_INVALID 3 37254939Sdes 38254939Sdes // _T2_libthread is true if we believe we are running with the newer 39254939Sdes // SunSoft lib/lwp/libthread: default Solaris 9, available Solaris 8 40254939Sdes // which is a lightweight libthread that also supports all T1 41254939Sdes static bool _T2_libthread; 42254939Sdes // These refer to new libthread interface functions 43254939Sdes // They get intialized if we dynamically detect new libthread 44254939Sdes static int_fnP_thread_t_iP_uP_stack_tP_gregset_t _thr_getstate; 45254939Sdes static int_fnP_thread_t_i_gregset_t _thr_setstate; 46254939Sdes static int_fnP_thread_t_i _thr_setmutator; 47254939Sdes static int_fnP_thread_t _thr_suspend_mutator; 48254939Sdes static int_fnP_thread_t _thr_continue_mutator; 49254939Sdes // libthread_init sets the above, if the new functionality is detected 50254939Sdes 51254939Sdes // initialized to libthread or lwp synchronization primitives depending on UseLWPSychronization 52254939Sdes static int_fnP_mutex_tP _mutex_lock; 53254939Sdes static int_fnP_mutex_tP _mutex_trylock; 54254939Sdes static int_fnP_mutex_tP _mutex_unlock; 55254939Sdes static int_fnP_mutex_tP_i_vP _mutex_init; 56254939Sdes static int_fnP_mutex_tP _mutex_destroy; 57254939Sdes static int _mutex_scope; 58254939Sdes 59254939Sdes static int_fnP_cond_tP_mutex_tP_timestruc_tP _cond_timedwait; 60254939Sdes static int_fnP_cond_tP_mutex_tP _cond_wait; 61254939Sdes static int_fnP_cond_tP _cond_signal; 62254939Sdes static int_fnP_cond_tP _cond_broadcast; 63254939Sdes static int_fnP_cond_tP_i_vP _cond_init; 64254939Sdes static int_fnP_cond_tP _cond_destroy; 65254939Sdes static int _cond_scope; 66254939Sdes 67254939Sdes typedef uintptr_t lgrp_cookie_t; 68254939Sdes typedef id_t lgrp_id_t; 69254939Sdes typedef enum lgrp_view { 70254939Sdes LGRP_VIEW_CALLER, /* what's available to the caller */ 71254939Sdes LGRP_VIEW_OS /* what's available to operating system */ 72254939Sdes } lgrp_view_t; 73254939Sdes 74254939Sdes typedef lgrp_id_t (*lgrp_home_func_t)(idtype_t idtype, id_t id); 75254939Sdes typedef lgrp_cookie_t (*lgrp_init_func_t)(lgrp_view_t view); 76254939Sdes typedef int (*lgrp_fini_func_t)(lgrp_cookie_t cookie); 77254939Sdes typedef lgrp_id_t (*lgrp_root_func_t)(lgrp_cookie_t cookie); 78254939Sdes typedef int (*lgrp_children_func_t)(lgrp_cookie_t cookie, lgrp_id_t parent, 79254939Sdes lgrp_id_t *lgrp_array, uint_t lgrp_array_size); 80254939Sdes typedef int (*lgrp_nlgrps_func_t)(lgrp_cookie_t cookie); 81254939Sdes typedef int (*lgrp_cookie_stale_func_t)(lgrp_cookie_t cookie); 82254939Sdes typedef int (*meminfo_func_t)(const uint64_t inaddr[], int addr_count, 83254939Sdes const uint_t info_req[], int info_count, 84254939Sdes uint64_t outdata[], uint_t validity[]); 85254939Sdes 86254939Sdes static lgrp_home_func_t _lgrp_home; 87254939Sdes static lgrp_init_func_t _lgrp_init; 88254939Sdes static lgrp_fini_func_t _lgrp_fini; 89254939Sdes static lgrp_root_func_t _lgrp_root; 90254939Sdes static lgrp_children_func_t _lgrp_children; 91254939Sdes static lgrp_nlgrps_func_t _lgrp_nlgrps; 92254939Sdes static lgrp_cookie_stale_func_t _lgrp_cookie_stale; 93254939Sdes static lgrp_cookie_t _lgrp_cookie; 94254939Sdes 95254939Sdes static meminfo_func_t _meminfo; 96254939Sdes 97254939Sdes // Large Page Support--mpss. 98254939Sdes static bool set_mpss_range(caddr_t start, size_t bytes, size_t align); 99254939Sdes 100254939Sdes static void init_thread_fpu_state(void); 101254939Sdes 102254939Sdes static void try_enable_extended_io(); 103254939Sdes 104254939Sdes // For signal-chaining 105254939Sdes static unsigned long sigs; // mask of signals that have 106254939Sdes // preinstalled signal handlers 107254939Sdes static struct sigaction *(*get_signal_action)(int); 108254939Sdes static struct sigaction *get_preinstalled_handler(int); 109254939Sdes static int (*get_libjsig_version)(); 110254939Sdes static void save_preinstalled_handler(int, struct sigaction&); 111254939Sdes static void check_signal_handler(int sig); 112254939Sdes 113254939Sdes // For overridable signals 114254939Sdes static int _SIGinterrupt; // user-overridable INTERRUPT_SIGNAL 115254939Sdes static int _SIGasync; // user-overridable ASYNC_SIGNAL 116254939Sdes static void set_SIGinterrupt(int newsig) { _SIGinterrupt = newsig; } 117254939Sdes static void set_SIGasync(int newsig) { _SIGasync = newsig; } 118254939Sdes 119254939Sdes 120254939Sdes public: 121254939Sdes // Large Page Support--ISM. 122254939Sdes static bool largepage_range(char* addr, size_t size); 123254939Sdes 124254939Sdes static int SIGinterrupt() { return _SIGinterrupt; } 125254939Sdes static int SIGasync() { return _SIGasync; } 126254939Sdes static address handler_start, handler_end; // start and end pc of thr_sighndlrinfo 127254939Sdes 128254939Sdes static bool valid_stack_address(Thread* thread, address sp); 129254939Sdes static bool valid_ucontext(Thread* thread, ucontext_t* valid, ucontext_t* suspect); 130254939Sdes static ucontext_t* get_valid_uc_in_signal_handler(Thread* thread, 131254939Sdes ucontext_t* uc); 132254939Sdes 133254939Sdes static ExtendedPC ucontext_get_ExtendedPC(ucontext_t* uc); 134254939Sdes static intptr_t* ucontext_get_sp(ucontext_t* uc); 135254939Sdes // ucontext_get_fp() is only used by Solaris X86 (see note below) 136254939Sdes static intptr_t* ucontext_get_fp(ucontext_t* uc); 137254939Sdes 138254939Sdes // For Analyzer Forte AsyncGetCallTrace profiling support: 139254939Sdes // Parameter ret_fp is only used by Solaris X86. 140254939Sdes // 141254939Sdes // We should have different declarations of this interface in 142254939Sdes // os_solaris_i486.hpp and os_solaris_sparc.hpp, but that file 143254939Sdes // provides extensions to the os class and not the Solaris class. 144254939Sdes static ExtendedPC fetch_frame_from_ucontext(Thread* thread, ucontext_t* uc, 145254939Sdes intptr_t** ret_sp, intptr_t** ret_fp); 146254939Sdes 147254939Sdes static void hotspot_sigmask(Thread* thread); 148254939Sdes 149254939Sdes protected: 150254939Sdes // Solaris-specific interface goes here 151254939Sdes static julong available_memory(); 152254939Sdes static julong physical_memory() { return _physical_memory; } 153254939Sdes static julong _physical_memory; 154254939Sdes static void initialize_system_info(); 155254939Sdes static int _dev_zero_fd; 156254939Sdes static int get_dev_zero_fd() { return _dev_zero_fd; } 157254939Sdes static void set_dev_zero_fd(int fd) { _dev_zero_fd = fd; } 158254939Sdes static char* mmap_chunk(char *addr, size_t size, int flags, int prot); 159254939Sdes static char* anon_mmap(char* requested_addr, size_t bytes, size_t alignment_hint, bool fixed); 160254939Sdes static bool mpss_sanity_check(bool warn, size_t * page_size); 161254939Sdes static bool ism_sanity_check (bool warn, size_t * page_size); 162254939Sdes 163254939Sdes // Workaround for 4352906. thr_stksegment sometimes returns 164254939Sdes // a bad value for the primordial thread's stack base when 165254939Sdes // it is called more than one time. 166254939Sdes // Workaround is to cache the initial value to avoid further 167254939Sdes // calls to thr_stksegment. 168254939Sdes // It appears that someone (Hotspot?) is trashing the user's 169254939Sdes // proc_t structure (note that this is a system struct). 170254939Sdes static address _main_stack_base; 171254939Sdes 172254939Sdes public: 173254939Sdes static void libthread_init(); 174254939Sdes static void synchronization_init(); 175254939Sdes static void liblgrp_init(); 176254939Sdes // Load miscellaneous symbols. 177254939Sdes static void misc_sym_init(); 178254939Sdes // This boolean allows users to forward their own non-matching signals 179254939Sdes // to JVM_handle_solaris_signal, harmlessly. 180254939Sdes static bool signal_handlers_are_installed; 181254939Sdes 182254939Sdes static void signal_sets_init(); 183254939Sdes static void install_signal_handlers(); 184254939Sdes static void set_signal_handler(int sig, bool set_installed, bool oktochain); 185254939Sdes static void init_signal_mem(); 186254939Sdes static bool is_sig_ignored(int sig); 187254939Sdes static void set_our_sigflags(int, int); 188254939Sdes static int get_our_sigflags(int); 189254939Sdes 190254939Sdes // For signal-chaining 191254939Sdes static bool libjsig_is_loaded; // libjsig that interposes sigaction(), 192254939Sdes // signal(), sigset() is loaded 193254939Sdes static struct sigaction *get_chained_signal_action(int sig); 194254939Sdes static bool chained_handler(int sig, siginfo_t *siginfo, void *context); 195254939Sdes 196254939Sdes // The following allow us to link against both the old and new libthread (2.8) 197254939Sdes // and exploit the new libthread functionality if available. 198254939Sdes 199254939Sdes static bool T2_libthread() { return _T2_libthread; } 200254939Sdes static void set_T2_libthread(bool T2_libthread) { _T2_libthread = T2_libthread; } 201254939Sdes 202254939Sdes static int thr_getstate(thread_t tid, int *flag, unsigned *lwp, stack_t *ss, gregset_t rs) 203254939Sdes { return _thr_getstate(tid, flag, lwp, ss, rs); } 204255403Sdes static void set_thr_getstate(int_fnP_thread_t_iP_uP_stack_tP_gregset_t func) 205254939Sdes { _thr_getstate = func; } 206255403Sdes 207255403Sdes static int thr_setstate(thread_t tid, int flag, gregset_t rs) { return _thr_setstate(tid, flag, rs); } 208255403Sdes static void set_thr_setstate(int_fnP_thread_t_i_gregset_t func) { _thr_setstate = func; } 209254939Sdes 210254939Sdes static int thr_setmutator(thread_t tid, int enabled) { return _thr_setmutator(tid, enabled); } 211254939Sdes static void set_thr_setmutator(int_fnP_thread_t_i func) { _thr_setmutator = func; } 212254939Sdes 213254939Sdes static int thr_suspend_mutator(thread_t tid) { return _thr_suspend_mutator(tid); } 214254939Sdes static void set_thr_suspend_mutator(int_fnP_thread_t func) { _thr_suspend_mutator = func; } 215254939Sdes 216254939Sdes static int thr_continue_mutator(thread_t tid) { return _thr_continue_mutator(tid); } 217254939Sdes static void set_thr_continue_mutator(int_fnP_thread_t func) { _thr_continue_mutator = func; } 218254939Sdes 219254939Sdes // Allows us to switch between lwp and thread -based synchronization 220254939Sdes static int mutex_lock(mutex_t *mx) { return _mutex_lock(mx); } 221254939Sdes static int mutex_trylock(mutex_t *mx) { return _mutex_trylock(mx); } 222254939Sdes static int mutex_unlock(mutex_t *mx) { return _mutex_unlock(mx); } 223254939Sdes static int mutex_init(mutex_t *mx) { return _mutex_init(mx, os::Solaris::mutex_scope(), NULL); } 224254939Sdes static int mutex_destroy(mutex_t *mx) { return _mutex_destroy(mx); } 225254939Sdes static int mutex_scope() { return _mutex_scope; } 226254939Sdes 227254939Sdes static void set_mutex_lock(int_fnP_mutex_tP func) { _mutex_lock = func; } 228254939Sdes static void set_mutex_trylock(int_fnP_mutex_tP func) { _mutex_trylock = func; } 229254939Sdes static void set_mutex_unlock(int_fnP_mutex_tP func) { _mutex_unlock = func; } 230254939Sdes static void set_mutex_init(int_fnP_mutex_tP_i_vP func) { _mutex_init = func; } 231254939Sdes static void set_mutex_destroy(int_fnP_mutex_tP func) { _mutex_destroy = func; } 232254939Sdes static void set_mutex_scope(int scope) { _mutex_scope = scope; } 233254939Sdes 234254939Sdes static int cond_timedwait(cond_t *cv, mutex_t *mx, timestruc_t *abst) 235254939Sdes { return _cond_timedwait(cv, mx, abst); } 236254939Sdes static int cond_wait(cond_t *cv, mutex_t *mx) { return _cond_wait(cv, mx); } 237254939Sdes static int cond_signal(cond_t *cv) { return _cond_signal(cv); } 238254939Sdes static int cond_broadcast(cond_t *cv) { return _cond_broadcast(cv); } 239254939Sdes static int cond_init(cond_t *cv) { return _cond_init(cv, os::Solaris::cond_scope(), NULL); } 240254939Sdes static int cond_destroy(cond_t *cv) { return _cond_destroy(cv); } 241254939Sdes static int cond_scope() { return _cond_scope; } 242254939Sdes 243254939Sdes static void set_cond_timedwait(int_fnP_cond_tP_mutex_tP_timestruc_tP func) 244254939Sdes { _cond_timedwait = func; } 245254939Sdes static void set_cond_wait(int_fnP_cond_tP_mutex_tP func) { _cond_wait = func; } 246254939Sdes static void set_cond_signal(int_fnP_cond_tP func) { _cond_signal = func; } 247254939Sdes static void set_cond_broadcast(int_fnP_cond_tP func) { _cond_broadcast = func; } 248254939Sdes static void set_cond_init(int_fnP_cond_tP_i_vP func) { _cond_init = func; } 249254939Sdes static void set_cond_destroy(int_fnP_cond_tP func) { _cond_destroy = func; } 250254939Sdes static void set_cond_scope(int scope) { _cond_scope = scope; } 251254939Sdes 252254939Sdes static void set_lgrp_home(lgrp_home_func_t func) { _lgrp_home = func; } 253254939Sdes static void set_lgrp_init(lgrp_init_func_t func) { _lgrp_init = func; } 254254939Sdes static void set_lgrp_fini(lgrp_fini_func_t func) { _lgrp_fini = func; } 255254939Sdes static void set_lgrp_root(lgrp_root_func_t func) { _lgrp_root = func; } 256254939Sdes static void set_lgrp_children(lgrp_children_func_t func) { _lgrp_children = func; } 257254939Sdes static void set_lgrp_nlgrps(lgrp_nlgrps_func_t func) { _lgrp_nlgrps = func; } 258254939Sdes static void set_lgrp_cookie_stale(lgrp_cookie_stale_func_t func) { _lgrp_cookie_stale = func; } 259254939Sdes static void set_lgrp_cookie(lgrp_cookie_t cookie) { _lgrp_cookie = cookie; } 260254939Sdes 261254939Sdes static id_t lgrp_home(idtype_t type, id_t id) { return _lgrp_home != NULL ? _lgrp_home(type, id) : -1; } 262254939Sdes static lgrp_cookie_t lgrp_init(lgrp_view_t view) { return _lgrp_init != NULL ? _lgrp_init(view) : 0; } 263254939Sdes static int lgrp_fini(lgrp_cookie_t cookie) { return _lgrp_fini != NULL ? _lgrp_fini(cookie) : -1; } 264254939Sdes static lgrp_id_t lgrp_root(lgrp_cookie_t cookie) { return _lgrp_root != NULL ? _lgrp_root(cookie) : -1; }; 265254939Sdes static int lgrp_children(lgrp_cookie_t cookie, lgrp_id_t parent, 266254939Sdes lgrp_id_t *lgrp_array, uint_t lgrp_array_size) { 267254939Sdes return _lgrp_children != NULL ? _lgrp_children(cookie, parent, lgrp_array, lgrp_array_size) : -1; 268254939Sdes } 269254939Sdes static int lgrp_nlgrps(lgrp_cookie_t cookie) { return _lgrp_nlgrps != NULL ? _lgrp_nlgrps(cookie) : -1; } 270254939Sdes static int lgrp_cookie_stale(lgrp_cookie_t cookie) { 271254939Sdes return _lgrp_cookie_stale != NULL ? _lgrp_cookie_stale(cookie) : -1; 272254939Sdes } 273254939Sdes static lgrp_cookie_t lgrp_cookie() { return _lgrp_cookie; } 274254939Sdes 275254939Sdes static void set_meminfo(meminfo_func_t func) { _meminfo = func; } 276254939Sdes static int meminfo (const uint64_t inaddr[], int addr_count, 277254939Sdes const uint_t info_req[], int info_count, 278254939Sdes uint64_t outdata[], uint_t validity[]) { 279254939Sdes return _meminfo != NULL ? _meminfo(inaddr, addr_count, info_req, info_count, 280254939Sdes outdata, validity) : -1; 281254939Sdes } 282254939Sdes 283254939Sdes enum { 284254939Sdes clear_interrupted = true 285254939Sdes }; 286254939Sdes static void setup_interruptible(JavaThread* thread); 287254939Sdes static void setup_interruptible_already_blocked(JavaThread* thread); 288254939Sdes static JavaThread* setup_interruptible(); 289254939Sdes static void cleanup_interruptible(JavaThread* thread); 290254939Sdes 291254939Sdes // perf counter incrementers used by _INTERRUPTIBLE 292254939Sdes 293254939Sdes static void bump_interrupted_before_count(); 294254939Sdes static void bump_interrupted_during_count(); 295254939Sdes 296254939Sdes#ifdef ASSERT 297254939Sdes static JavaThread* setup_interruptible_native(); 298254939Sdes static void cleanup_interruptible_native(JavaThread* thread); 299254939Sdes#endif 300254939Sdes 301254939Sdes static sigset_t* unblocked_signals(); 302254939Sdes static sigset_t* vm_signals(); 303254939Sdes static sigset_t* allowdebug_blocked_signals(); 304254939Sdes 305254939Sdes // %%% Following should be promoted to os.hpp: 306254939Sdes // Trace number of created threads 307254939Sdes static jint _os_thread_limit; 308254939Sdes static volatile jint _os_thread_count; 309254939Sdes 310254939Sdes // Minimum stack size a thread can be created with (allowing 311254939Sdes // the VM to completely create the thread and enter user code) 312254939Sdes 313254939Sdes static size_t min_stack_allowed; 314254939Sdes 315254939Sdes // Stack overflow handling 316254939Sdes 317254939Sdes static int max_register_window_saves_before_flushing(); 318254939Sdes 319254939Sdes // Stack repair handling 320254939Sdes 321254939Sdes // none present 322254939Sdes 323254939Sdes}; 324254939Sdes 325254939Sdesclass PlatformEvent : public CHeapObj { 326254939Sdes private: 327254939Sdes double CachePad [4] ; // increase odds that _mutex is sole occupant of cache line 328254939Sdes volatile int _Event ; 329254939Sdes int _nParked ; 330254939Sdes int _pipev [2] ; 331254939Sdes mutex_t _mutex [1] ; 332254939Sdes cond_t _cond [1] ; 333254939Sdes double PostPad [2] ; 334254939Sdes 335254939Sdes protected: 336254939Sdes // Defining a protected ctor effectively gives us an abstract base class. 337254939Sdes // That is, a PlatformEvent can never be instantiated "naked" but only 338254939Sdes // as a part of a ParkEvent (recall that ParkEvent extends PlatformEvent). 339254939Sdes // TODO-FIXME: make dtor private 340254939Sdes ~PlatformEvent() { guarantee (0, "invariant") ; } 341254939Sdes PlatformEvent() { 342254939Sdes int status; 343254939Sdes status = os::Solaris::cond_init(_cond); 344254939Sdes assert_status(status == 0, status, "cond_init"); 345254939Sdes status = os::Solaris::mutex_init(_mutex); 346254939Sdes assert_status(status == 0, status, "mutex_init"); 347254939Sdes _Event = 0 ; 348254939Sdes _nParked = 0 ; 349254939Sdes _pipev[0] = _pipev[1] = -1 ; 350254939Sdes } 351254939Sdes 352254939Sdes public: 353254939Sdes // Exercise caution using reset() and fired() -- they may require MEMBARs 354254939Sdes void reset() { _Event = 0 ; } 355254939Sdes int fired() { return _Event; } 356254939Sdes void park () ; 357254939Sdes int park (jlong millis) ; 358254939Sdes int TryPark () ; 359254939Sdes void unpark () ; 360254939Sdes} ; 361254939Sdes 362254939Sdesclass PlatformParker : public CHeapObj { 363254939Sdes protected: 364254939Sdes mutex_t _mutex [1] ; 365254939Sdes cond_t _cond [1] ; 366254939Sdes 367254939Sdes public: // TODO-FIXME: make dtor private 368254939Sdes ~PlatformParker() { guarantee (0, "invariant") ; } 369254939Sdes 370254939Sdes public: 371254939Sdes PlatformParker() { 372254939Sdes int status; 373254939Sdes status = os::Solaris::cond_init(_cond); 374254939Sdes assert_status(status == 0, status, "cond_init"); 375254939Sdes status = os::Solaris::mutex_init(_mutex); 376254939Sdes assert_status(status == 0, status, "mutex_init"); 377254939Sdes } 378254939Sdes} ; 379254939Sdes