changeset 15:6d475889590a

Bug 1428: Refactoring to get GCCause string reviewed-by: ykubota
author Yasumasa Suenaga <suenaga.yasumasa@lab.ntt.co.jp>
date Tue, 25 Jun 2013 19:53:25 +0900
parents 27a3ec638eaa
children 5a930f8c514b
files agent/ChangeLog agent/src/jvmInfo.cpp agent/src/jvmInfo.hpp agent/src/libmain.cpp agent/src/logManager.cpp agent/src/oopUtil.cpp agent/src/oopUtil.hpp agent/src/overrideFunc.S agent/src/snapShotMain.cpp agent/src/util.cpp agent/src/util.hpp
diffstat 11 files changed, 120 insertions(+), 321 deletions(-) [+]
line wrap: on
line diff
--- a/agent/ChangeLog	Mon Jun 24 18:06:21 2013 -0700
+++ b/agent/ChangeLog	Tue Jun 25 19:53:25 2013 +0900
@@ -1,3 +1,11 @@
+2013-06-25  Yasumasa Suenaga  <suenaga.yasumasa@lab.ntt.co.jp>
+
+	* Bug 1428: Refactoring to get GCCause string
+
+2013-06-25  KUBOTA Yuji  <kubota.yuji@lab.ntt.co.jp>
+
+	* Bug 1475: Some codes' line feed code are CRLF(DOS).
+
 2013-06-24  Yasumasa Suenaga  <suenaga.yasumasa@lab.ntt.co.jp>
 
 	* Bug 1485: Change the method of finding debuginfo files.
--- a/agent/src/jvmInfo.cpp	Mon Jun 24 18:06:21 2013 -0700
+++ b/agent/src/jvmInfo.cpp	Tue Jun 25 19:53:25 2013 +0900
@@ -35,7 +35,6 @@
 
 #include "jvmInfo.hpp"
 #include "util.hpp"
-#include "agentThread.hpp"
 
 #ifdef USE_VMSTRUCTS
 #include "vmStructScanner.hpp"
@@ -44,7 +43,7 @@
 /*!
  * \brief TJvmInfo constructor.
  */
-TJvmInfo::TJvmInfo(void) : TAgentThread("HeapStats JVM PerformInfo") {
+TJvmInfo::TJvmInfo(){
   
   /* Initialization. */
   _nowFGC      = NULL;
@@ -57,7 +56,6 @@
   _YGCTime     = NULL;
   _freqTime    = NULL;
   _gcCause     = NULL;
-  _lastGCCause = NULL;
   perfAddr     = 0;
   elapFGCTime  = 0;
   elapYGCTime  = 0;
@@ -111,28 +109,6 @@
   
   /* Initialize. */
   memcpy(this->gcCause, UNKNOWN_GC_CAUSE, 16);
-}
-
-/*!
- * \brief TJvmInfo destructor.
- */
-TJvmInfo::~TJvmInfo() {
-  /* Free allcated GC cause container. */
-  free(gcCause);
-}
-
-/*!
- * \brief Start parallel work by JThread.
- * \param jvmti [in] JVMTI environment object.
- * \param env   [in] JNI environment object.
- */
-void TJvmInfo::start(jvmtiEnv *jvmti, JNIEnv *env) {
-  /* Get GC information addres. */
-  #ifdef USE_VMSTRUCTS
-    this->detectInfoAddress();
-  #else
-    this->detectInfoAddress(env);
-  #endif
   
   /* Get memory function address. */
   this->maxMemFunc   = (TGetMemoryFunc)dlsym(RTLD_DEFAULT, "JVM_MaxMemory");
@@ -146,54 +122,15 @@
   if (this->totalMemFunc == NULL) {
     PRINT_WARN_MSG("Couldn't get memory function. function:JVM_TotalMemory");
   }
-  
-  /* Start JThread. */
-  TAgentThread::start(jvmti, env, TJvmInfo::entryPoint,
-                                            this, JVMTI_THREAD_MIN_PRIORITY);
+
 }
 
 /*!
- * \brief Parallel work function by JThread.
- * \param jvmti [in] JVMTI environment object.
- * \param jni   [in] JNI environment object.
- * \param data  [in] Pointer of TJvmInfo.
+ * \brief TJvmInfo destructor.
  */
-void JNICALL TJvmInfo::entryPoint(jvmtiEnv *jvmti, JNIEnv *jni, void *data) {
-  /* Get self. */
-  TJvmInfo *controller = (TJvmInfo *)data;
-  /* Change running state. */
-  controller->_isRunning = true;
-  
-  /* Loop for agent run. */
-  while (!controller->_terminateRequest) {
-    bool needProcess = false;
-    
-    ENTER_PTHREAD_SECTION(&controller->mutex) {
-      
-      /* Wait for notification or termination. */
-      pthread_cond_wait(&controller->mutexCond, &controller->mutex);
-      
-      /* If get notification */
-      if (likely(controller->_numRequests > 0)) {
-        controller->_numRequests--;
-        needProcess = true;
-      }
-      
-    } EXIT_PTHREAD_SECTION(&controller->mutex)
-    
-    /* If waiting is finished by notification. */
-    if (needProcess) {
-      /* Get delay info */
-      if (unlikely(controller->_freqTime == NULL)) {
-        controller->detectDelayInfoAddress();
-      }
-      /* Load string of GC cause. */
-      controller->loadGCCause();
-    }
-  }
-  
-  /* Change running state. */
-  controller->_isRunning = false;
+TJvmInfo::~TJvmInfo() {
+  /* Free allcated GC cause container. */
+  free(gcCause);
 }
 
 #ifdef USE_VMSTRUCTS
@@ -481,11 +418,6 @@
       /* GC cause entry. */
       this->_gcCause = (char *)(ofs + entry.data_offset);
     }
-    else if ((strcmp("sun.gc.lastCause", name) == 0)
-                                           && (entry.data_type == 'B')) {
-      /* Last GC cause entry. */
-      this->_lastGCCause = (char *)(ofs + entry.data_offset);
-    }
     else if ((strcmp("sun.rt._sync_Parks", name) == 0)
                                            && (entry.data_type == 'J')) {
       /* Monitor conflict count entry. */
@@ -568,12 +500,6 @@
                                                      " Entry:\"sun.gc.cause\"");
   }
   
