src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp

Thu, 20 Nov 2008 16:56:09 -0800

author
ysr
date
Thu, 20 Nov 2008 16:56:09 -0800
changeset 888
c96030fff130
parent 435
a61af66fc99e
child 1907
c18cbe5936b8
permissions
-rw-r--r--

6684579: SoftReference processing can be made more efficient
Summary: For current soft-ref clearing policies, we can decide at marking time if a soft-reference will definitely not be cleared, postponing the decision of whether it will definitely be cleared to the final reference processing phase. This can be especially beneficial in the case of concurrent collectors where the marking is usually concurrent but reference processing is usually not.
Reviewed-by: jmasa

     1 /*
     2  * Copyright 2001-2006 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    20  * CA 95054 USA or visit www.sun.com if you need additional information or
    21  * have any questions.
    22  *
    23  */
    25 class ConcurrentMarkSweepGeneration;
    26 class CMSCollector;
    28 // The Concurrent Mark Sweep GC Thread (could be several in the future).
    29 class ConcurrentMarkSweepThread: public ConcurrentGCThread {
    30   friend class VMStructs;
    31   friend class ConcurrentMarkSweepGeneration;   // XXX should remove friendship
    32   friend class CMSCollector;
    33  public:
    34   virtual void run();
    36  private:
    37   static ConcurrentMarkSweepThread*     _cmst;
    38   static CMSCollector*                  _collector;
    39   static SurrogateLockerThread*         _slt;
    40   static SurrogateLockerThread::SLT_msg_type _sltBuffer;
    41   static Monitor*                       _sltMonitor;
    43   ConcurrentMarkSweepThread*            _next;
    45   static bool _should_terminate;
    47   enum CMS_flag_type {
    48     CMS_nil             = NoBits,
    49     CMS_cms_wants_token = nth_bit(0),
    50     CMS_cms_has_token   = nth_bit(1),
    51     CMS_vm_wants_token  = nth_bit(2),
    52     CMS_vm_has_token    = nth_bit(3)
    53   };
    55   static int _CMS_flag;
    57   static bool CMS_flag_is_set(int b)        { return (_CMS_flag & b) != 0;   }
    58   static bool set_CMS_flag(int b)           { return (_CMS_flag |= b) != 0;  }
    59   static bool clear_CMS_flag(int b)         { return (_CMS_flag &= ~b) != 0; }
    60   void sleepBeforeNextCycle();
    62   // CMS thread should yield for a young gen collection, direct allocation,
    63   // and iCMS activity.
    64   static char _pad_1[64 - sizeof(jint)];    // prevent cache-line sharing
    65   static volatile jint _pending_yields;
    66   static volatile jint _pending_decrements; // decrements to _pending_yields
    67   static char _pad_2[64 - sizeof(jint)];    // prevent cache-line sharing
    69   // Tracing messages, enabled by CMSTraceThreadState.
    70   static inline void trace_state(const char* desc);
    72   static volatile bool _icms_enabled;   // iCMS enabled?
    73   static volatile bool _should_run;     // iCMS may run
    74   static volatile bool _should_stop;    // iCMS should stop
    76   // debugging
    77   void verify_ok_to_terminate() const PRODUCT_RETURN;
    79  public:
    80   // Constructor
    81   ConcurrentMarkSweepThread(CMSCollector* collector);
    83   static void makeSurrogateLockerThread(TRAPS);
    84   static SurrogateLockerThread* slt() { return _slt; }
    86   // Tester
    87   bool is_ConcurrentGC_thread() const { return true;       }
    89   static void threads_do(ThreadClosure* tc);
    91   // Printing
    92   void print_on(outputStream* st) const;
    93   void print() const                                  { print_on(tty); }
    94   static void print_all_on(outputStream* st);
    95   static void print_all()                             { print_all_on(tty); }
    97   // Returns the CMS Thread
    98   static ConcurrentMarkSweepThread* cmst()    { return _cmst; }
    99   static CMSCollector*         collector()    { return _collector;  }
   101   // Create and start the CMS Thread, or stop it on shutdown
   102   static ConcurrentMarkSweepThread* start(CMSCollector* collector);
   103   static void stop();
   104   static bool should_terminate() { return _should_terminate; }
   106   // Synchronization using CMS token
   107   static void synchronize(bool is_cms_thread);
   108   static void desynchronize(bool is_cms_thread);
   109   static bool vm_thread_has_cms_token() {
   110     return CMS_flag_is_set(CMS_vm_has_token);
   111   }
   112   static bool cms_thread_has_cms_token() {
   113     return CMS_flag_is_set(CMS_cms_has_token);
   114   }
   115   static bool vm_thread_wants_cms_token() {
   116     return CMS_flag_is_set(CMS_vm_wants_token);
   117   }
   118   static bool cms_thread_wants_cms_token() {
   119     return CMS_flag_is_set(CMS_cms_wants_token);
   120   }
   122   // Wait on CMS lock until the next synchronous GC
   123   // or given timeout, whichever is earlier.
   124   void    wait_on_cms_lock(long t); // milliseconds
   126   // The CMS thread will yield during the work portion of it's cycle
   127   // only when requested to.  Both synchronous and asychronous requests
   128   // are provided.  A synchronous request is used for young gen
   129   // collections and direct allocations.  The requesting thread increments
   130   // pending_yields at the beginning of an operation, and decrements it when
   131   // the operation is completed.  The CMS thread yields when pending_yields
   132   // is positive.  An asynchronous request is used by iCMS in the stop_icms()
   133   // operation. A single yield satisfies the outstanding asynch yield requests.
   134   // The requesting thread increments both pending_yields and pending_decrements.
   135   // After yielding, the CMS thread decrements both by the amount in
   136   // pending_decrements.
   137   // Note that, while "_pending_yields >= _pending_decrements" is an invariant,
   138   // we cannot easily test that invariant, since the counters are manipulated via
   139   // atomic instructions without explicit locking and we cannot read
   140   // the two counters atomically together: one suggestion is to
   141   // use (for example) 16-bit counters so as to be able to read the
   142   // two counters atomically even on 32-bit platforms. Notice that
   143   // the second assert in acknowledge_yield_request() does indeed
   144   // check a form of the above invariant, albeit indirectly.
   146   static void increment_pending_yields()   {
   147     Atomic::inc(&_pending_yields);
   148     assert(_pending_yields >= 0, "can't be negative");
   149   }
   150   static void decrement_pending_yields()   {
   151     Atomic::dec(&_pending_yields);
   152     assert(_pending_yields >= 0, "can't be negative");
   153   }
   154   static void asynchronous_yield_request() {
   155     increment_pending_yields();
   156     Atomic::inc(&_pending_decrements);
   157     assert(_pending_decrements >= 0, "can't be negative");
   158   }
   159   static void acknowledge_yield_request() {
   160     jint decrement = _pending_decrements;
   161     if (decrement > 0) {
   162       // Order important to preserve: _pending_yields >= _pending_decrements
   163       Atomic::add(-decrement, &_pending_decrements);
   164       Atomic::add(-decrement, &_pending_yields);
   165       assert(_pending_decrements >= 0, "can't be negative");
   166       assert(_pending_yields >= 0, "can't be negative");
   167     }
   168   }
   169   static bool should_yield()   { return _pending_yields > 0; }
   171   // CMS incremental mode.
   172   static void start_icms(); // notify thread to start a quantum of work
   173   static void stop_icms();  // request thread to stop working
   174   void icms_wait();         // if asked to stop, wait until notified to start
   176   // Incremental mode is enabled globally by the flag CMSIncrementalMode.  It
   177   // must also be enabled/disabled dynamically to allow foreground collections.
   178   static inline void enable_icms()              { _icms_enabled = true; }
   179   static inline void disable_icms()             { _icms_enabled = false; }
   180   static inline void set_icms_enabled(bool val) { _icms_enabled = val; }
   181   static inline bool icms_enabled()             { return _icms_enabled; }
   182 };
   184 inline void ConcurrentMarkSweepThread::trace_state(const char* desc) {
   185   if (CMSTraceThreadState) {
   186     char buf[128];
   187     TimeStamp& ts = gclog_or_tty->time_stamp();
   188     if (!ts.is_updated()) {
   189       ts.update();
   190     }
   191     jio_snprintf(buf, sizeof(buf), " [%.3f:  CMSThread %s] ",
   192                  ts.seconds(), desc);
   193     buf[sizeof(buf) - 1] = '\0';
   194     gclog_or_tty->print(buf);
   195   }
   196 }
   198 // For scoped increment/decrement of yield requests
   199 class CMSSynchronousYieldRequest: public StackObj {
   200  public:
   201   CMSSynchronousYieldRequest() {
   202     ConcurrentMarkSweepThread::increment_pending_yields();
   203   }
   204   ~CMSSynchronousYieldRequest() {
   205     ConcurrentMarkSweepThread::decrement_pending_yields();
   206   }
   207 };
   209 // Used to emit a warning in case of unexpectedly excessive
   210 // looping (in "apparently endless loops") in CMS code.
   211 class CMSLoopCountWarn: public StackObj {
   212  private:
   213   const char* _src;
   214   const char* _msg;
   215   const intx  _threshold;
   216   intx        _ticks;
   218  public:
   219   inline CMSLoopCountWarn(const char* src, const char* msg,
   220                           const intx threshold) :
   221     _src(src), _msg(msg), _threshold(threshold), _ticks(0) { }
   223   inline void tick() {
   224     _ticks++;
   225     if (CMSLoopWarn && _ticks % _threshold == 0) {
   226       warning("%s has looped %d times %s", _src, _ticks, _msg);
   227     }
   228   }
   229 };

mercurial