os_solaris.hpp 18.1 KB
Newer Older
D
duke 已提交
1
/*
S
sla 已提交
2
 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
D
duke 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
 * 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.
 *
19 20 21
 * 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.
D
duke 已提交
22 23 24
 *
 */

25 26 27
#ifndef OS_SOLARIS_VM_OS_SOLARIS_HPP
#define OS_SOLARIS_VM_OS_SOLARIS_HPP

D
duke 已提交
28 29
// Solaris_OS defines the interface to Solaris operating systems

30 31 32
// Information about the protection of the page at address '0' on this os.
static bool zero_page_read_protected() { return true; }

D
duke 已提交
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
class Solaris {
  friend class os;

 private:

  // Support for "new" libthread APIs for getting & setting thread context (2.8)
  #define TRS_VALID       0
  #define TRS_NONVOLATILE 1
  #define TRS_LWPID       2
  #define TRS_INVALID     3

  // _T2_libthread is true if we believe we are running with the newer
  // SunSoft lib/lwp/libthread: default Solaris 9, available Solaris 8
  // which is a lightweight libthread that also supports all T1
  static bool _T2_libthread;
  // These refer to new libthread interface functions
  // They get intialized if we dynamically detect new libthread
  static int_fnP_thread_t_iP_uP_stack_tP_gregset_t _thr_getstate;
  static int_fnP_thread_t_i_gregset_t _thr_setstate;
  static int_fnP_thread_t_i _thr_setmutator;
  static int_fnP_thread_t _thr_suspend_mutator;
  static int_fnP_thread_t _thr_continue_mutator;
  // libthread_init sets the above, if the new functionality is detected

  // initialized to libthread or lwp synchronization primitives depending on UseLWPSychronization
  static int_fnP_mutex_tP _mutex_lock;
  static int_fnP_mutex_tP _mutex_trylock;
  static int_fnP_mutex_tP _mutex_unlock;
  static int_fnP_mutex_tP_i_vP _mutex_init;
  static int_fnP_mutex_tP _mutex_destroy;
  static int _mutex_scope;

  static int_fnP_cond_tP_mutex_tP_timestruc_tP _cond_timedwait;
  static int_fnP_cond_tP_mutex_tP _cond_wait;
  static int_fnP_cond_tP _cond_signal;
  static int_fnP_cond_tP _cond_broadcast;
  static int_fnP_cond_tP_i_vP _cond_init;
  static int_fnP_cond_tP _cond_destroy;
  static int _cond_scope;

  typedef uintptr_t       lgrp_cookie_t;
  typedef id_t            lgrp_id_t;
75
  typedef int             lgrp_rsrc_t;
D
duke 已提交
76 77 78 79 80
  typedef enum lgrp_view {
        LGRP_VIEW_CALLER,       /* what's available to the caller */
        LGRP_VIEW_OS            /* what's available to operating system */
  } lgrp_view_t;

81 82
  typedef uint_t (*getisax_func_t)(uint32_t* array, uint_t n);

D
duke 已提交
83 84 85 86 87 88
  typedef lgrp_id_t (*lgrp_home_func_t)(idtype_t idtype, id_t id);
  typedef lgrp_cookie_t (*lgrp_init_func_t)(lgrp_view_t view);
  typedef int (*lgrp_fini_func_t)(lgrp_cookie_t cookie);
  typedef lgrp_id_t (*lgrp_root_func_t)(lgrp_cookie_t cookie);
  typedef int (*lgrp_children_func_t)(lgrp_cookie_t  cookie,  lgrp_id_t  parent,
                                      lgrp_id_t *lgrp_array, uint_t lgrp_array_size);
89 90 91
  typedef int (*lgrp_resources_func_t)(lgrp_cookie_t  cookie,  lgrp_id_t  lgrp,
                                      lgrp_id_t *lgrp_array, uint_t lgrp_array_size,
                                      lgrp_rsrc_t type);
D
duke 已提交
92 93 94 95 96 97
  typedef int (*lgrp_nlgrps_func_t)(lgrp_cookie_t cookie);
  typedef int (*lgrp_cookie_stale_func_t)(lgrp_cookie_t cookie);
  typedef int (*meminfo_func_t)(const uint64_t inaddr[],   int addr_count,
                                const uint_t  info_req[],  int info_count,
                                uint64_t  outdata[], uint_t validity[]);

98 99
  static getisax_func_t _getisax;

D
duke 已提交
100 101 102 103 104
  static lgrp_home_func_t _lgrp_home;
  static lgrp_init_func_t _lgrp_init;
  static lgrp_fini_func_t _lgrp_fini;
  static lgrp_root_func_t _lgrp_root;
  static lgrp_children_func_t _lgrp_children;
105
  static lgrp_resources_func_t _lgrp_resources;
D
duke 已提交
106 107 108 109 110 111
  static lgrp_nlgrps_func_t _lgrp_nlgrps;
  static lgrp_cookie_stale_func_t _lgrp_cookie_stale;
  static lgrp_cookie_t _lgrp_cookie;

