src/os_cpu/solaris_x86/vm/threadLS_solaris_x86.cpp

Thu, 16 Feb 2012 17:12:49 -0800

author
kvn
date
Thu, 16 Feb 2012 17:12:49 -0800
changeset 3577
9b8ce46870df
parent 2314
f95d63e2154a
child 4299
f34d701e952e
permissions
-rw-r--r--

7145346: VerifyStackAtCalls is broken
Summary: Replace call_epilog() encoding with macroassembler use. Moved duplicated code to x86.ad. Fixed return_addr() definition.
Reviewed-by: never

     1 /*
     2  * Copyright (c) 1998, 2010, 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 #include "precompiled.hpp"
    26 #include "runtime/threadLocalStorage.hpp"
    27 #include "thread_solaris.inline.hpp"
    29 #ifdef AMD64
    30 extern "C" Thread*  fs_load(ptrdiff_t tlsOffset);
    31 extern "C" intptr_t fs_thread();
    32 #else
    33 // From solaris_i486.s
    34 extern "C" Thread*  gs_load(ptrdiff_t tlsOffset);
    35 extern "C" intptr_t gs_thread();
    36 #endif // AMD64
    38 // tlsMode encoding:
    39 //
    40 // pd_tlsAccessUndefined : uninitialized
    41 // pd_tlsAccessSlow      : not available
    42 // pd_tlsAccessIndirect  :
    43 //   old-style indirect access - present in "T1" libthread.
    44 //   use thr_slot_sync_allocate() to attempt to allocate a slot.
    45 // pd_tlsAccessDirect    :
    46 //   new-style direct access - present in late-model "T2" libthread.
    47 //   Allocate the offset (slot) via _thr_slot_offset() or by
    48 //   defining an IE- or LE-mode TLS/TSD slot in the launcher and then passing
    49 //   that offset into libjvm.so.
    50 //   See http://sac.eng/Archives/CaseLog/arc/PSARC/2003/159/.
    51 //
    52 // Note that we have a capability gap - some early model T2 forms
    53 // (e.g., unpatched S9) have neither _thr_slot_sync_allocate() nor
    54 // _thr_slot_offset().  In that case we revert to the usual
    55 // thr_getspecific accessor.
    56 //
    58 static ThreadLocalStorage::pd_tlsAccessMode tlsMode = ThreadLocalStorage::pd_tlsAccessUndefined ;
    59 static ptrdiff_t tlsOffset = 0 ;
    60 static thread_key_t tlsKey ;
    62 typedef int (*TSSA_Entry) (ptrdiff_t *, int, int) ;
    63 typedef ptrdiff_t (*TSO_Entry) (int) ;
    65 ThreadLocalStorage::pd_tlsAccessMode ThreadLocalStorage::pd_getTlsAccessMode ()
    66 {
    67    guarantee (tlsMode != pd_tlsAccessUndefined, "tlsMode not set") ;
    68    return tlsMode ;
    69 }
    71 ptrdiff_t ThreadLocalStorage::pd_getTlsOffset () {
    72    guarantee (tlsMode != pd_tlsAccessUndefined, "tlsMode not set") ;
    73    return tlsOffset ;
    74 }
    76 // TODO: Consider the following improvements:
    77 //
    78 // 1.   Convert from thr_*specific* to pthread_*specific*.
    79 //      The pthread_ forms are slightly faster.  Also, the
    80 //      pthread_ forms have a pthread_key_delete() API which
    81 //      would aid in clean JVM shutdown and the eventual goal
    82 //      of permitting a JVM to reinstantiate itself withing a process.
    83 //
    84 // 2.   See ThreadLocalStorage::init().  We end up allocating
    85 //      two TLS keys during VM startup.  That's benign, but we could collapse
    86 //      down to one key without too much trouble.
    87 //
    88 // 3.   MacroAssembler::get_thread() currently emits calls to thr_getspecific().
    89 //      Modify get_thread() to call Thread::current() instead.
    90 //
    91 // 4.   Thread::current() currently uses a cache keyed by %gs:[0].
    92 //      (The JVM has PSARC permission to use %g7/%gs:[0]
    93 //      as an opaque temporally unique thread identifier).
    94 //      For C++ access to a thread's reflexive "self" pointer we
    95 //      should consider using one of the following:
    96 //      a. a radix tree keyed by %esp - as in EVM.
    97 //         This requires two loads (the 2nd dependent on the 1st), but
    98 //         is easily inlined and doesn't require a "miss" slow path.
    99 //      b. a fast TLS/TSD slot allocated by _thr_slot_offset
   100 //         or _thr_slot_sync_allocate.
   101 //
   102 // 5.   'generate_code_for_get_thread' is a misnomer.
   103 //      We should change it to something more general like
   104 //      pd_ThreadSelf_Init(), for instance.
   105 //
   107 static void AllocateTLSOffset ()
   108 {
   109    int rslt ;
   110    TSSA_Entry tssa ;
   111    TSO_Entry  tso ;
   112    ptrdiff_t off ;
   114    guarantee (tlsMode == ThreadLocalStorage::pd_tlsAccessUndefined, "tlsMode not set") ;
   115    tlsMode = ThreadLocalStorage::pd_tlsAccessSlow ;
   116    tlsOffset = 0 ;
   117 #ifndef AMD64
   119    tssa = (TSSA_Entry) dlsym (RTLD_DEFAULT, "thr_slot_sync_allocate") ;
   120    if (tssa != NULL) {
   121         off = -1 ;
   122         rslt = (*tssa)(&off, NULL, NULL) ;                // (off,dtor,darg)
   123         if (off != -1) {
   124            tlsOffset = off ;
   125            tlsMode = ThreadLocalStorage::pd_tlsAccessIndirect ;
   126            return ;
   127         }
   128     }
   130     rslt = thr_keycreate (&tlsKey, NULL) ;
   131     if (rslt != 0) {
   132         tlsMode = ThreadLocalStorage::pd_tlsAccessSlow ;   // revert to slow mode
   133         return ;
   134     }
   136     tso = (TSO_Entry) dlsym (RTLD_DEFAULT, "_thr_slot_offset") ;
   137     if (tso != NULL) {
   138         off = (*tso)(tlsKey) ;
   139         if (off >= 0) {
   140            tlsOffset = off ;
   141            tlsMode = ThreadLocalStorage::pd_tlsAccessDirect ;
   142            return ;
   143         }
   144     }
   146     // Failure: Too bad ... we've allocated a TLS slot we don't need and there's
   147     // no provision in the ABI for returning the slot.
   148     //
   149     // If we didn't find a slot then then:
   150     // 1. We might be on liblwp.
   151     // 2. We might be on T2 libthread, but all "fast" slots are already
   152     //    consumed
   153     // 3. We might be on T1, and all TSD (thr_slot_sync_allocate) slots are
   154     //    consumed.
   155     // 4. We might be on T2 libthread, but it's be re-architected
   156     //    so that fast slots are no longer g7-relative.
   157     //
   159     tlsMode = ThreadLocalStorage::pd_tlsAccessSlow ;
   160     return ;
   161 #endif // AMD64
   162 }
   164 void ThreadLocalStorage::generate_code_for_get_thread() {
   165     AllocateTLSOffset() ;
   166 }
   168 void ThreadLocalStorage::set_thread_in_slot(Thread *thread) {
   169   guarantee (tlsMode != pd_tlsAccessUndefined, "tlsMode not set") ;
   170   if (tlsMode == pd_tlsAccessIndirect) {
   171 #ifdef AMD64
   172         intptr_t tbase = fs_thread();
   173 #else
   174         intptr_t tbase = gs_thread();
   175 #endif // AMD64
   176         *((Thread**) (tbase + tlsOffset)) = thread ;
   177   } else
   178   if (tlsMode == pd_tlsAccessDirect) {
   179         thr_setspecific (tlsKey, (void *) thread) ;
   180         // set with thr_setspecific and then readback with gs_load to validate.
   181 #ifdef AMD64
   182         guarantee (thread == fs_load(tlsOffset), "tls readback failure") ;
   183 #else
   184         guarantee (thread == gs_load(tlsOffset), "tls readback failure") ;
   185 #endif // AMD64
   186   }
   187 }
   190 extern "C" Thread* get_thread() {
   191   return ThreadLocalStorage::thread();
   192 }

mercurial