File: rapl-set.c

package info (click to toggle)
powercap 0.1.1-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 336 kB
  • sloc: ansic: 2,890; makefile: 6
file content (159 lines) | stat: -rw-r--r-- 5,110 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/**
 * Set RAPL values.
 *
 * @author Connor Imes
 * @date 2017-08-24
 */
#include <errno.h>
#include <getopt.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include "powercap-rapl-sysfs.h"
#include "util-common.h"

static const char short_options[] = "hp:z:c:e:l:s:";
static const struct option long_options[] = {
  {"help",                no_argument,        NULL, 'h'},
  {"package",             required_argument,  NULL, 'p'},
  {"subzone",             required_argument,  NULL, 'z'},
  {"constraint",          required_argument,  NULL, 'c'},
  {"z-enabled",           required_argument,  NULL, 'e'},
  {"c-power-limit",       required_argument,  NULL, 'l'},
  {"c-time-window",       required_argument,  NULL, 's'},
  {0, 0, 0, 0}
};

static void print_usage(void) {
  printf("Usage: rapl-set [OPTION]...\n");
  printf("Options:\n");
  printf("  -h, --help                   Print this message and exit\n");
  printf("  -p, --package=PACKAGE        The package number (0 by default)\n");
  printf("  -z, --subzone=SUBZONE        The package subzone number (none by default)\n");
  printf("  -c, --constraint=CONSTRAINT  The constraint number (none by default)\n");
  printf("The following is a zone-level argument (-z/--subzone is optional):\n");
  printf("  -e, --z-enabled=1|0          Enable/disable a zone\n");
  printf("The following constraint-level arguments may be used together and require -c/--constraint (-z/--subzone is optional):\n");
  printf("  -l, --c-power-limit=UW       Set constraint power limit\n");
  printf("  -s, --c-time-window=US       Set constraint time window\n");
  printf("\nA package is a zone with constraints.\n");
  printf("Subzones are a package's child domains, including power planes.\n");
  printf("\nPower units: microwatts (uW)\n");
  printf("Time units: microseconds (us)\n");
}

static void print_common_help(void) {
  printf("Considerations for common errors:\n");
  printf("- Ensure that the intel_rapl kernel module is loaded\n");
  printf("- Ensure that you run with administrative (super-user) privileges\n");
}

int main(int argc, char** argv) {
  u32_param package = {0, 0};
  u32_param subzone = {0, 0};
  u32_param constraint = {0, 0};
  u32_param enabled = {0, 0};
  u64_param power_limit = {0, 0};
  u64_param time_window = {0, 0};
  int c;
  int cont = 1;
  int ret = 0;

  /* Parse command-line arguments */
  while (cont) {
    c = getopt_long(argc, argv, short_options, long_options, NULL);
    switch (c) {
    case -1:
      cont = 0;
      break;
    case 'h':
      print_usage();
      return 0;
    case 'p':
      ret = set_u32_param(&package, optarg, &cont);
      break;
    case 'z':
      ret = set_u32_param(&subzone, optarg, &cont);
      break;
    case 'c':
      ret = set_u32_param(&constraint, optarg, &cont);
      break;
    case 'e':
      ret = set_u32_param(&enabled, optarg, &cont);
      break;
    case 'l':
      ret = set_u64_param(&power_limit, optarg, &cont);
      break;
    case 's':
      ret = set_u64_param(&time_window, optarg, &cont);
      break;
    case '?':
    default:
      cont = 0;
      ret = -EINVAL;
      break;
    }
  }

  /* Verify argument combinations */
  if (ret) {
    fprintf(stderr, "Invalid arguments\n");
  } else if (constraint.set && !(power_limit.set || time_window.set)) {
    fprintf(stderr, "Must set at least one constraint-level argument when using -c/--constraint\n");
    ret = -EINVAL;
  } else if (!constraint.set && (power_limit.set || time_window.set)) {
    fprintf(stderr, "Must specify -c/--constraint when using constraint-level arguments\n");
    ret = -EINVAL;
  } else if (!(enabled.set || power_limit.set || time_window.set)) {
    printf("Nothing to do\n");
    ret = -EINVAL;
  }
  if (ret) {
    print_usage();
    return ret;
  }

  /* Check if package/subzone/constraint exist */
  if (rapl_sysfs_pkg_exists(package.val)) {
    fprintf(stderr, "Package does not exist\n");
    ret = -EINVAL;
  } else if (subzone.set && rapl_sysfs_sz_exists(package.val, subzone.val)) {
    fprintf(stderr, "Subzone does not exist\n");
    ret = -EINVAL;
  } else if (constraint.set && rapl_sysfs_constraint_exists(package.val, subzone.val, subzone.set, constraint.val)) {
    fprintf(stderr, "Constraint does not exist\n");
    ret = -EINVAL;
  }
  if (ret) {
    print_common_help();
    return ret;
  }

  /* Perform requested action(s) */
  if (enabled.set) {
    c = rapl_sysfs_zone_set_enabled(package.val, subzone.val, subzone.set, enabled.val);
    if (c) {
      perror("Error setting enabled/disabled");
      ret |= c;
    }
  }
  if (power_limit.set) {
    c = rapl_sysfs_constraint_set_power_limit_uw(package.val, subzone.val, subzone.set, constraint.val, power_limit.val);
    if (c) {
      perror("Error setting power limit");
      ret |= c;
    }
  }
  if (time_window.set) {
    c = rapl_sysfs_constraint_set_time_window_us(package.val, subzone.val, subzone.set, constraint.val, time_window.val);
    if (c) {
      perror("Error setting time window");
      ret |= c;
    }
  }
  if (ret) {
    print_common_help();
  }

  return ret;
}