  static meminfo_func_t _meminfo;

112 113
  // Large Page Support
  static bool setup_large_pages(caddr_t start, size_t bytes, size_t align);
D
duke 已提交
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149

  static void init_thread_fpu_state(void);

  static void try_enable_extended_io();

  // For signal-chaining
  static unsigned long sigs;                 // mask of signals that have
                                             // preinstalled signal handlers
  static struct sigaction *(*get_signal_action)(int);
  static struct sigaction *get_preinstalled_handler(int);
  static int (*get_libjsig_version)();
  static void save_preinstalled_handler(int, struct sigaction&);
  static void check_signal_handler(int sig);
  // For overridable signals
  static int _SIGinterrupt;                  // user-overridable INTERRUPT_SIGNAL
  static int _SIGasync;                      // user-overridable ASYNC_SIGNAL
  static void set_SIGinterrupt(int newsig) { _SIGinterrupt = newsig; }
  static void set_SIGasync(int newsig) { _SIGasync = newsig; }

 public:
  // Large Page Support--ISM.
  static bool largepage_range(char* addr, size_t size);

  static int SIGinterrupt() { return _SIGinterrupt; }
  static int SIGasync() { return _SIGasync; }
  static address handler_start, handler_end; // start and end pc of thr_sighndlrinfo

  static bool valid_stack_address(Thread* thread, address sp);
  static bool valid_ucontext(Thread* thread, ucontext_t* valid, ucontext_t* suspect);
  static ucontext_t* get_valid_uc_in_signal_handler(Thread* thread,
    ucontext_t* uc);

  static ExtendedPC  ucontext_get_ExtendedPC(ucontext_t* uc);
  static intptr_t*   ucontext_get_sp(ucontext_t* uc);
  // ucontext_get_fp() is only used by Solaris X86 (see note below)
  static intptr_t*   ucontext_get_fp(ucontext_t* uc);
S
sla 已提交
150
  static address    ucontext_get_pc(ucontext_t* uc);
D
duke 已提交
151 152 153 154 155 156 157 158 159 160 161 162

  // For Analyzer Forte AsyncGetCallTrace profiling support:
  // Parameter ret_fp is only used by Solaris X86.
  //
  // We should have different declarations of this interface in
  // os_solaris_i486.hpp and os_solaris_sparc.hpp, but that file
  // provides extensions to the os class and not the Solaris class.
  static ExtendedPC fetch_frame_from_ucontext(Thread* thread, ucontext_t* uc,
    intptr_t** ret_sp, intptr_t** ret_fp);

  static void hotspot_sigmask(Thread* thread);

S
sla 已提交
163 164
  // SR_handler
  static void SR_handler(Thread* thread, ucontext_t* uc);
D
duke 已提交
165 166 167 168 169 170 171 172 173
 protected:
  // Solaris-specific interface goes here
  static julong available_memory();
  static julong physical_memory() { return _physical_memory; }
  static julong _physical_memory;
  static void initialize_system_info();
  static int _dev_zero_fd;
  static int get_dev_zero_fd() { return _dev_zero_fd; }
  static void set_dev_zero_fd(int fd) { _dev_zero_fd = fd; }
174 175 176
  static int commit_memory_impl(char* addr, size_t bytes, bool exec);
  static int commit_memory_impl(char* addr, size_t bytes,
                                size_t alignment_hint, bool exec);
D
duke 已提交
177
  static char* mmap_chunk(char *addr, size_t size, int flags, int prot);
178
  static char* anon_mmap(char* requested_addr, size_t bytes, size_t alignment_hint, bool fixed);
D
duke 已提交
179 180 181 182 183 184 185 186 187 188 189
  static bool mpss_sanity_check(bool warn, size_t * page_size);

