aboutsummaryrefslogtreecommitdiff
path: root/client/tests/monotonic_time/src/cpuset.c
blob: 490cf1bb31201cd1a3c9e3ca99b3b7d89fd99901 (plain)
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
/*
 * Copyright 2008 Google Inc. All Rights Reserved.
 * Author: md@google.com (Michael Davidson)
 */
#define _GNU_SOURCE	/* for cpu_set macros */

#include <sched.h>
#include <stdlib.h>
#include <stdio.h>
#include "cpuset.h"
#include "logging.h"

/*
 * Return the number of cpus in a cpu_set
 */
int count_cpus(const cpu_set_t *cpus)
{
	int	count	= 0;
	int	cpu;

	for (cpu = 0; cpu < CPU_SETSIZE; cpu++)
		if (CPU_ISSET(cpu, cpus))
			++count;

	return count;
}

/*
 * Parse a string containing a comma separated list of ranges
 * of cpu numbers such as: "0,2,4-7" into a cpu_set_t.
 */
int parse_cpu_set(const char *s, cpu_set_t *cpus)
{
	CPU_ZERO(cpus);

	while (*s) {
		char	*next;
		int	cpu;
		int	start, end;

		start = end = (int)strtol(s, &next, 0);
		if (s == next)
			break;
		s = next;

		if (*s == '-') {
			++s;
			end = (int)strtol(s, &next, 0);
			if (s == next)
				break;
			s = next;
		}

		if (*s == ',')
			++s;

		if (start < 0 || start >= CPU_SETSIZE) {
			ERROR(0, "bad cpu number '%d' in cpu set", start);
			return 1;
		}

		if (end < 0 || end >= CPU_SETSIZE) {
			ERROR(0, "bad cpu number '%d' in cpu set", end);
			return 1;
		}

		if (end < start) {
			ERROR(0, "bad range '%d-%d' in cpu set", start, end);
			return 1;
		}

		for (cpu = start; cpu <= end; ++cpu)
			CPU_SET(cpu, cpus);

	}

	if (*s) {
		ERROR(0, "unexpected character '%c' in cpu set", *s);
		return 1;
	}

	return 0;
}


static int show_range(char *buf, size_t len, const char *prefix,
			int start, int end)
{
	int	n;

	if (start == end)
		n = snprintf(buf, len, "%s%d", prefix, start);
	else
		n = snprintf(buf, len, "%s%d-%d", prefix, start, end);

	if (n < len)
		return n;

	return -1;
}

/*
 * Turn a cpu_set_t into a human readable string containing a
 * comma separated list of ranges of cpu numbers.
 *
 * Returns the number of bytes written to the buffer,
 * not including the terminating '\0' character,
 * or -1 if there was not enough space in the  buffer.
 */
int show_cpu_set(char *buf, size_t len, const cpu_set_t *cpus)
{
	char	*bufp	= buf;
	int	start	= -1;
	int	end	= -1;
	char	*sep	= "";
	int	cpu;

	for (cpu = 0; cpu < CPU_SETSIZE; cpu++) {
		if (CPU_ISSET(cpu, cpus)) {
			if (start < 0)
				start = cpu;
			end = cpu;
		} else if (start >= 0) {
			int	n;
			if ((n = show_range(bufp, len, sep, start, end)) < 0)
				return -1;
			len -= n;
			bufp += n;
			sep = ",";
			start = end = -1;
		}
	}

	if (start >= 0) {
		int	n;
		if ((n = show_range(bufp, len, sep, start, end)) < 0)
			return -1;
		bufp += n;
	}

	return bufp - buf;
}