TaskStatInfo parseStatFile()

in cpp/counters/ProcFs.cpp [164:270]


TaskStatInfo parseStatFile(char* data, size_t size, uint32_t stats_mask) {
  const char* end = (data + size);

  data = skipUntil(data, end, ' '); // pid
  data = skipUntil(data, end, ')'); // name
  data = skipUntil(data, end, ' '); // space after name
  char state = *data; // state

  data = skipUntil(data, end, ' '); // state

  data = skipUntil(data, end, ' '); // ppid
  data = skipUntil(data, end, ' '); // pgrp
  data = skipUntil(data, end, ' '); // session
  data = skipUntil(data, end, ' '); // tty_nr
  data = skipUntil(data, end, ' '); // tpgid

  data = skipUntil(data, end, ' '); // flags

  char* endptr = nullptr;
  auto minflt = parse_ull(data, &endptr); // minflt
  if (errno == ERANGE || data == endptr || endptr > end) {
    throw std::runtime_error("Could not parse minflt");
  }
  data = skipUntil(endptr, end, ' ');

  data = skipUntil(data, end, ' '); // cminflt

  endptr = nullptr;
  auto majflt = parse_ull(data, &endptr); // majflt
  if (errno == ERANGE || data == endptr || endptr > end) {
    throw std::runtime_error("Could not parse majflt");
  }
  data = skipUntil(endptr, end, ' ');

  data = skipUntil(data, end, ' '); // cmajflt

  endptr = nullptr;
  auto utime = parse_ull(data, &endptr); // utime
  if (errno == ERANGE || data == endptr || endptr > end) {
    throw std::runtime_error("Could not parse utime");
  }
  data = skipUntil(endptr, end, ' ');

  endptr = nullptr;
  auto stime = parse_ull(data, &endptr); // stime
  if (errno == ERANGE || data == endptr || endptr > end) {
    throw std::runtime_error("Could not parse stime");
  }
  data = skipUntil(endptr, end, ' ');

  data = skipUntil(data, end, ' '); // cutime
  data = skipUntil(data, end, ' '); // cstime

  endptr = nullptr;
  auto priority = strtol(data, &endptr, 10); // priority
  if (errno == ERANGE || data == endptr || endptr > end) {
    throw std::runtime_error("Could not parse priority");
  }

  int cpuNum = 0;
  if (StatType::CPU_NUM & stats_mask) {
    data = skipUntil(endptr, end, ' ');

    data = skipUntil(data, end, ' '); // nice
    data = skipUntil(data, end, ' '); // num_threads
    data = skipUntil(data, end, ' '); // itrealvalue
    data = skipUntil(data, end, ' '); // starttime

    data = skipUntil(data, end, ' '); // vsize
    data = skipUntil(data, end, ' '); // rss
    data = skipUntil(data, end, ' '); // rsslim
    data = skipUntil(data, end, ' '); // startcode
    data = skipUntil(data, end, ' '); // endcode
    data = skipUntil(data, end, ' '); // startstack
    data = skipUntil(data, end, ' '); // kstkesp
    data = skipUntil(data, end, ' '); // kstkeip

    data = skipUntil(data, end, ' '); // signal
    data = skipUntil(data, end, ' '); // blocked
    data = skipUntil(data, end, ' '); // sigignore
    data = skipUntil(data, end, ' '); // sigcatch
    data = skipUntil(data, end, ' '); // wchan
    data = skipUntil(data, end, ' '); // nswap
    data = skipUntil(data, end, ' '); // cnswap
    data = skipUntil(data, end, ' '); // exit_signal
    endptr = nullptr;
    cpuNum = strtol(data, &endptr, 10); // processor
    if (errno == ERANGE || data == endptr || endptr > end) {
      throw std::runtime_error("Could not parse cpu num");
    }
  }

  // SYSTEM_CLK_TCK is defined as 100 in linux as is unchanged in android.
  // Therefore there are 10 milli seconds in each clock tick.
  static int kClockTicksMs = systemClockTickIntervalMs();

  TaskStatInfo info{};
  info.cpuTime = kClockTicksMs * (utime + stime);
  info.kernelCpuTimeMs = kClockTicksMs * stime;
  info.state = convertCharToStateEnum(state);
  info.majorFaults = majflt;
  info.minorFaults = minflt;
  info.cpuNum = cpuNum;
  info.threadPriority = priority;

  return info;
}