Home | History | Annotate | Download | only in src
      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