<commit_before>/**
 * Implementation that uses MSRs directly.
 *
 * See the Intel 64 and IA-32 Architectures Software Developer's Manual for MSR
 * register bit fields.
 *
 * @author <NAME>
 * @date 2016-10-19
 */
// for popen, pread, pwrite
#define _POSIX_C_SOURCE 200809L
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/sysinfo.h>
#include <sys/types.h>
#include <unistd.h>
#include "raplcap.h"
#define RAPLCAP_IMPL "raplcap-msr"
#include "raplcap-common.h"

#define MSR_RAPL_POWER_UNIT       0x606
/* Package RAPL Domain */
#define MSR_PKG_POWER_LIMIT       0x610
/* PP0 RAPL Domain */
#define MSR_PP0_POWER_LIMIT       0x638
/* PP1 RAPL Domain, may reflect to uncore devices */
#define MSR_PP1_POWER_LIMIT       0x640
/* DRAM RAPL Domain */
#define MSR_DRAM_POWER_LIMIT      0x618
/* Platform (PSys) Domain (Skylake and newer) */
#define MSR_PLATFORM_POWER_LIMIT  0x65C

typedef struct raplcap_msr {
  int* fds;
  // assuming consistent unit values between sockets
  double power_units;
  double time_units;
} raplcap_msr;

static raplcap rc_default;

static int open_msr(uint32_t core) {
  char msr_filename[32];
  // first try using the msr_safe kernel module
  snprintf(msr_filename, sizeof(msr_filename), "/dev/cpu/%"PRIu32"/msr_safe", core);
  int fd = open(msr_filename, O_RDWR);
  if (fd < 0) {
    raplcap_perror(DEBUG, msr_filename);
    raplcap_log(INFO, "msr-safe not available, falling back on standard msr\n");
    // fall back on the standard msr kernel module
    snprintf(msr_filename, sizeof(msr_filename), "/dev/cpu/%"PRIu32"/msr", core);
    fd = open(msr_filename, O_RDWR);
    if (fd < 0) {
      raplcap_perror(ERROR, msr_filename);
      if (errno == ENOENT) {
        raplcap_log(WARN, "Is the msr kernel module loaded?\n");
      }
    }
  }
  return fd;
}

static int read_msr_by_offset(int fd, off_t msr, uint64_t* data) {
  assert(msr >= 0);
  assert(data != NULL);
  if (pread(fd, data, sizeof(uint64_t), msr) == sizeof(uint64_t)) {
    raplcap_log(DEBUG, "read_msr_by_offset: msr=0x%lX, data=0x%016lX\n", msr, *data);
    return 0;
  }
  raplcap_log(ERROR, "read_msr_by_offset(0x%lX): pread: %s\n", msr, strerror(errno));
  return -1;
}

static int write_msr_by_offset(int fd, off_t msr, uint64_t data) {
  assert(msr >= 0);
  raplcap_log(DEBUG, "write_msr_by_offset: msr=0x%lX, data=0x%016lX\n", msr, data);
  if (pwrite(fd, &data, sizeof(uint64_t), msr) == sizeof(uint64_t)) {
    return 0;
  }
  raplcap_log(ERROR, "write_msr_by_offset(0x%lX): pwrite: %s\n", msr, strerror(errno));
  return -1;
}

static off_t zone_to_msr_offset(raplcap_zone zone) {
  switch (zone) {
    case RAPLCAP_ZONE_PACKAGE:
      return MSR_PKG_POWER_LIMIT;
    case RAPLCAP_ZONE_CORE:
      return MSR_PP0_POWER_LIMIT;
    case RAPLCAP_ZONE_UNCORE:
      return MSR_PP1_POWER_LIMIT;
    case RAPLCAP_ZONE_DRAM:
      return MSR_DRAM_POWER_LIMIT;
    case RAPLCAP_ZONE_PSYS:
      return MSR_PLATFORM_POWER_LIMIT;
    default:
      raplcap_log(ERROR, "zone_to_msr_offset: Unknown zone: %d\n", zone);
      errno = EINVAL;
      return -1;
  }
}

