src/os/solaris/vm/os_solaris.hpp

Wed, 27 Mar 2013 19:21:18 +0100

author
tschatzl
date
Wed, 27 Mar 2013 19:21:18 +0100
changeset 4854
754c24457b20
parent 4153
b9a9ed0f8eeb
child 5237
f2110083203d
permissions
-rw-r--r--

7112912: Message "Error occurred during initialization of VM" on boxes with lots of RAM
Summary: Ergonomics now also takes available virtual memory into account when deciding for a heap size. The helper method to determine the maximum allocatable memory block now uses the appropriate OS specific calls to retrieve available virtual memory for the java process. In 32 bit environments this method now also searches for the maximum actually reservable amount of memory. Merge previously separate implementations for Linux/BSD/Solaris into a single method.
Reviewed-by: jmasa, tamao

     1 /*
     2  * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  *
    23  */
    25 #ifndef OS_SOLARIS_VM_OS_SOLARIS_HPP
    26 #define OS_SOLARIS_VM_OS_SOLARIS_HPP
    28 // Solaris_OS defines the interface to Solaris operating systems
    30 class Solaris {
    31   friend class os;
    33  private:
    35   // Support for "new" libthread APIs for getting & setting thread context (2.8)
    36   #define TRS_VALID       0
    37   #define TRS_NONVOLATILE 1
    38   #define TRS_LWPID       2
    39   #define TRS_INVALID     3
    41   // _T2_libthread is true if we believe we are running with the newer
    42   // SunSoft lib/lwp/libthread: default Solaris 9, available Solaris 8
    43   // which is a lightweight libthread that also supports all T1
    44   static bool _T2_libthread;
    45   // These refer to new libthread interface functions
    46   // They get intialized if we dynamically detect new libthread
    47   static int_fnP_thread_t_iP_uP_stack_tP_gregset_t _thr_getstate;
    48   static int_fnP_thread_t_i_gregset_t _thr_setstate;
    49   static int_fnP_thread_t_i _thr_setmutator;
    50   static int_fnP_thread_t _thr_suspend_mutator;
    51   static int_fnP_thread_t _thr_continue_mutator;
    52   // libthread_init sets the above, if the new functionality is detected
    54   // initialized to libthread or lwp synchronization primitives depending on UseLWPSychronization
    55   static int_fnP_mutex_tP _mutex_lock;
    56   static int_fnP_mutex_tP _mutex_trylock;
    57   static int_fnP_mutex_tP _mutex_unlock;
    58   static int_fnP_mutex_tP_i_vP _mutex_init;
    59   static int_fnP_mutex_tP _mutex_destroy;
    60   static int _mutex_scope;
    62   static int_fnP_cond_tP_mutex_tP_timestruc_tP _cond_timedwait;
    63   static int_fnP_cond_tP_mutex_tP _cond_wait;
    64   static int_fnP_cond_tP _cond_signal;
    65   static int_fnP_cond_tP _cond_broadcast;
    66   static int_fnP_cond_tP_i_vP _cond_init;
    67   static int_fnP_cond_tP _cond_destroy;
    68   static int _cond_scope;
    70   typedef uintptr_t       lgrp_cookie_t;
    71   typedef id_t            lgrp_id_t;
    72   typedef int             lgrp_rsrc_t;
    73   typedef enum lgrp_view {
    74         LGRP_VIEW_CALLER,       /* what's available to the caller */
    75         LGRP_VIEW_OS            /* what's available to operating system */
    76   } lgrp_view_t;
    78   typedef uint_t (*getisax_func_t)(uint32_t* array, uint_t n);
    80   typedef lgrp_id_t (*lgrp_home_func_t)(idtype_t idtype, id_t id);
    81   typedef lgrp_cookie_t (*lgrp_init_func_t)(lgrp_view_t view);
    82   typedef int (*lgrp_fini_func_t)(lgrp_cookie_t cookie);
    83   typedef lgrp_id_t (*lgrp_root_func_t)(lgrp_cookie_t cookie);
    84   typedef int (*lgrp_children_func_t)(lgrp_cookie_t  cookie,  lgrp_id_t  parent,
    85                                       lgrp_id_t *lgrp_array, uint_t lgrp_array_size);
    86   typedef int (*lgrp_resources_func_t)(lgrp_cookie_t  cookie,  lgrp_id_t  lgrp,
    87                                       lgrp_id_t *lgrp_array, uint_t lgrp_array_size,
    88                                       lgrp_rsrc_t type);
    89   typedef int (*lgrp_nlgrps_func_t)(lgrp_cookie_t cookie);
    90   typedef int (*lgrp_cookie_stale_func_t)(lgrp_cookie_t cookie);
    91   typedef int (*meminfo_func_t)(const uint64_t inaddr[],   int addr_count,
    92                                 const uint_t  info_req[],  int info_count,
    93                                 uint64_t  outdata[], uint_t validity[]);
    95   static getisax_func_t _getisax;
    97   static lgrp_home_func_t _lgrp_home;
    98   static lgrp_init_func_t _lgrp_init;
    99   static lgrp_fini_func_t _lgrp_fini;
   100   static lgrp_root_func_t _lgrp_root;
   101   static lgrp_children_func_t _lgrp_children;
   102   static lgrp_resources_func_t _lgrp_resources;
   103   static lgrp_nlgrps_func_t _lgrp_nlgrps;
   104   static lgrp_cookie_stale_func_t _lgrp_cookie_stale;
   105   static lgrp_cookie_t _lgrp_cookie;
   107   static meminfo_func_t _meminfo;
   109   // Large Page Support--mpss.
   110   static bool set_mpss_range(caddr_t start, size_t bytes, size_t align);
   112   static void init_thread_fpu_state(void);
   114   static void try_enable_extended_io();
   116   // For signal-chaining
   117   static unsigned long sigs;                 // mask of signals that have
   118                                              // preinstalled signal handlers
   119   static struct sigaction *(*get_signal_action)(int);
   120   static struct sigaction *get_preinstalled_handler(int);
   121   static int (*get_libjsig_version)();
   122   static void save_preinstalled_handler(int, struct sigaction&);
   123   static void check_signal_handler(int sig);
   124   // For overridable signals
   125   static int _SIGinterrupt;                  // user-overridable INTERRUPT_SIGNAL
   126   static int _SIGasync;                      // user-overridable ASYNC_SIGNAL
   127   static void set_SIGinterrupt(int newsig) { _SIGinterrupt = newsig; }
   128   static void set_SIGasync(int newsig) { _SIGasync = newsig; }
   131  public:
   132   // Large Page Support--ISM.
   133   static bool largepage_range(char* addr, size_t size);
   135   static int SIGinterrupt() { return _SIGinterrupt; }
   136   static int SIGasync() { return _SIGasync; }
   137   static address handler_start, handler_end; // start and end pc of thr_sighndlrinfo
   139   static bool valid_stack_address(Thread* thread, address sp);
   140   static bool valid_ucontext(Thread* thread, ucontext_t* valid, ucontext_t* suspect);
   141   static ucontext_t* get_valid_uc_in_signal_handler(Thread* thread,
   142     ucontext_t* uc);
   144   static ExtendedPC  ucontext_get_ExtendedPC(ucontext_t* uc);
   145   static intptr_t*   ucontext_get_sp(ucontext_t* uc);
   146   // ucontext_get_fp() is only used by Solaris X86 (see note below)
   147   static intptr_t*   ucontext_get_fp(ucontext_t* uc);
   149   // For Analyzer Forte AsyncGetCallTrace profiling support:
   150   // Parameter ret_fp is only used by Solaris X86.
   151   //
   152   // We should have different declarations of this interface in
   153   // os_solaris_i486.hpp and os_solaris_sparc.hpp, but that file
   154   // provides extensions to the os class and not the Solaris class.
   155   static ExtendedPC fetch_frame_from_ucontext(Thread* thread, ucontext_t* uc,
   156     intptr_t** ret_sp, intptr_t** ret_fp);
   158   static void hotspot_sigmask(Thread* thread);
   160  protected:
   161   // Solaris-specific interface goes here
   162   static julong available_memory();
   163   static julong physical_memory() { return _physical_memory; }
   164   static julong _physical_memory;
   165   static void initialize_system_info();
   166   static int _dev_zero_fd;
   167   static int get_dev_zero_fd() { return _dev_zero_fd; }
   168   static void set_dev_zero_fd(int fd) { _dev_zero_fd = fd; }
   169   static char* mmap_chunk(char *addr, size_t size, int flags, int prot);
   170   static char* anon_mmap(char* requested_addr, size_t bytes, size_t alignment_hint, bool fixed);
   171   static bool mpss_sanity_check(bool warn, size_t * page_size);
   172   static bool ism_sanity_check (bool warn, size_t * page_size);
   174   // Workaround for 4352906. thr_stksegment sometimes returns
   175   // a bad value for the primordial thread's stack base when
   176   // it is called more than one time.
   177   // Workaround is to cache the initial value to avoid further
   178   // calls to thr_stksegment.
   179   // It appears that someone (Hotspot?) is trashing the user's
   180   // proc_t structure (note that this is a system struct).
   181   static address _main_stack_base;
   183   static void print_distro_info(outputStream* st);
   184   static void print_libversion_info(outputStream* st);
   186  public:
   187   static void libthread_init();
   188   static void synchronization_init();
   189   static bool liblgrp_init();
   190   // Load miscellaneous symbols.
   191   static void misc_sym_init();
   192   // This boolean allows users to forward their own non-matching signals
   193   // to JVM_handle_solaris_signal, harmlessly.
   194   static bool signal_handlers_are_installed;
   196   static void signal_sets_init();
   197   static void install_signal_handlers();
   198   static void set_signal_handler(int sig, bool set_installed, bool oktochain);
   199   static void init_signal_mem();
   200   static bool is_sig_ignored(int sig);
   201   static void set_our_sigflags(int, int);
   202   static int get_our_sigflags(int);
   204   // For signal-chaining
   205   static bool libjsig_is_loaded; // libjsig that interposes sigaction(),
   206                                  // signal(), sigset() is loaded
   207   static struct sigaction *get_chained_signal_action(int sig);
   208   static bool chained_handler(int sig, siginfo_t *siginfo, void *context);
   210   // The following allow us to link against both the old and new libthread (2.8)
   211   // and exploit the new libthread functionality if available.
   213   static bool T2_libthread()                                { return _T2_libthread; }
   214   static void set_T2_libthread(bool T2_libthread) { _T2_libthread = T2_libthread; }
   216   static int thr_getstate(thread_t tid, int *flag, unsigned *lwp, stack_t *ss, gregset_t rs)
   217     { return _thr_getstate(tid, flag, lwp, ss, rs); }
   218   static void set_thr_getstate(int_fnP_thread_t_iP_uP_stack_tP_gregset_t func)
   219     { _thr_getstate = func; }
   221   static int thr_setstate(thread_t tid, int flag, gregset_t rs)   { return _thr_setstate(tid, flag, rs); }
   222   static void set_thr_setstate(int_fnP_thread_t_i_gregset_t func) { _thr_setstate = func; }
   224   static int thr_setmutator(thread_t tid, int enabled)    { return _thr_setmutator(tid, enabled); }
   225   static void set_thr_setmutator(int_fnP_thread_t_i func) { _thr_setmutator = func; }
   227   static int  thr_suspend_mutator(thread_t tid)              { return _thr_suspend_mutator(tid); }
   228   static void set_thr_suspend_mutator(int_fnP_thread_t func) { _thr_suspend_mutator = func; }
   230   static int  thr_continue_mutator(thread_t tid)              { return _thr_continue_mutator(tid); }
   231   static void set_thr_continue_mutator(int_fnP_thread_t func) { _thr_continue_mutator = func; }
   233   // Allows us to switch between lwp and thread -based synchronization
   234   static int mutex_lock(mutex_t *mx)    { return _mutex_lock(mx); }
   235   static int mutex_trylock(mutex_t *mx) { return _mutex_trylock(mx); }
   236   static int mutex_unlock(mutex_t *mx)  { return _mutex_unlock(mx); }
   237   static int mutex_init(mutex_t *mx)    { return _mutex_init(mx, os::Solaris::mutex_scope(), NULL); }
   238   static int mutex_destroy(mutex_t *mx) { return _mutex_destroy(mx); }
   239   static int mutex_scope()              { return _mutex_scope; }
   241   static void set_mutex_lock(int_fnP_mutex_tP func)      { _mutex_lock = func; }
   242   static void set_mutex_trylock(int_fnP_mutex_tP func)   { _mutex_trylock = func; }
   243   static void set_mutex_unlock(int_fnP_mutex_tP func)    { _mutex_unlock = func; }
   244   static void set_mutex_init(int_fnP_mutex_tP_i_vP func) { _mutex_init = func; }
   245   static void set_mutex_destroy(int_fnP_mutex_tP func)   { _mutex_destroy = func; }
   246   static void set_mutex_scope(int scope)                 { _mutex_scope = scope; }
   248   static int cond_timedwait(cond_t *cv, mutex_t *mx, timestruc_t *abst)
   249                                                 { return _cond_timedwait(cv, mx, abst); }
   250   static int cond_wait(cond_t *cv, mutex_t *mx) { return _cond_wait(cv, mx); }
   251   static int cond_signal(cond_t *cv)            { return _cond_signal(cv); }
   252   static int cond_broadcast(cond_t *cv)         { return _cond_broadcast(cv); }
   253   static int cond_init(cond_t *cv)              { return _cond_init(cv, os::Solaris::cond_scope(), NULL); }
   254   static int cond_destroy(cond_t *cv)           { return _cond_destroy(cv); }
   255   static int cond_scope()                       { return _cond_scope; }
   257   static void set_cond_timedwait(int_fnP_cond_tP_mutex_tP_timestruc_tP func)
   258                                                            { _cond_timedwait = func; }
   259   static void set_cond_wait(int_fnP_cond_tP_mutex_tP func) { _cond_wait = func; }
   260   static void set_cond_signal(int_fnP_cond_tP func)        { _cond_signal = func; }
   261   static void set_cond_broadcast(int_fnP_cond_tP func)     { _cond_broadcast = func; }
   262   static void set_cond_init(int_fnP_cond_tP_i_vP func)     { _cond_init = func; }
   263   static void set_cond_destroy(int_fnP_cond_tP func)       { _cond_destroy = func; }
   264   static void set_cond_scope(int scope)                    { _cond_scope = scope; }
   266   static void set_lgrp_home(lgrp_home_func_t func) { _lgrp_home = func; }
   267   static void set_lgrp_init(lgrp_init_func_t func) { _lgrp_init = func; }
   268   static void set_lgrp_fini(lgrp_fini_func_t func) { _lgrp_fini = func; }
   269   static void set_lgrp_root(lgrp_root_func_t func) { _lgrp_root = func; }
   270   static void set_lgrp_children(lgrp_children_func_t func)   { _lgrp_children = func; }
   271   static void set_lgrp_resources(lgrp_resources_func_t func) { _lgrp_resources = func; }
   272   static void set_lgrp_nlgrps(lgrp_nlgrps_func_t func)       { _lgrp_nlgrps = func; }
   273   static void set_lgrp_cookie_stale(lgrp_cookie_stale_func_t func) { _lgrp_cookie_stale = func; }
   274   static void set_lgrp_cookie(lgrp_cookie_t cookie)  { _lgrp_cookie = cookie; }
   276   static id_t lgrp_home(idtype_t type, id_t id)      { return _lgrp_home != NULL ? _lgrp_home(type, id) : -1; }
   277   static lgrp_cookie_t lgrp_init(lgrp_view_t view)   { return _lgrp_init != NULL ? _lgrp_init(view) : 0; }
   278   static int lgrp_fini(lgrp_cookie_t cookie)         { return _lgrp_fini != NULL ? _lgrp_fini(cookie) : -1; }
   279   static lgrp_id_t lgrp_root(lgrp_cookie_t cookie)   { return _lgrp_root != NULL ? _lgrp_root(cookie) : -1; };
   280   static int lgrp_children(lgrp_cookie_t  cookie,  lgrp_id_t  parent,
   281                     lgrp_id_t *lgrp_array, uint_t lgrp_array_size) {
   282     return _lgrp_children != NULL ? _lgrp_children(cookie, parent, lgrp_array, lgrp_array_size) : -1;
   283   }
   284   static int lgrp_resources(lgrp_cookie_t  cookie,  lgrp_id_t  lgrp,
   285                             lgrp_id_t *lgrp_array, uint_t lgrp_array_size,
   286                             lgrp_rsrc_t type) {
   287     return _lgrp_resources != NULL ? _lgrp_resources(cookie, lgrp, lgrp_array, lgrp_array_size, type) : -1;
   288   }
   290   static int lgrp_nlgrps(lgrp_cookie_t cookie)       { return _lgrp_nlgrps != NULL ? _lgrp_nlgrps(cookie) : -1; }
   291   static int lgrp_cookie_stale(lgrp_cookie_t cookie) {
   292     return _lgrp_cookie_stale != NULL ? _lgrp_cookie_stale(cookie) : -1;
   293   }
   294   static lgrp_cookie_t lgrp_cookie()                 { return _lgrp_cookie; }
   296   static bool supports_getisax()                     { return _getisax != NULL; }
   297   static uint_t getisax(uint32_t* array, uint_t n);
   299   static void set_meminfo(meminfo_func_t func)       { _meminfo = func; }
   300   static int meminfo (const uint64_t inaddr[],   int addr_count,
   301                      const uint_t  info_req[],  int info_count,
   302                      uint64_t  outdata[], uint_t validity[]) {
   303     return _meminfo != NULL ? _meminfo(inaddr, addr_count, info_req, info_count,
   304                                        outdata, validity) : -1;
   305   }
   307   enum {
   308     clear_interrupted = true
   309   };
   310   static void setup_interruptible(JavaThread* thread);
   311   static void setup_interruptible_already_blocked(JavaThread* thread);
   312   static JavaThread* setup_interruptible();
   313   static void cleanup_interruptible(JavaThread* thread);
   315   // perf counter incrementers used by _INTERRUPTIBLE
   317   static void bump_interrupted_before_count();
   318   static void bump_interrupted_during_count();
   320 #ifdef ASSERT
   321   static JavaThread* setup_interruptible_native();
   322   static void cleanup_interruptible_native(JavaThread* thread);
   323 #endif
   325   static sigset_t* unblocked_signals();
   326   static sigset_t* vm_signals();
   327   static sigset_t* allowdebug_blocked_signals();
   329   // %%% Following should be promoted to os.hpp:
   330   // Trace number of created threads
   331   static          jint  _os_thread_limit;
   332   static volatile jint  _os_thread_count;
   334   // Minimum stack size a thread can be created with (allowing
   335   // the VM to completely create the thread and enter user code)
   337   static size_t min_stack_allowed;
   339   // Stack overflow handling
   341   static int max_register_window_saves_before_flushing();
   343   // Stack repair handling
   345   // none present
   347 };
   349 class PlatformEvent : public CHeapObj<mtInternal> {
   350   private:
   351     double CachePad [4] ;   // increase odds that _mutex is sole occupant of cache line
   352     volatile int _Event ;
   353     int _nParked ;
   354     int _pipev [2] ;
   355     mutex_t _mutex  [1] ;
   356     cond_t  _cond   [1] ;
   357     double PostPad  [2] ;
   359   protected:
   360     // Defining a protected ctor effectively gives us an abstract base class.
   361     // That is, a PlatformEvent can never be instantiated "naked" but only
   362     // as a part of a ParkEvent (recall that ParkEvent extends PlatformEvent).
   363     // TODO-FIXME: make dtor private
   364     ~PlatformEvent() { guarantee (0, "invariant") ; }
   365     PlatformEvent() {
   366       int status;
   367       status = os::Solaris::cond_init(_cond);
   368       assert_status(status == 0, status, "cond_init");
   369       status = os::Solaris::mutex_init(_mutex);
   370       assert_status(status == 0, status, "mutex_init");
   371       _Event   = 0 ;
   372       _nParked = 0 ;
   373       _pipev[0] = _pipev[1] = -1 ;
   374     }
   376   public:
   377     // Exercise caution using reset() and fired() -- they may require MEMBARs
   378     void reset() { _Event = 0 ; }
   379     int  fired() { return _Event; }
   380     void park () ;
   381     int  park (jlong millis) ;
   382     int  TryPark () ;
   383     void unpark () ;
   384 } ;
   386 class PlatformParker : public CHeapObj<mtInternal> {
   387   protected:
   388     mutex_t _mutex [1] ;
   389     cond_t  _cond  [1] ;
   391   public:       // TODO-FIXME: make dtor private
   392     ~PlatformParker() { guarantee (0, "invariant") ; }
   394   public:
   395     PlatformParker() {
   396       int status;
   397       status = os::Solaris::cond_init(_cond);
   398       assert_status(status == 0, status, "cond_init");
   399       status = os::Solaris::mutex_init(_mutex);
   400       assert_status(status == 0, status, "mutex_init");
   401     }
   402 } ;
   404 #endif // OS_SOLARIS_VM_OS_SOLARIS_HPP

mercurial