  // Workaround for 4352906. thr_stksegment sometimes returns
  // a bad value for the primordial thread's stack base when
  // it is called more than one time.
  // Workaround is to cache the initial value to avoid further
  // calls to thr_stksegment.
  // It appears that someone (Hotspot?) is trashing the user's
  // proc_t structure (note that this is a system struct).
  static address _main_stack_base;

190 191 192
  static void print_distro_info(outputStream* st);
  static void print_libversion_info(outputStream* st);

D
duke 已提交
193 194 195
 public:
  static void libthread_init();
  static void synchronization_init();
196
  static bool liblgrp_init();
D
duke 已提交
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
  // Load miscellaneous symbols.
  static void misc_sym_init();
  // This boolean allows users to forward their own non-matching signals
  // to JVM_handle_solaris_signal, harmlessly.
  static bool signal_handlers_are_installed;

  static void signal_sets_init();
  static void install_signal_handlers();
  static void set_signal_handler(int sig, bool set_installed, bool oktochain);
  static void init_signal_mem();
  static bool is_sig_ignored(int sig);
  static void set_our_sigflags(int, int);
  static int get_our_sigflags(int);

  // For signal-chaining
  static bool libjsig_is_loaded; // libjsig that interposes sigaction(),
                                 // signal(), sigset() is loaded
  static struct sigaction *get_chained_signal_action(int sig);
  static bool chained_handler(int sig, siginfo_t *siginfo, void *context);

  // The following allow us to link against both the old and new libthread (2.8)
  // and exploit the new libthread functionality if available.

  static bool T2_libthread()                                { return _T2_libthread; }
  static void set_T2_libthread(bool T2_libthread) { _T2_libthread = T2_libthread; }

  static int thr_getstate(thread_t tid, int *flag, unsigned *lwp, stack_t *ss, gregset_t rs)
    { return _thr_getstate(tid, flag, lwp, ss, rs); }
  static void set_thr_getstate(int_fnP_thread_t_iP_uP_stack_tP_gregset_t func)
    { _thr_getstate = func; }

  static int thr_setstate(thread_t tid, int flag, gregset_t rs)   { return _thr_setstate(tid, flag, rs); }
  static void set_thr_setstate(int_fnP_thread_t_i_gregset_t func) { _thr_setstate = func; }

  static int thr_setmutator(thread_t tid, int enabled)    { return _thr_setmutator(tid, enabled); }
  static void set_thr_setmutator(int_fnP_thread_t_i func) { _thr_setmutator = func; }

  static int  thr_suspend_mutator(thread_t tid)              { return _thr_suspend_mutator(tid); }
  static void set_thr_suspend_mutator(int_fnP_thread_t func) { _thr_suspend_mutator = func; }

  static int  thr_continue_mutator(thread_t tid)              { return _thr_continue_mutator(tid); }
  static void set_thr_continue_mutator(int_fnP_thread_t func) { _thr_continue_mutator = func; }

  // Allows us to switch between lwp and thread -based synchronization
  static int mutex_lock(mutex_t *mx)    { return _mutex_lock(mx); }
  static int mutex_trylock(mutex_t *mx) { return _mutex_trylock(mx); }
  static int mutex_unlock(mutex_t *mx)  { return _mutex_unlock(mx); }
  static int mutex_init(mutex_t *mx)    { return _mutex_init(mx, os::Solaris::mutex_scope(), NULL); }
  static int mutex_destroy(mutex_t *mx) { return _mutex_destroy(mx); }
  static int mutex_scope()              { return _mutex_scope; }

