1 /* 2 * Copyright 2008 Google Inc. All Rights Reserved. 3 * Author: md (at) 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 */ 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 */ 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 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 */ 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