-  /* If failure get last GC cause entry. */
-  if (_lastGCCause == NULL) {
-    PRINT_WARN_MSG("Necessary information isn't found in performance data."
-                                                 " Entry:\"sun.gc.lastCause\"");
-  }
-  
   /* If failure get monitor conflict count entry. */
   if (_syncPark == NULL) {
     PRINT_WARN_MSG("Necessary information isn't found in performance data."
--- a/agent/src/jvmInfo.hpp	Mon Jun 24 18:06:21 2013 -0700
+++ b/agent/src/jvmInfo.hpp	Tue Jun 25 19:53:25 2013 +0900
@@ -29,7 +29,6 @@
 #include <stdint.h>
 
 #include "util.hpp"
-#include "agentThread.hpp"
 
 
 /*!
@@ -88,29 +87,6 @@
 const static int MAXSIZE_GC_CAUSE = 80;
 
 
-/*!
- * \brief Default spin cycle for waiting to change GCCause.
- */
-#define DEFAULT_MAX_SPINS 10
-
-
-/* Characters of "No GC" */
-#ifdef WORDS_BIGENDIAN
-#define NOGC_VALUE "$0x4e6f2047"
-#else
-#define NOGC_VALUE "$0x4347206f"
-#endif
-
-/* Entry of "loadGCCause()" */
-#define loadGCCause_entry(SpinCycle, GCCauseValue) \
-  "sfence;" \
-  ".align 16;" \
-  "1: subl $0x1, " SpinCycle ";" \
-  "   jz 2f;" \
-  "   pause;" \
-  "   testl " NOGC_VALUE ", " GCCauseValue ";" \
-  "   jz 1b;"
-
 /* memcpy for gccause */
 
 /* Strcpy with AVX (80 bytes).
@@ -145,26 +121,19 @@
 /*!
  * \brief This class is used to get JVM performance information.
  */
-class TJvmInfo : public TAgentThread {
+class TJvmInfo{
   public:
     
     /*!
      * \brief TJvmInfo constructor.
      */
-    TJvmInfo(void);
+    TJvmInfo();
     /*!
      * \brief TJvmInfo destructor.
      */
     virtual ~TJvmInfo();
     
     /*!
-     * \brief Start parallel work by JThread.
-     * \param jvmti [in] JVMTI environment object.
-     * \param env   [in] JNI environment object.
-     */
-    void start(jvmtiEnv *jvmti, JNIEnv *env);
-    
-    /*!
      * \brief   Get heap memory size (New + Old)
      *          through the JVM internal function.
      * \return  Heap memory size.
@@ -222,23 +191,15 @@
      * \brief Load string of GC cause.
      */
     inline void loadGCCause(void) {
-      /* Spin-Lock. */
-      int SpinCycle = arg.maxSpins;
       
       /* If got GC cause address. */
       if(likely(this->_gcCause != NULL)){
       #ifdef AVX
         if(likely(usableAVX)){
           asm volatile(
-          /* Prepare for Spin-Lock condition. */
-            loadGCCause_entry("%0", "(%2)")
-
           /* Strcpy with AVX (80 bytes). */
-            AVX_MEMCPY_GCCAUSE("(%1)", "(%2)")
-
-          /* Exit inline assembler. */
-            "2: "
-            : "+a" (SpinCycle)
+            AVX_MEMCPY_GCCAUSE("(%0)", "(%1)")
+            :
             : "c" (this->gcCause),  /* GC Cause container. */
               "d" (this->_gcCause)  /* GC Cause address.   */
             : "cc", "%xmm2" /* ,"%ymm0", "%ymm1" */
@@ -249,15 +210,9 @@
       #ifdef SSE3
         if(likely(usableSSE3)){
           asm volatile(
-          /* Prepare for Spin-Lock condition. */
-            loadGCCause_entry("%0", "(%2)")
-
           /* Strcpy with SSE2 (80 bytes). */
-            SSE_MEMCPY_GCCAUSE("lddqu", "(%1)", "(%2)")
-
-          /* Exit inline assembler. */
-            "2: "
-            : "+a" (SpinCycle)
+            SSE_MEMCPY_GCCAUSE("lddqu", "(%0)", "(%1)")
+            :
             : "c" (this->gcCause),  /* GC Cause container. */
               "d" (this->_gcCause)  /* GC Cause address.   */
             : "cc", "%xmm0", "%xmm1"
@@ -268,15 +223,9 @@
       #ifdef SSE2
         if(likely(usableSSE2)){
           asm volatile(
-          /* Prepare for Spin-Lock condition. */
-            loadGCCause_entry("%0", "(%2)")
-
           /* Strcpy with SSE2 (80 bytes). */
-            SSE_MEMCPY_GCCAUSE("movdqu", "(%1)", "(%2)")
-
-          /* Exit inline assembler. */
-            "2: "
-            : "+a" (SpinCycle)
+            SSE_MEMCPY_GCCAUSE("movdqu", "(%0)", "(%1)")
+            :
             : "c" (this->gcCause),  /* GC Cause container. */
               "d" (this->_gcCause)  /* GC Cause address.   */
             : "cc", "%xmm0", "%xmm1"
@@ -285,74 +234,7 @@
         else
       #endif // SSE2.
         {
-          /* Default GC cause string. */
-          const char NO_GC_STR[6] = "No GC";
-          /* Get GC cause loop. */
-          for(; SpinCycle > 0; SpinCycle--){
-
-            /* If loaded GC cause. */
-            if(memcmp(this->_gcCause, NO_GC_STR, 6) != 0){
-              /* Copy and break. */
-              memcpy(this->gcCause, this->_gcCause, MAXSIZE_GC_CAUSE);
-              break;
-            }
-
-          }
-
-        }
-
-      }
-
-      /* If failure get GC cause in loop. */
-      if(unlikely(SpinCycle == 0)){
-        if(likely(_lastGCCause != NULL)){
-
-      #ifdef AVX
-          if(likely(usableAVX)){
-            asm volatile(
-            /* Strcpy with AVX (80 bytes). */
-              AVX_MEMCPY_GCCAUSE("(%0)", "(%1)")
-              : /* No input */
-              : "a" (this->gcCause),     /* GC Cause container.    */
-                "c" (this->_lastGCCause) /* Last GC Cause address. */
-              : "%xmm2" /* ,"%ymm0", "%ymm1" */
-                        );
-          }
-          else
-      #endif // AVX.
-      #ifdef SSE3
-          if(likely(usableSSE3)){
-            asm volatile(
-            /* Strcpy with AVX (80 bytes). */
-              SSE_MEMCPY_GCCAUSE("lddqu", "(%0)", "(%1)")
-              : /* No input */
-              : "a" (this->gcCause),     /* GC Cause container.    */
-                "c" (this->_lastGCCause) /* Last GC Cause address. */
-              : "%xmm0", "%xmm1"
-                        );
-          }
-          else
-      #endif // SSE3.
-      #ifdef SSE2
-          if(likely(usableSSE2)){
-            asm volatile(
-            /* Strcpy with AVX (80 bytes). */
-              SSE_MEMCPY_GCCAUSE("movdqu", "(%0)", "(%1)")
-              : /* No input  */
-              : "a" (this->gcCause),     /* GC Cause container.    */
-                "c" (this->_lastGCCause) /* Last GC Cause address. */
-              : "%xmm0", "%xmm1"
-                        );
-          }
-          else
-      #endif // SSE2.
-          {
-            /* Get GC cause from sun.gc.lastCause. */
-            memcpy(this->gcCause, this->_lastGCCause, MAXSIZE_GC_CAUSE);
-          }
-        }
-        else{
-          this->SetUnknownGCCause();
+          __builtin_memcpy(this->gcCause, this->_gcCause, MAXSIZE_GC_CAUSE);
         }
 
       }
@@ -417,15 +299,6 @@
     void detectDelayInfoAddress(void);
     
     /*!
-     * \brief Check loaded log data entries.
-     * \return Value is true, if data is loaded.<br>
-     *         Value is false, if data isn't loaded yet.
-     */
-    const inline bool isLoadedLogData(void) {
-      return (loadLogFlag && loadDelayLogFlag);
-    }
-    
-    /*!
      * \brief Get finished conflict count.
      * \return It's count of finished conflict of monitor.
      */
@@ -587,7 +460,50 @@
       return ((_tickTime == NULL) ? -1 : *_tickTime / freqTime);
     }
   
-  protected:
+  #ifdef USE_VMSTRUCTS
+    
+    /*!
+     * \brief Detect GC-informaion address.<br>
+     *        Use external VM structure.
+     * \sa "jdk/src/share/classes/sun/tools/jstat/resources/jstat_options"
+     */
+    void detectInfoAddress(void);
+  #else
+    
+    /*!
+     * \brief Detect GC-informaion address.<br>
+     *        Use performance data file.
+     * \param env [in] JNI environment object.
+     * \sa "jdk/src/share/classes/sun/tools/jstat/resources/jstat_options"
+     */
+    void detectInfoAddress(JNIEnv *env);
+  #endif
+
+    inline void SetUnknownGCCause(void){
+
+    #ifdef AVX
+      if(likely(usableAVX)){
+        asm volatile("vmovdqa   (%1), %%xmm0;"
+                     "vmovdqa %%xmm0,   (%0);"
+          : : "a" (this->gcCause), "c" (UNKNOWN_GC_CAUSE) : "%xmm0");
+      }
+      else
+    #endif // AVX.
+    #ifdef SSE2
+      if(likely(usableSSE2)){
+        asm volatile("movdqa   (%1), %%xmm0;"
+                     "movdqa %%xmm0,   (%0);"
+          : : "a" (this->gcCause), "c" (UNKNOWN_GC_CAUSE) : "%xmm0");
+      }
+      else
+    #endif // SSE2.
+      {
+        memcpy(this->gcCause, UNKNOWN_GC_CAUSE, 16);
+      }
+
+    }
+
+ protected:
     
     /*!
      * \brief Address of java.lang.getMaxMemory().
@@ -623,35 +539,7 @@
      */
     virtual ptrdiff_t getPerfMemoryAddress(JNIEnv *env);
   #endif
-    
-  #ifdef USE_VMSTRUCTS
-    
-    /*!
-     * \brief Detect GC-informaion address.<br>
-     *        Use external VM structure.
-     * \sa "jdk/src/share/classes/sun/tools/jstat/resources/jstat_options"
-     */
-    void detectInfoAddress(void);
-  #else
-    
-    /*!
-     * \brief Detect GC-informaion address.<br>
-     *        Use performance data file.
-     * \param env [in] JNI environment object.
-     * \sa "jdk/src/share/classes/sun/tools/jstat/resources/jstat_options"
-     */
-    void detectInfoAddress(JNIEnv *env);
-  #endif
-    
-    /*!
-     * \brief Parallel work function by JThread.
-     * \param jvmti [in] JVMTI environment object.
-     * \param jni   [in] JNI environment object.
-     * \param data  [in] Pointer of TJvmInfo.
-     */
-    static void JNICALL entryPoint(jvmtiEnv *jvmti, JNIEnv *jni,
-      void *data);
-    
+   
   private:
     /*!
      * \brief JVM running performance data pointer.
@@ -706,10 +594,6 @@
      */
     char *_gcCause;
     /*!
-     * \brief Last GC cause.
-     */
-    char *_lastGCCause;
-    /*!
      * \brief Stored GC cause.
      */
     char *gcCause;
@@ -794,30 +678,6 @@
      */
     jlong *_tickTime;
 
-    inline void SetUnknownGCCause(void){
-
-    #ifdef AVX
-      if(likely(usableAVX)){
-        asm volatile("vmovdqa   (%1), %%xmm0;"
-                     "vmovdqa %%xmm0,   (%0);"
-          : : "a" (this->gcCause), "c" (UNKNOWN_GC_CAUSE) : "%xmm0");
-      }
-      else
-    #endif // AVX.
-    #ifdef SSE2
-      if(likely(usableSSE2)){
-        asm volatile("movdqa   (%1), %%xmm0;"
-                     "movdqa %%xmm0,   (%0);"
-          : : "a" (this->gcCause), "c" (UNKNOWN_GC_CAUSE) : "%xmm0");
-      }
-      else
-    #endif // SSE2.
-      {
-        memcpy(this->gcCause, UNKNOWN_GC_CAUSE, 16);
-      }
-
-    }
-
 };
 
 #endif //JVMINFO_H
--- a/agent/src/libmain.cpp	Mon Jun 24 18:06:21 2013 -0700
+++ b/agent/src/libmain.cpp	Tue Jun 25 19:53:25 2013 +0900
@@ -257,6 +257,12 @@
  * \param thread [in] Java thread object.
  */
 void JNICALL OnVMInit(jvmtiEnv *jvmti, JNIEnv *env, jthread thread) {
+  /* Get GC information addres. */
+  #ifdef USE_VMSTRUCTS
+    jvmInfo->detectInfoAddress();
+  #else
+    jvmInfo->detectInfoAddress(env);
+  #endif
   
   /* If failure signal initialization. */
   if (unlikely(!TSignalManager::globalInitialize(env))) {
@@ -276,8 +282,6 @@
   
   /* Start HeapStats agent threads. */
   try {
-    jvmInfo->start(jvmti, env);
-    
     reloadSigMngr = new TSignalManager(env, &ReloadSigProc);
     
     /* Switch reload signal state. */
@@ -359,8 +363,6 @@
   /* Terminate each thread. */
   intervalSigTimer->terminate();
   
-  jvmInfo->terminate();
-  
   /* Check reload signal is enable. */
   bool enableReloadSig = (reloadSigMngr != NULL)
     && (arg.reloadSignal != NULL) && (strlen(arg.reloadSignal) > 0);
@@ -645,6 +647,8 @@
 
   /* Call live step initialization. */
   OnVMInit(jvmti, env, NULL);
+
+  jvmInfo->detectDelayInfoAddress();
   
   return SUCCESS;
 }
--- a/agent/src/logManager.cpp	Mon Jun 24 18:06:21 2013 -0700
+++ b/agent/src/logManager.cpp	Tue Jun 25 19:53:25 2013 +0900
@@ -184,13 +184,6 @@
   TLargeUInt rssize  = 0;
   TMachineTimes cpuTimes = {0};
   
-  /* Check loaded data in JVM running information. */
-  if (unlikely(!jvmInfo->isLoadedLogData())) {
-    
-    /* Load JVM running information. */
-    jvmInfo->detectDelayInfoAddress();
-  }
-  
   /* Get java process information. */
   if (unlikely(!getProcInfo(&systime, &usrtime, &vmsize, &rssize))) {
     PRINT_WARN_MSG("Failure getting java process information.");
@@ -333,13 +326,6 @@
     free(dumpName);
   }
   
-  /* Check loaded data in JVM running information. */
-  if (unlikely(!jvmInfo->isLoadedLogData())) {
-    
-    /* Load JVM running information. */
-    jvmInfo->detectDelayInfoAddress();
-  }
-  
   /* Copy gc log file. */
   if (unlikely(!copyOptionFile("-Xloggc:", (char*)basePath))) {
     PRINT_WARN_MSG("Failure copy gc log file.");
@@ -440,13 +426,6 @@
 bool TLogManager::makeEnvironFile(char *basePath,
                                      TInvokeCause cause, TMSecTime nowTime) {
   
-  /* Check loaded data in JVM running information. */
-  if (unlikely(!jvmInfo->isLoadedLogData())) {
-    
-    /* Load JVM running information. */
-    jvmInfo->detectDelayInfoAddress();
-  }
-  
   /* Invoke OS version function. */
   struct utsname uInfo;
   memset(&uInfo, 0, sizeof(struct utsname));
--- a/agent/src/oopUtil.cpp	Mon Jun 24 18:06:21 2013 -0700
+++ b/agent/src/oopUtil.cpp	Tue Jun 25 19:53:25 2013 +0900
@@ -155,6 +155,11 @@
  */
 DEFINE_OVERRIDE_FUNC_3(innerStart)
 
+/*!
+ * \brief Override function for WatcherThread.
+ */
+DEFINE_OVERRIDE_FUNC_1(watcherThread)
+
 /* Macro. */
 
 #define SELECT_HOOK_FUNCS(result, prefix) \
@@ -864,6 +869,16 @@
     HOOK_FUNC_END
 };
 
+/*!
+ * \brief Pointer of WatcherThread hook.
+ */
+THookFunctionInfo watcherThread_hook[] = {
+  HOOK_FUNC("_ZTV13WatcherThread",
+    "_ZN13WatcherThread3runEv",
+    &watcherThread_override_func_0, (void *)callbackForWatcherThreadRun),
+  HOOK_FUNC_END
+};
+
 /* Event callback for outter. */
 
 /*!
@@ -1452,7 +1467,6 @@
 
   /* If call GC function more one. */
   if(unlikely(isInvokeGCManyTimes)){
-
     /* Invoke GC interrupt callback. */
     if(likely(gcInterruptCallbackFunc != NULL)){
       gcInterruptCallbackFunc();
@@ -1463,6 +1477,15 @@
     isInvokeGCManyTimes = true;
   }
 
+  /* Get current GCCause. */
+  jvmInfo->loadGCCause();
+}
+
+/*!
+ * \brief Callback function for WatcherThread.
+ */
+extern "C" void callbackForWatcherThreadRun(void){
+  jvmInfo->detectDelayInfoAddress();
 }
 
 /* Function for pthread. */
@@ -2208,7 +2231,14 @@
   collectedHeap = (*(void**)collectedHeap);
   narrowOffsetBase = (ptrdiff_t)*(void**)narrowOffsetBase;
   
-  /* Setup for JVMTI. */
+  /* Setup for WatcherThread. */
+  if(unlikely(!setupOverrideFunction(watcherThread_hook))){
+    PRINT_WARN_MSG("Failure function overriding. func:WatcherThread");
+    return false;
+  }
+  switchOverrideFunction(watcherThread_hook, true);
+
+   /* Setup for JVMTI. */
   if (unlikely(!setupOverrideFunction(jvmti_hook))) {
     
     PRINT_WARN_MSG("Failure function overriding. func:JVMTI");
--- a/agent/src/oopUtil.hpp	Mon Jun 24 18:06:21 2013 -0700
+++ b/agent/src/oopUtil.hpp	Tue Jun 25 19:53:25 2013 +0900
@@ -384,6 +384,11 @@
  */
 extern "C" void callbackForG1FullReturn(void);
 
+/*!
+ * \brief Callback function for WatcherThread.
+ */
+extern "C" void callbackForWatcherThreadRun(void);
+
 /* Function for init/final. */
 
 /*!
--- a/agent/src/overrideFunc.S	Mon Jun 24 18:06:21 2013 -0700
+++ b/agent/src/overrideFunc.S	Tue Jun 25 19:53:25 2013 +0900
@@ -704,6 +704,10 @@
 /* GenCollectedHeap::gc_prologue(bool) */
 OVERRIDE_CALLBACK_DEFINE(innerStart, 2, callbackForInnerGCStart)
 
+/* For WatcherThread */
+/* WatcherThread::run() */
+OVERRIDE_CALLBACK_DEFINE(watcherThread, 0, callbackForWatcherThreadRun)
+
 
 #ifdef AVOID__i686
 	/* Define again. */
--- a/agent/src/snapShotMain.cpp	Mon Jun 24 18:06:21 2013 -0700
+++ b/agent/src/snapShotMain.cpp	Tue Jun 25 19:53:25 2013 +0900
@@ -212,9 +212,6 @@
   /* Standby for next GC. */
   jvmInfo->resumeGCinfo();
 
-  /* Send "order of load GC-cause" notification. */
-  jvmInfo->notify();
-
   /* Clear unfinished snapshot data. */
   snapshotByGC->clear();
 }
@@ -225,8 +222,6 @@
  * \param jvmti [in] JVMTI environment object.
  */
 void JNICALL OnGarbageCollectionStart(jvmtiEnv *jvmti) {
-  /* Send "order of load GC-cause" notification. */
-  jvmInfo->notify();
   snapshotByGC = TSnapShotContainer::getInstance();
 
   /* Enable inner GC event. */
@@ -257,6 +252,9 @@
  * \brief After G1 garbage collection event.
  */
 void OnG1GarbageCollectionFinish(void) {
+  //jvmInfo->loadGCCause();
+  jvmInfo->SetUnknownGCCause();
+
   /* Set information and push waiting queue. */
   outputSnapShotByGC(snapshotByGC);
   snapshotByGC = TSnapShotContainer::getInstance();
@@ -376,9 +374,6 @@
     }
   }
   
-  /* Send "order of load GC-cause" notification. */
-  jvmInfo->notify();
-  
   if(likely(snapshotByGC == NULL)){
     snapshotByGC = TSnapShotContainer::getInstance();
   }
--- a/agent/src/util.cpp	Mon Jun 24 18:06:21 2013 -0700
+++ b/agent/src/util.cpp	Tue Jun 25 19:53:25 2013 +0900
@@ -166,7 +166,6 @@
   arg.snmpComName        = strdup("public");
   arg.logDir             = strdup("./tmp");
   arg.archiveCommand     = strdup("/usr/bin/zip %archivefile% -jr %logdir%");
-  arg.maxSpins           = DEFAULT_MAX_SPINS;
 }
 
 /*!
@@ -225,7 +224,6 @@
   newArg->logSignalNormal    = oldArg->logSignalNormal;
   newArg->logSignalAll       = oldArg->logSignalAll;
   newArg->reloadSignal       = oldArg->reloadSignal;
-  newArg->maxSpins           = oldArg->maxSpins;
 
   /* Swap setting. */
   oldArg->logSignalNormal = swapArg.logSignalNormal;
@@ -585,10 +583,6 @@
           free(arg.archiveCommand);
           arg.archiveCommand = strdup(value);
         }
-        else if(strcmp(key, "max_spins") == 0){
-          arg.maxSpins = ReadLongValue(
-               key, value, arg.maxSpins, INT_MAX);
-        }
         else{
           PRINT_WARN_MSG_HEADER
             << "Unknown configuration name. name:" << key
@@ -802,11 +796,6 @@
     << ((arg.archiveCommand != NULL) ? arg.archiveCommand : EMPTY_STR)
     << "\"" << NEWLINE;
 
-  /* Output max spin count if this value is not default. */
-  if(arg.maxSpins != DEFAULT_MAX_SPINS){
-    PRINT_INFO_MSG_HEADER_NOIF << "Max spin count = " << arg.maxSpins << NEWLINE;
-  }
-
 }
 
 /*!
--- a/agent/src/util.hpp	Mon Jun 24 18:06:21 2013 -0700
+++ b/agent/src/util.hpp	Tue Jun 25 19:53:25 2013 +0900
@@ -271,7 +271,6 @@
   char* snmpComName;       /*!< SNMP trap community name.                   */
   char* logDir;            /*!< Path of working directory for log archive.  */
   char* archiveCommand;    /*!< Command was execute to making log archive.  */
-  int maxSpins;            /*!< Max spin count for getting gccause string.  */
 } TArguments;
 
 /*!