  static void set_mutex_lock(int_fnP_mutex_tP func)      { _mutex_lock = func; }
  static void set_mutex_trylock(int_fnP_mutex_tP func)   { _mutex_trylock = func; }
  static void set_mutex_unlock(int_fnP_mutex_tP func)    { _mutex_unlock = func; }
  static void set_mutex_init(int_fnP_mutex_tP_i_vP func) { _mutex_init = func; }
  static void set_mutex_destroy(int_fnP_mutex_tP func)   { _mutex_destroy = func; }
  static void set_mutex_scope(int scope)                 { _mutex_scope = scope; }

  static int cond_timedwait(cond_t *cv, mutex_t *mx, timestruc_t *abst)
                                                { return _cond_timedwait(cv, mx, abst); }
  static int cond_wait(cond_t *cv, mutex_t *mx) { return _cond_wait(cv, mx); }
  static int cond_signal(cond_t *cv)            { return _cond_signal(cv); }
  static int cond_broadcast(cond_t *cv)         { return _cond_broadcast(cv); }
  static int cond_init(cond_t *cv)              { return _cond_init(cv, os::Solaris::cond_scope(), NULL); }
  static int cond_destroy(cond_t *cv)           { return _cond_destroy(cv); }
  static int cond_scope()                       { return _cond_scope; }

  static void set_cond_timedwait(int_fnP_cond_tP_mutex_tP_timestruc_tP func)
                                                           { _cond_timedwait = func; }
  static void set_cond_wait(int_fnP_cond_tP_mutex_tP func) { _cond_wait = func; }
  static void set_cond_signal(int_fnP_cond_tP func)        { _cond_signal = func; }
  static void set_cond_broadcast(int_fnP_cond_tP func)     { _cond_broadcast = func; }
  static void set_cond_init(int_fnP_cond_tP_i_vP func)     { _cond_init = func; }
  static void set_cond_destroy(int_fnP_cond_tP func)       { _cond_destroy = func; }
  static void set_cond_scope(int scope)                    { _cond_scope = scope; }

  static void set_lgrp_home(lgrp_home_func_t func) { _lgrp_home = func; }
  static void set_lgrp_init(lgrp_init_func_t func) { _lgrp_init = func; }
  static void set_lgrp_fini(lgrp_fini_func_t func) { _lgrp_fini = func; }
  static void set_lgrp_root(lgrp_root_func_t func) { _lgrp_root = func; }
277 278 279
  static void set_lgrp_children(lgrp_children_func_t func)   { _lgrp_children = func; }
  static void set_lgrp_resources(lgrp_resources_func_t func) { _lgrp_resources = func; }
  static void set_lgrp_nlgrps(lgrp_nlgrps_func_t func)       { _lgrp_nlgrps = func; }
D
duke 已提交
280 281 282 283 284 285 286 287 288 289 290
  static void set_lgrp_cookie_stale(lgrp_cookie_stale_func_t func) { _lgrp_cookie_stale = func; }
  static void set_lgrp_cookie(lgrp_cookie_t cookie)  { _lgrp_cookie = cookie; }

  static id_t lgrp_home(idtype_t type, id_t id)      { return _lgrp_home != NULL ? _lgrp_home(type, id) : -1; }
  static lgrp_cookie_t lgrp_init(lgrp_view_t view)   { return _lgrp_init != NULL ? _lgrp_init(view) : 0; }
  static int lgrp_fini(lgrp_cookie_t cookie)         { return _lgrp_fini != NULL ? _lgrp_fini(cookie) : -1; }
  static lgrp_id_t lgrp_root(lgrp_cookie_t cookie)   { return _lgrp_root != NULL ? _lgrp_root(cookie) : -1; };
  static int lgrp_children(lgrp_cookie_t  cookie,  lgrp_id_t  parent,
                    lgrp_id_t *lgrp_array, uint_t lgrp_array_size) {
    return _lgrp_children != NULL ? _lgrp_children(cookie, parent, lgrp_array, lgrp_array_size) : -1;
  }
291 292 293 294 295 296
  static int lgrp_resources(lgrp_cookie_t  cookie,  lgrp_id_t  lgrp,
                            lgrp_id_t *lgrp_array, uint_t lgrp_array_size,
                            lgrp_rsrc_t type) {
    return _lgrp_resources != NULL ? _lgrp_resources(cookie, lgrp, lgrp_array, lgrp_array_size, type) : -1;
  }

D
duke 已提交
297 298 299 300 301 302
  static int lgrp_nlgrps(lgrp_cookie_t cookie)       { return _lgrp_nlgrps != NULL ? _lgrp_nlgrps(cookie) : -1; }
  static int lgrp_cookie_stale(lgrp_cookie_t cookie) {
    return _lgrp_cookie_stale != NULL ? _lgrp_cookie_stale(cookie) : -1;
  }
  static lgrp_cookie_t lgrp_cookie()                 { return _lgrp_cookie; }

303 304 305
  static bool supports_getisax()                     { return _getisax != NULL; }
  static uint_t getisax(uint32_t* array, uint_t n);

D
duke 已提交
306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355
  static void set_meminfo(meminfo_func_t func)       { _meminfo = func; }
  static int meminfo (const uint64_t inaddr[],   int addr_count,
                     const uint_t  info_req[],  int info_count,
                     uint64_t  outdata[], uint_t validity[]) {
    return _meminfo != NULL ? _meminfo(inaddr, addr_count, info_req, info_count,
                                       outdata, validity) : -1;
  }