static uint32_t count_sockets(void) {
  uint32_t sockets = 0;
  int err_save;
  char output[32];
  // pretty hacky, but seems to work
  FILE* fp = popen("egrep 'physical id' /proc/cpuinfo | sort -u | cut -d : -f 2 | awk '{print $1}' | tail -n 1", "r");
  if (fp == NULL) {
    raplcap_perror(ERROR, "count_sockets: popen");
  } else {
    while (fgets(output, sizeof(output), fp) != NULL) {
      errno = 0;
      sockets = strtoul(output, NULL, 0) + 1;
      if (errno) {
        raplcap_perror(ERROR, "count_sockets: strtoul");
        sockets = 0;
        break;
      }
    }
    // preserve any error
    err_save = errno;
    if (pclose(fp)) {
      raplcap_perror(WARN, "count_sockets: pclose");
    }
    errno = err_save;
  }
  raplcap_log(DEBUG, "count_sockets: sockets=%"PRIu32"\n", sockets);
  return sockets;
}

// Note: doesn't close previously opened file descriptors if one fails to open
static int raplcap_open_msrs(uint32_t sockets, int* fds) {
  // need to find a core for each socket
  assert(sockets > 0);
  assert(fds != NULL);
  uint32_t coreids[sockets];
  int coreids_found[sockets];
  char output[32];
  uint32_t socket;
  uint32_t core;
  uint32_t i;
  // this is REALLY hacky... I'm so sorry. --CKI, 10/22/16
  FILE* fp = popen("egrep 'processor|core id|physical id' /proc/cpuinfo | cut -d : -f 2 | paste - - -  | awk '{print $2 \" \" $1}'", "r");
  if (fp == NULL) {
    raplcap_perror(ERROR, "raplcap_open_msrs: popen");
    return -1;
  }
  memset(coreids, 0, sockets * sizeof(uint32_t));
  memset(coreids_found, 0, sockets * sizeof(int));
  // first column of the output is the socket, second column is the core id
  while (fgets(output, sizeof(output), fp) != NULL) {
    if (sscanf(output, "%"PRIu32" %"PRIu32, &socket, &core) != 2) {
      raplcap_log(ERROR, "raplcap_open_msrs: Failed to parse socket to MSR mapping\n");
      if (pclose(fp)) {
        raplcap_perror(WARN, "raplcap_open_msrs: pclose");
      }
      errno = ENOENT;
      return -1;
    }
    if (socket >= sockets) {
      raplcap_log(ERROR, "raplcap_open_msrs: Socket %"PRIu32" is outside range [0, %"PRIu32")\n", socket, sockets);
      if (pclose(fp)) {
        raplcap_perror(WARN, "raplcap_open_msrs: pclose");
      }
      errno = EINVAL;
      return -1;
    }
    // keep the smallest core value (ideally maps to the first physical core on the socket)
    if (!coreids_found[socket] || core < coreids[socket]) {
      coreids_found[socket] = 1;
      coreids[socket] = core;
    }
  }
  if (pclose(fp)) {
    raplcap_perror(WARN, "raplcap_open_msrs: pclose");
  }
  // verify that we found a MSR for each socket
  for (i = 0; i < sockets; i++) {
    if (!coreids_found[i]) {
      raplcap_log(ERROR, "raplcap_open_msrs: No MSR found for socket %"PRIu32"\n", i);
      errno = ENOENT;
      return -1;
    }
  }
  // now open the MSR for each core
  for (i = 0; i < sockets; i++) {
    if ((fds[i] = open_msr(coreids[i])) < 0) {
      return -1;
    }
  }
  return 0;
}

static uint64_t pow2_u64(uint64_t y) {
  // 2^y
  return ((uint64_t) 1) << y;
}

