Top


定義場所(file name)

hotspot/src/os/linux/vm/os_linux.cpp

名前(function name)

static jlong slow_thread_cpu_time(Thread *thread, bool user_sys_cpu_time) {

本体部(body)

  {- -------------------------------------------
  (1) proc ファイルシステム下の以下のファイルから CPU 使用時間情報を取得する.
        (1) もし /proc/<pid>/cpu があれば, それを使う.
        (2) (1)が存在せず, /proc/self/task/<tid>/stat があれば, それを使う.
        (3) (1)も(2)も存在しなければ, /proc/<tid>/stat を使う.
      ---------------------------------------- -}

      static bool proc_pid_cpu_avail = true;
      static bool proc_task_unchecked = true;
      static const char *proc_stat_path = "/proc/%d/stat";
      pid_t  tid = thread->osthread()->thread_id();
      int i;
      char *s;
      char stat[2048];
      int statlen;
      char proc_name[64];
      int count;
      long sys_time, user_time;
      char string[64];
      char cdummy;
      int idummy;
      long ldummy;
      FILE *fp;

      // We first try accessing /proc/<pid>/cpu since this is faster to
      // process.  If this file is not present (linux kernels 2.5 and above)
      // then we open /proc/<pid>/stat.
      if ( proc_pid_cpu_avail ) {
        sprintf(proc_name, "/proc/%d/cpu", tid);
        fp =  fopen(proc_name, "r");
        if ( fp != NULL ) {
          count = fscanf( fp, "%s %lu %lu\n", string, &user_time, &sys_time);
          fclose(fp);
          if ( count != 3 ) return -1;

          if (user_sys_cpu_time) {
            return ((jlong)sys_time + (jlong)user_time) * (1000000000 / clock_tics_per_sec);
          } else {
            return (jlong)user_time * (1000000000 / clock_tics_per_sec);
          }
        }
        else proc_pid_cpu_avail = false;
      }

      // The /proc/<tid>/stat aggregates per-process usage on
      // new Linux kernels 2.6+ where NPTL is supported.
      // The /proc/self/task/<tid>/stat still has the per-thread usage.
      // See bug 6328462.
      // There can be no directory /proc/self/task on kernels 2.4 with NPTL
      // and possibly in some other cases, so we check its availability.
      if (proc_task_unchecked && os::Linux::is_NPTL()) {
        // This is executed only once
        proc_task_unchecked = false;
        fp = fopen("/proc/self/task", "r");
        if (fp != NULL) {
          proc_stat_path = "/proc/self/task/%d/stat";
          fclose(fp);
        }
      }

      sprintf(proc_name, proc_stat_path, tid);
      fp = fopen(proc_name, "r");
      if ( fp == NULL ) return -1;
      statlen = fread(stat, 1, 2047, fp);
      stat[statlen] = '\0';
      fclose(fp);

      // Skip pid and the command string. Note that we could be dealing with
      // weird command names, e.g. user could decide to rename java launcher
      // to "java 1.4.2 :)", then the stat file would look like
      //                1234 (java 1.4.2 :)) R ... ...
      // We don't really need to know the command string, just find the last
      // occurrence of ")" and then start parsing from there. See bug 4726580.
      s = strrchr(stat, ')');
      i = 0;
      if (s == NULL ) return -1;

      // Skip blank chars
      do s++; while (isspace(*s));

      count = sscanf(s,"%c %d %d %d %d %d %lu %lu %lu %lu %lu %lu %lu",
                     &cdummy, &idummy, &idummy, &idummy, &idummy, &idummy,
                     &ldummy, &ldummy, &ldummy, &ldummy, &ldummy,
                     &user_time, &sys_time);
      if ( count != 13 ) return -1;
      if (user_sys_cpu_time) {
        return ((jlong)sys_time + (jlong)user_time) * (1000000000 / clock_tics_per_sec);
      } else {
        return (jlong)user_time * (1000000000 / clock_tics_per_sec);
      }
    }

This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.