  enum {
    clear_interrupted = true
  };
  static void setup_interruptible(JavaThread* thread);
  static void setup_interruptible_already_blocked(JavaThread* thread);
  static JavaThread* setup_interruptible();
  static void cleanup_interruptible(JavaThread* thread);

  // perf counter incrementers used by _INTERRUPTIBLE

  static void bump_interrupted_before_count();
  static void bump_interrupted_during_count();

#ifdef ASSERT
  static JavaThread* setup_interruptible_native();
  static void cleanup_interruptible_native(JavaThread* thread);
#endif

  static sigset_t* unblocked_signals();
  static sigset_t* vm_signals();
  static sigset_t* allowdebug_blocked_signals();

  // %%% Following should be promoted to os.hpp:
  // Trace number of created threads
  static          jint  _os_thread_limit;
  static volatile jint  _os_thread_count;

  // 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;

  // Stack overflow handling

  static int max_register_window_saves_before_flushing();

  // Stack repair handling

  // none present

};

Z
zgu 已提交
356
class PlatformEvent : public CHeapObj<mtInternal> {
D
duke 已提交
357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392
  private:
    double CachePad [4] ;   // increase odds that _mutex is sole occupant of cache line
    volatile int _Event ;
    int _nParked ;
    int _pipev [2] ;
    mutex_t _mutex  [1] ;
    cond_t  _cond   [1] ;
    double PostPad  [2] ;

  protected:
    // Defining a protected ctor effectively gives us an abstract base class.
    // That is, a PlatformEvent can never be instantiated "naked" but only
    // as a part of a ParkEvent (recall that ParkEvent extends PlatformEvent).
    // TODO-FIXME: make dtor private
    ~PlatformEvent() { guarantee (0, "invariant") ; }
    PlatformEvent() {
      int status;
      status = os::Solaris::cond_init(_cond);
      assert_status(status == 0, status, "cond_init");
      status = os::Solaris::mutex_init(_mutex);
      assert_status(status == 0, status, "mutex_init");
      _Event   = 0 ;
      _nParked = 0 ;
      _pipev[0] = _pipev[1] = -1 ;
    }

  public:
    // Exercise caution using reset() and fired() -- they may require MEMBARs
    void reset() { _Event = 0 ; }
    int  fired() { return _Event; }
    void park () ;
    int  park (jlong millis) ;
    int  TryPark () ;
    void unpark () ;
} ;

Z
zgu 已提交
393
class PlatformParker : public CHeapObj<mtInternal> {
D
duke 已提交
394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409
  protected:
    mutex_t _mutex [1] ;
    cond_t  _cond  [1] ;

  public:       // TODO-FIXME: make dtor private
    ~PlatformParker() { guarantee (0, "invariant") ; }

  public:
    PlatformParker() {
      int status;
      status = os::Solaris::cond_init(_cond);
      assert_status(status == 0, status, "cond_init");
      status = os::Solaris::mutex_init(_mutex);
      assert_status(status == 0, status, "mutex_init");
    }
} ;
410 411

#endif // OS_SOLARIS_VM_OS_SOLARIS_HPP