int raplcap_init(raplcap* rc) {
  if (rc == NULL) {
    rc = &rc_default;<commit_msg>Added debug log messages to parsing of /proc/cpuinfo<commit_after>/**
 * Implementation that uses MSRs directly.
 *
 * See the Intel 64 and IA-32 Architectures Software Developer's Manual for MSR
 * register bit fields.
 *
 * @author <NAME>
 * @date 2016-10-19
 */
// for popen, pread, pwrite
#define _POSIX_C_SOURCE 200809L
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/sysinfo.h>
#include <sys/types.h>
#include <unistd.h>
#include "raplcap.h"
#define RAPLCAP_IMPL "raplcap-msr"
#include "raplcap-common.h"

#define MSR_RAPL_POWER_UNIT       0x606
/* Package RAPL Domain */
#define MSR_PKG_POWER_LIMIT       0x610
/* PP0 RAPL Domain */
#define MSR_PP0_POWER_LIMIT       0x638
/* PP1 RAPL Domain, may reflect to uncore devices */
#define MSR_PP1_POWER_LIMIT       0x640
/* DRAM RAPL Domain */
#define MSR_DRAM_POWER_LIMIT      0x618
/* Platform (PSys) Domain (Skylake and newer) */
#define MSR_PLATFORM_POWER_LIMIT  0x65C

typedef struct raplcap_msr {
  int* fds;
  // assuming consistent unit values between sockets
  double power_units;
  double time_units;
} raplcap_msr;

static raplcap rc_default;

static int open_msr(uint32_t core) {
  char msr_filename[32];
  // first try using the msr_safe kernel module
  snprintf(msr_filename, sizeof(msr_filename), "/dev/cpu/%"PRIu32"/msr_safe", core);
  int fd = open(msr_filename, O_RDWR);
  if (fd < 0) {
    raplcap_perror(DEBUG, msr_filename);
    raplcap_log(INFO, "msr-safe not available, falling back on standard msr\n");
    // fall back on the standard msr kernel module
    snprintf(msr_filename, sizeof(msr_filename), "/dev/cpu/%"PRIu32"/msr", core);
    fd = open(msr_filename, O_RDWR);
    if (fd < 0) {
      raplcap_perror(ERROR, msr_filename);
      if (errno == ENOENT) {
        raplcap_log(WARN, "Is the msr kernel module loaded?\n");
      }
    }
  }
  return fd;
}

static int read_msr_by_offset(int fd, off_t msr, uint64_t* data) {
  assert(msr >= 0);
  assert(data != NULL);
  if (pread(fd, data, sizeof(uint64_t), msr) == sizeof(uint64_t)) {
    raplcap_log(DEBUG, "read_msr_by_offset: msr=0x%lX, data=0x%016lX\n", msr, *data);
    return 0;
  }
  raplcap_log(ERROR, "read_msr_by_offset(0x%lX): pread: %s\n", msr, strerror(errno));
  return -1;
}

static int write_msr_by_offset(int fd, off_t msr, uint64_t data) {
  assert(msr >= 0);
  raplcap_log(DEBUG, "write_msr_by_offset: msr=0x%lX, data=0x%016lX\n", msr, data);
  if (pwrite(fd, &data, sizeof(uint64_t), msr) == sizeof(uint64_t)) {
    return 0;
  }
  raplcap_log(ERROR, "write_msr_by_offset(0x%lX): pwrite: %s\n", msr, strerror(errno));
  return -1;
}

static off_t zone_to_msr_offset(raplcap_zone zone) {
  switch (zone) {
    case RAPLCAP_ZONE_PACKAGE:
      return MSR_PKG_POWER_LIMIT;
    case RAPLCAP_ZONE_CORE:
      return MSR_PP0_POWER_LIMIT;
    case RAPLCAP_ZONE_UNCORE:
      return MSR_PP1_POWER_LIMIT;
    case RAPLCAP_ZONE_DRAM:
      return MSR_DRAM_POWER_LIMIT;
    case RAPLCAP_ZONE_PSYS:
      return MSR_PLATFORM_POWER_LIMIT;
    default:
      raplcap_log(ERROR, "zone_to_msr_offset: Unknown zone: %d\n", zone);
      errno = EINVAL;
      return -1;
  }
}

static uint32_t count_sockets(void) {
  uint32_t sockets = 0;
  int err_save;
  char output[32];
  // pretty hacky, but seems to work
  FILE* fp = popen("egrep 'physical id' /proc/cpuinfo | sort -u | cut -d : -f 2 | awk '{print $1}' | tail -n 1", "r");
  if (fp == NULL) {
    raplcap_perror(ERROR, "count_sockets: popen");
  } else {
    while (fgets(output, sizeof(output), fp) != NULL) {
      errno = 0;
      sockets = strtoul(output, NULL, 0) + 1;
      if (errno) {
        raplcap_perror(ERROR, "count_sockets: strtoul");
        sockets = 0;
        break;
      }
    }
    // preserve any error
    err_save = errno;
    if (pclose(fp)) {
      raplcap_perror(WARN, "count_sockets: pclose");
    }
    errno = err_save;
  }
  raplcap_log(DEBUG, "count_sockets: sockets=%"PRIu32"\n", sockets);
  return sockets;
}

// Note: doesn't close previously opened file descriptors if one fails to open
static int raplcap_open_msrs(uint32_t sockets, int* fds) {
  // need to find a core for each socket
  assert(sockets > 0);
  assert(fds != NULL);
  uint32_t coreids[sockets];
  int coreids_found[sockets];
  char output[32];
  uint32_t socket;
  uint32_t core;
  uint32_t i;
  // this is REALLY hacky... I'm so sorry. --CKI, 10/22/16
  FILE* fp = popen("egrep 'processor|core id|physical id' /proc/cpuinfo | cut -d : -f 2 | paste - - -  | awk '{print $2 \" \" $1}'", "r");
  if (fp == NULL) {
    raplcap_perror(ERROR, "raplcap_open_msrs: popen");
    return -1;
  }
  memset(coreids, 0, sockets * sizeof(uint32_t));
  memset(coreids_found, 0, sockets * sizeof(int));
  // first column of the output is the socket, second column is the core id
  while (fgets(output, sizeof(output), fp) != NULL) {
    if (sscanf(output, "%"PRIu32" %"PRIu32, &socket, &core) != 2) {
      raplcap_log(ERROR, "raplcap_open_msrs: Failed to parse socket to MSR mapping\n");
      if (pclose(fp)) {
        raplcap_perror(WARN, "raplcap_open_msrs: pclose");
      }
      errno = ENOENT;
      return -1;
    }
    raplcap_log(DEBUG, "raplcap_open_msrs: Found mapping: socket %"PRIu32", core %"PRIu32"\n", socket, core);
    if (socket >= sockets) {
      raplcap_log(ERROR, "raplcap_open_msrs: Socket %"PRIu32" is outside range [0, %"PRIu32")\n", socket, sockets);
      if (pclose(fp)) {
        raplcap_perror(WARN, "raplcap_open_msrs: pclose");
      }
      errno = EINVAL;
      return -1;
    }
    // keep the smallest core value (ideally maps to the first physical core on the socket)
    if (!coreids_found[socket] || core < coreids[socket]) {
      coreids_found[socket] = 1;
      coreids[socket] = core;
    }
  }
  if (pclose(fp)) {
    raplcap_perror(WARN, "raplcap_open_msrs: pclose");
  }
  // verify that we found a MSR for each socket
  for (i = 0; i < sockets; i++) {
    if (!coreids_found[i]) {
      raplcap_log(ERROR, "raplcap_open_msrs: No MSR found for socket %"PRIu32"\n", i);
      errno = ENOENT;
      return -1;
    }
  }
  // now open the MSR for each core
  for (i = 0; i < sockets; i++) {
    raplcap_log(DEBUG, "raplcap_open_msrs: Using mapping: socket %"PRIu32", core %"PRIu32"\n", i, coreids[i]);
    if ((fds[i] = open_msr(coreids[i])) < 0) {
      return -1;
    }
  }
  return 0;
}

static uint64_t pow2_u64(uint64_t y) {
  // 2^y
  return ((uint64_t) 1) << y;
}

int raplcap_init(raplcap* rc) {
  if (rc == NULL) {
    rc = &rc_default;
{'fraction_non_alphanumeric': 0.13554356206630686, 'fraction_numerical': 0.02575173477255204, 'mean_word_length': 3.364401076716016, 'pattern_counts': {'":': 0, '<': 45, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '185075', 'n_tokens_mistral': 5380, 'n_tokens_neox': 5165, 'n_words': 1266}