1 /*
2 * Copyright 2008 Google Inc. All Rights Reserved.
3 * Author: md@google.com (Michael Davidson)
4 */
5 #define _GNU_SOURCE /* for cpu_set macros */
6
7 #include <sched.h>
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include "cpuset.h"
11 #include "logging.h"
12
13 /*
14 * Return the number of cpus in a cpu_set
15 */
count_cpus(const cpu_set_t * cpus)16 int count_cpus(const cpu_set_t *cpus)
17 {
18 int count = 0;
19 int cpu;
20
21 for (cpu = 0; cpu < CPU_SETSIZE; cpu++)
22 if (CPU_ISSET(cpu, cpus))
23 ++count;
24
25 return count;
26 }
27
28 /*
29 * Parse a string containing a comma separated list of ranges
30 * of cpu numbers such as: "0,2,4-7" into a cpu_set_t.
31 */
parse_cpu_set(const char * s,cpu_set_t * cpus)32 int parse_cpu_set(const char *s, cpu_set_t *cpus)
33 {
34 CPU_ZERO(cpus);
35
36 while (*s) {
37 char *next;
38 int cpu;
39 int start, end;
40
41 start = end = (int)strtol(s, &next, 0);
42 if (s == next)
43 break;
44 s = next;
45
46 if (*s == '-') {
47 ++s;
48 end = (int)strtol(s, &next, 0);
49 if (s == next)
50 break;
51 s = next;
52 }
53
54 if (*s == ',')
55 ++s;
56
57 if (start < 0 || start >= CPU_SETSIZE) {
58 ERROR(0, "bad cpu number '%d' in cpu set", start);
59 return 1;
60 }
61
62 if (end < 0 || end >= CPU_SETSIZE) {
63 ERROR(0, "bad cpu number '%d' in cpu set", end);
64 return 1;
65 }
66
67 if (end < start) {
68 ERROR(0, "bad range '%d-%d' in cpu set", start, end);
69 return 1;
70 }
71
72 for (cpu = start; cpu <= end; ++cpu)
73 CPU_SET(cpu, cpus);
74
75 }
76
77 if (*s) {
78 ERROR(0, "unexpected character '%c' in cpu set", *s);
79 return 1;
80 }
81
82 return 0;
83 }
84
85
show_range(char * buf,size_t len,const char * prefix,int start,int end)86 static int show_range(char *buf, size_t len, const char *prefix,
87 int start, int end)
88 {
89 int n;
90
91 if (start == end)
92 n = snprintf(buf, len, "%s%d", prefix, start);
93 else
94 n = snprintf(buf, len, "%s%d-%d", prefix, start, end);
95
96 if (n < len)
97 return n;
98
99 return -1;
100 }
101
102 /*
103 * Turn a cpu_set_t into a human readable string containing a
104 * comma separated list of ranges of cpu numbers.
105 *
106 * Returns the number of bytes written to the buffer,
107 * not including the terminating '\0' character,
108 * or -1 if there was not enough space in the buffer.
109 */
show_cpu_set(char * buf,size_t len,const cpu_set_t * cpus)110 int show_cpu_set(char *buf, size_t len, const cpu_set_t *cpus)
111 {
112 char *bufp = buf;
113 int start = -1;
114 int end = -1;
115 char *sep = "";
116 int cpu;
117
118 for (cpu = 0; cpu < CPU_SETSIZE; cpu++) {
119 if (CPU_ISSET(cpu, cpus)) {
120 if (start < 0)
121 start = cpu;
122 end = cpu;
123 } else if (start >= 0) {
124 int n;
125 if ((n = show_range(bufp, len, sep, start, end)) < 0)
126 return -1;
127 len -= n;
128 bufp += n;
129 sep = ",";
130 start = end = -1;
131 }
132 }
133
134 if (start >= 0) {
135 int n;
136 if ((n = show_range(bufp, len, sep, start, end)) < 0)
137 return -1;
138 bufp += n;
139 }
140
141 return bufp - buf;
142 }
143