1f08c3bdfSopenharmony_ci#include "config.h"
2f08c3bdfSopenharmony_ci#include <stdio.h>
3f08c3bdfSopenharmony_ci#include <stdlib.h>
4f08c3bdfSopenharmony_ci#include <string.h>
5f08c3bdfSopenharmony_ci#include <sys/types.h>
6f08c3bdfSopenharmony_ci#include <dirent.h>
7f08c3bdfSopenharmony_ci#include <err.h>
8f08c3bdfSopenharmony_ci#include <errno.h>
9f08c3bdfSopenharmony_ci
10f08c3bdfSopenharmony_ci#include "bitmask.h"
11f08c3bdfSopenharmony_ci#include "cpuset.h"
12f08c3bdfSopenharmony_ci#include "common.h"
13f08c3bdfSopenharmony_ci#include "cpuinfo.h"
14f08c3bdfSopenharmony_ci
15f08c3bdfSopenharmony_ci#if HAVE_LINUX_MEMPOLICY_H
16f08c3bdfSopenharmony_ci
17f08c3bdfSopenharmony_ci#define CPUINFO_FILE		"/proc/cpuinfo"
18f08c3bdfSopenharmony_ci#define SCHEDSTAT_FILE		"/proc/schedstat"
19f08c3bdfSopenharmony_ci#define CGROUPINFO_FILE		"/proc/cgroups"
20f08c3bdfSopenharmony_ci#define SYS_CPU_DIR		"/sys/devices/system/cpu"
21f08c3bdfSopenharmony_ci#define LIST_PRESENT_CPU_FILE	"/sys/devices/system/cpu/present"
22f08c3bdfSopenharmony_ci#define LIST_ONLINE_CPU_FILE	"/sys/devices/system/cpu/online"
23f08c3bdfSopenharmony_ci
24f08c3bdfSopenharmony_cistruct cpuinfo *cpus;
25f08c3bdfSopenharmony_ciint ncpus;
26f08c3bdfSopenharmony_ciint cpus_nbits;
27f08c3bdfSopenharmony_ci
28f08c3bdfSopenharmony_ci/* get cpu_baseinfo from /proc/cpuinfo */
29f08c3bdfSopenharmony_cistatic int get_cpu_baseinfo(void)
30f08c3bdfSopenharmony_ci{
31f08c3bdfSopenharmony_ci	FILE *fp = NULL;
32f08c3bdfSopenharmony_ci	char buf[BUFFSIZE];
33f08c3bdfSopenharmony_ci	char *istr = NULL, *valstr = NULL, *saveptr = NULL;
34f08c3bdfSopenharmony_ci	int ci = 0;
35f08c3bdfSopenharmony_ci	int data = 0;
36f08c3bdfSopenharmony_ci
37f08c3bdfSopenharmony_ci	/* get the number of cpus including offline cpus */
38f08c3bdfSopenharmony_ci	if (!ncpus) {
39f08c3bdfSopenharmony_ci		ncpus = get_ncpus();
40f08c3bdfSopenharmony_ci		if (ncpus <= 0)
41f08c3bdfSopenharmony_ci			return -1;
42f08c3bdfSopenharmony_ci	}
43f08c3bdfSopenharmony_ci
44f08c3bdfSopenharmony_ci	if (cpus != NULL) {
45f08c3bdfSopenharmony_ci		free(cpus);
46f08c3bdfSopenharmony_ci		cpus = NULL;
47f08c3bdfSopenharmony_ci	}
48f08c3bdfSopenharmony_ci
49f08c3bdfSopenharmony_ci	/* allocate the memory space for cpus */
50f08c3bdfSopenharmony_ci	cpus = malloc(sizeof(*cpus) * ncpus);
51f08c3bdfSopenharmony_ci	if (cpus == NULL)
52f08c3bdfSopenharmony_ci		return -1;
53f08c3bdfSopenharmony_ci	memset(cpus, 0, sizeof(*cpus) * ncpus);
54f08c3bdfSopenharmony_ci
55f08c3bdfSopenharmony_ci	/* open file /proc/cpuinfo */
56f08c3bdfSopenharmony_ci	if ((fp = fopen(CPUINFO_FILE, "r")) == NULL)
57f08c3bdfSopenharmony_ci		return -1;
58f08c3bdfSopenharmony_ci
59f08c3bdfSopenharmony_ci	/* get cpuinfo */
60f08c3bdfSopenharmony_ci	while (fgets(buf, sizeof(buf), fp) != NULL) {
61f08c3bdfSopenharmony_ci		istr = strtok_r(buf, "\t", &saveptr);
62f08c3bdfSopenharmony_ci		valstr = strchr(saveptr, ':');
63f08c3bdfSopenharmony_ci		if (valstr == NULL)
64f08c3bdfSopenharmony_ci			continue;
65f08c3bdfSopenharmony_ci		valstr++;
66f08c3bdfSopenharmony_ci		sscanf(valstr, " %d\n", &data);
67f08c3bdfSopenharmony_ci		if (!strcmp(istr, "processor")) {
68f08c3bdfSopenharmony_ci			if (data >= ncpus) {
69f08c3bdfSopenharmony_ci				warnx("Warn: wrong cpu index");
70f08c3bdfSopenharmony_ci				fclose(fp);
71f08c3bdfSopenharmony_ci				return -1;
72f08c3bdfSopenharmony_ci			}
73f08c3bdfSopenharmony_ci			ci = data;
74f08c3bdfSopenharmony_ci			cpus[ci].online = 1;
75f08c3bdfSopenharmony_ci		}
76f08c3bdfSopenharmony_ci	}
77f08c3bdfSopenharmony_ci
78f08c3bdfSopenharmony_ci	fclose(fp);
79f08c3bdfSopenharmony_ci	return 0;
80f08c3bdfSopenharmony_ci}
81f08c3bdfSopenharmony_ci
82f08c3bdfSopenharmony_ci/*
83f08c3bdfSopenharmony_ci * get the cpu bitmask of the online processors
84f08c3bdfSopenharmony_ci *
85f08c3bdfSopenharmony_ci * return value: 0  - success
86f08c3bdfSopenharmony_ci *               -1 - failed
87f08c3bdfSopenharmony_ci */
88f08c3bdfSopenharmony_ciint online_cpumask(struct bitmask *cpumask)
89f08c3bdfSopenharmony_ci{
90f08c3bdfSopenharmony_ci	FILE *fp = NULL;
91f08c3bdfSopenharmony_ci	char buf[BUFFSIZE];
92f08c3bdfSopenharmony_ci	int i;
93f08c3bdfSopenharmony_ci
94f08c3bdfSopenharmony_ci	if (cpumask == NULL)
95f08c3bdfSopenharmony_ci		return -1;
96f08c3bdfSopenharmony_ci	/*
97f08c3bdfSopenharmony_ci	 * open file /sys/devices/system/cpu/online and get online
98f08c3bdfSopenharmony_ci	 * cpulist.
99f08c3bdfSopenharmony_ci	 */
100f08c3bdfSopenharmony_ci	if ((fp = fopen(LIST_ONLINE_CPU_FILE, "r")) == NULL) {
101f08c3bdfSopenharmony_ci		if (get_cpu_baseinfo() != 0)
102f08c3bdfSopenharmony_ci			return -1;
103f08c3bdfSopenharmony_ci		for (i = 0; i < ncpus; i++) {
104f08c3bdfSopenharmony_ci			if (cpus[i].online)
105f08c3bdfSopenharmony_ci				bitmask_setbit(cpumask, i);
106f08c3bdfSopenharmony_ci		}
107f08c3bdfSopenharmony_ci	} else {
108f08c3bdfSopenharmony_ci		if (fgets(buf, sizeof(buf), fp) == NULL) {
109f08c3bdfSopenharmony_ci			fclose(fp);
110f08c3bdfSopenharmony_ci			return -1;
111f08c3bdfSopenharmony_ci		}
112f08c3bdfSopenharmony_ci		fclose(fp);
113f08c3bdfSopenharmony_ci
114f08c3bdfSopenharmony_ci		/* parse present cpu list to bitmap */
115f08c3bdfSopenharmony_ci		buf[strlen(buf) - 1] = '\0';
116f08c3bdfSopenharmony_ci		if (bitmask_parselist(buf, cpumask) != 0)
117f08c3bdfSopenharmony_ci			return -1;
118f08c3bdfSopenharmony_ci	}
119f08c3bdfSopenharmony_ci
120f08c3bdfSopenharmony_ci	return 0;
121f08c3bdfSopenharmony_ci}
122f08c3bdfSopenharmony_ci
123f08c3bdfSopenharmony_ci/*
124f08c3bdfSopenharmony_ci * get the cpu bitmask of the present processors including offline CPUs
125f08c3bdfSopenharmony_ci *
126f08c3bdfSopenharmony_ci * return value: 0  - success
127f08c3bdfSopenharmony_ci *               -1 - failed
128f08c3bdfSopenharmony_ci */
129f08c3bdfSopenharmony_ciint present_cpumask(struct bitmask *cpumask)
130f08c3bdfSopenharmony_ci{
131f08c3bdfSopenharmony_ci	FILE *fp = NULL;
132f08c3bdfSopenharmony_ci	char buf[BUFFSIZE];
133f08c3bdfSopenharmony_ci	char c_relpath[PATH_MAX];
134f08c3bdfSopenharmony_ci	int cpu = -1;
135f08c3bdfSopenharmony_ci
136f08c3bdfSopenharmony_ci	if (cpumask == NULL)
137f08c3bdfSopenharmony_ci		return -1;
138f08c3bdfSopenharmony_ci	/*
139f08c3bdfSopenharmony_ci	 * open file /sys/devices/system/cpu/present and get present
140f08c3bdfSopenharmony_ci	 * cpulist.
141f08c3bdfSopenharmony_ci	 */
142f08c3bdfSopenharmony_ci	if ((fp = fopen(LIST_PRESENT_CPU_FILE, "r")) == NULL) {
143f08c3bdfSopenharmony_ci		while_each_childdir(SYS_CPU_DIR, "/", c_relpath,
144f08c3bdfSopenharmony_ci				    sizeof(c_relpath)) {
145f08c3bdfSopenharmony_ci			if (!strncmp(c_relpath + 1, "cpu", 3)
146f08c3bdfSopenharmony_ci			    && sscanf(c_relpath + 4, "%d", &cpu) > 0) {
147f08c3bdfSopenharmony_ci				if (cpu >= 0)
148f08c3bdfSopenharmony_ci					bitmask_setbit(cpumask, cpu);
149f08c3bdfSopenharmony_ci			}
150f08c3bdfSopenharmony_ci		}
151f08c3bdfSopenharmony_ci	end_while_each_childdir} else {
152f08c3bdfSopenharmony_ci		if (fgets(buf, sizeof(buf), fp) == NULL) {
153f08c3bdfSopenharmony_ci			fclose(fp);
154f08c3bdfSopenharmony_ci			return -1;
155f08c3bdfSopenharmony_ci		}
156f08c3bdfSopenharmony_ci		fclose(fp);
157f08c3bdfSopenharmony_ci
158f08c3bdfSopenharmony_ci		/* parse present cpu list to bitmap */
159f08c3bdfSopenharmony_ci		buf[strlen(buf) - 1] = '\0';
160f08c3bdfSopenharmony_ci		if (bitmask_parselist(buf, cpumask) != 0)
161f08c3bdfSopenharmony_ci			return -1;
162f08c3bdfSopenharmony_ci	}
163f08c3bdfSopenharmony_ci
164f08c3bdfSopenharmony_ci	return 0;
165f08c3bdfSopenharmony_ci}
166f08c3bdfSopenharmony_ci
167f08c3bdfSopenharmony_ci/*
168f08c3bdfSopenharmony_ci * get the number of the processors including offline CPUs
169f08c3bdfSopenharmony_ci * We get this number from /sys/devices/system/cpu/present.
170f08c3bdfSopenharmony_ci * By analyzing the present cpu list, we get the number of all cpus
171f08c3bdfSopenharmony_ci */
172f08c3bdfSopenharmony_ciint get_ncpus(void)
173f08c3bdfSopenharmony_ci{
174f08c3bdfSopenharmony_ci	struct bitmask *bmp = NULL;
175f08c3bdfSopenharmony_ci	int n = 0;
176f08c3bdfSopenharmony_ci
177f08c3bdfSopenharmony_ci	/* get the bitmask's len */
178f08c3bdfSopenharmony_ci	cpus_nbits = cpuset_cpus_nbits();
179f08c3bdfSopenharmony_ci	if (cpus_nbits <= 0)
180f08c3bdfSopenharmony_ci		return -1;
181f08c3bdfSopenharmony_ci
182f08c3bdfSopenharmony_ci	/* allocate the space for bitmask */
183f08c3bdfSopenharmony_ci	bmp = bitmask_alloc(cpus_nbits);
184f08c3bdfSopenharmony_ci	if (bmp == NULL)
185f08c3bdfSopenharmony_ci		return -1;
186f08c3bdfSopenharmony_ci
187f08c3bdfSopenharmony_ci	if (present_cpumask(bmp)) {
188f08c3bdfSopenharmony_ci		bitmask_free(bmp);
189f08c3bdfSopenharmony_ci		return -1;
190f08c3bdfSopenharmony_ci	}
191f08c3bdfSopenharmony_ci
192f08c3bdfSopenharmony_ci	/* Number of highest set bit +1 is the number of the CPUs */
193f08c3bdfSopenharmony_ci	n = bitmask_last(bmp) + 1;
194f08c3bdfSopenharmony_ci	bitmask_free(bmp);
195f08c3bdfSopenharmony_ci
196f08c3bdfSopenharmony_ci	return n;
197f08c3bdfSopenharmony_ci}
198f08c3bdfSopenharmony_ci
199f08c3bdfSopenharmony_ci/* get the sched domain's info for each cpu */
200f08c3bdfSopenharmony_cistatic int get_sched_domains(void)
201f08c3bdfSopenharmony_ci{
202f08c3bdfSopenharmony_ci	FILE *fp = NULL;
203f08c3bdfSopenharmony_ci	char buf[BUFFSIZE];
204f08c3bdfSopenharmony_ci	char str1[20], str2[BUFFSIZE];
205f08c3bdfSopenharmony_ci	int ci = 0;
206f08c3bdfSopenharmony_ci
207f08c3bdfSopenharmony_ci	/* get the bitmask's len */
208f08c3bdfSopenharmony_ci	if (!cpus_nbits) {
209f08c3bdfSopenharmony_ci		cpus_nbits = cpuset_cpus_nbits();
210f08c3bdfSopenharmony_ci		if (cpus_nbits <= 0) {
211f08c3bdfSopenharmony_ci			warnx("get cpus nbits failed.");
212f08c3bdfSopenharmony_ci			return -1;
213f08c3bdfSopenharmony_ci		}
214f08c3bdfSopenharmony_ci	}
215f08c3bdfSopenharmony_ci
216f08c3bdfSopenharmony_ci	/* open file /proc/schedstat */
217f08c3bdfSopenharmony_ci	if ((fp = fopen(SCHEDSTAT_FILE, "r")) == NULL)
218f08c3bdfSopenharmony_ci		return -1;
219f08c3bdfSopenharmony_ci
220f08c3bdfSopenharmony_ci	/* get cpuinfo */
221f08c3bdfSopenharmony_ci	while (fgets(buf, sizeof(buf), fp) != NULL) {
222f08c3bdfSopenharmony_ci		sscanf(buf, "%s %s", str1, str2);
223f08c3bdfSopenharmony_ci		if (!strncmp(str1, "cpu", 3)) {
224f08c3bdfSopenharmony_ci			ci = atoi(str1 + 3);
225f08c3bdfSopenharmony_ci			if (ci < 0 || ci >= ncpus) {
226f08c3bdfSopenharmony_ci				fprintf(stderr, "Warn: wrong cpu index");
227f08c3bdfSopenharmony_ci				fclose(fp);
228f08c3bdfSopenharmony_ci				return -1;
229f08c3bdfSopenharmony_ci			}
230f08c3bdfSopenharmony_ci		} else if (!strncmp(str1, "domain", 6)) {
231f08c3bdfSopenharmony_ci			if (!cpus[ci].sched_domain) {
232f08c3bdfSopenharmony_ci				cpus[ci].sched_domain =
233f08c3bdfSopenharmony_ci				    bitmask_alloc(cpus_nbits);
234f08c3bdfSopenharmony_ci				if (!cpus[ci].sched_domain) {
235f08c3bdfSopenharmony_ci					fclose(fp);
236f08c3bdfSopenharmony_ci					return -1;
237f08c3bdfSopenharmony_ci				}
238f08c3bdfSopenharmony_ci			}
239f08c3bdfSopenharmony_ci			if (bitmask_parsehex(str2, cpus[ci].sched_domain)) {
240f08c3bdfSopenharmony_ci				fclose(fp);
241f08c3bdfSopenharmony_ci				return -1;
242f08c3bdfSopenharmony_ci			}
243f08c3bdfSopenharmony_ci		}
244f08c3bdfSopenharmony_ci	}
245f08c3bdfSopenharmony_ci
246f08c3bdfSopenharmony_ci	fclose(fp);
247f08c3bdfSopenharmony_ci	return 0;
248f08c3bdfSopenharmony_ci}
249f08c3bdfSopenharmony_ci
250f08c3bdfSopenharmony_ciint getcpuinfo(void)
251f08c3bdfSopenharmony_ci{
252f08c3bdfSopenharmony_ci	int i;
253f08c3bdfSopenharmony_ci	int node = -1;
254f08c3bdfSopenharmony_ci
255f08c3bdfSopenharmony_ci	/* get the number of cpus including offline cpus */
256f08c3bdfSopenharmony_ci	if (!ncpus) {
257f08c3bdfSopenharmony_ci		ncpus = get_ncpus();
258f08c3bdfSopenharmony_ci		if (ncpus <= 0)
259f08c3bdfSopenharmony_ci			return -1;
260f08c3bdfSopenharmony_ci	}
261f08c3bdfSopenharmony_ci
262f08c3bdfSopenharmony_ci	if (cpus == NULL) {
263f08c3bdfSopenharmony_ci		if (get_cpu_baseinfo() != 0) {
264f08c3bdfSopenharmony_ci			warn("get base infomation of cpus from /proc/cpuinfo "
265f08c3bdfSopenharmony_ci			     "failed.");
266f08c3bdfSopenharmony_ci			return -1;
267f08c3bdfSopenharmony_ci		}
268f08c3bdfSopenharmony_ci	}
269f08c3bdfSopenharmony_ci
270f08c3bdfSopenharmony_ci	/* which node is every cpu belong to? */
271f08c3bdfSopenharmony_ci	for (i = 0; i < ncpus; i++) {
272f08c3bdfSopenharmony_ci		node = cpuset_cpu2node(i);
273f08c3bdfSopenharmony_ci		if (node == -1)
274f08c3bdfSopenharmony_ci			warnx("cpu2node failed(cpu = %d)", i);
275f08c3bdfSopenharmony_ci		cpus[i].nodeid = node;
276f08c3bdfSopenharmony_ci	}
277f08c3bdfSopenharmony_ci
278f08c3bdfSopenharmony_ci	/* get sched domain's infomation for each cpu */
279f08c3bdfSopenharmony_ci	if (get_sched_domains()) {
280f08c3bdfSopenharmony_ci		warnx("get sched domain's info for each cpu failed.");
281f08c3bdfSopenharmony_ci		return -1;
282f08c3bdfSopenharmony_ci	}
283f08c3bdfSopenharmony_ci
284f08c3bdfSopenharmony_ci	return 0;
285f08c3bdfSopenharmony_ci}
286f08c3bdfSopenharmony_ci
287f08c3bdfSopenharmony_ci/* get the number of the cpuset groups */
288f08c3bdfSopenharmony_cistatic int get_num_cpusets(void)
289f08c3bdfSopenharmony_ci{
290f08c3bdfSopenharmony_ci	FILE *fp = NULL;
291f08c3bdfSopenharmony_ci	char buf[BUFFSIZE];
292f08c3bdfSopenharmony_ci	char subsys_name[BUFFSIZE];
293f08c3bdfSopenharmony_ci	int num_cgroups = 0;
294f08c3bdfSopenharmony_ci	int hierarchy;
295f08c3bdfSopenharmony_ci	int enabled;
296f08c3bdfSopenharmony_ci
297f08c3bdfSopenharmony_ci	/* open file /proc/cgroups and get num cpusets */
298f08c3bdfSopenharmony_ci	if ((fp = fopen(CGROUPINFO_FILE, "r")) == NULL)
299f08c3bdfSopenharmony_ci		return -1;
300f08c3bdfSopenharmony_ci
301f08c3bdfSopenharmony_ci	while (fgets(buf, sizeof(buf), fp) != NULL) {
302f08c3bdfSopenharmony_ci		if (!strncmp(buf, "cpuset", 6)) {
303f08c3bdfSopenharmony_ci			sscanf(buf, "%s\t%d\t%d\t%d\n", subsys_name,
304f08c3bdfSopenharmony_ci			       &hierarchy, &num_cgroups, &enabled);
305f08c3bdfSopenharmony_ci		}
306f08c3bdfSopenharmony_ci	}
307f08c3bdfSopenharmony_ci
308f08c3bdfSopenharmony_ci	fclose(fp);
309f08c3bdfSopenharmony_ci
310f08c3bdfSopenharmony_ci	return num_cgroups;
311f08c3bdfSopenharmony_ci}
312f08c3bdfSopenharmony_ci
313f08c3bdfSopenharmony_cistatic struct cpuset **cpusets;
314f08c3bdfSopenharmony_cistatic int ncpusets;
315f08c3bdfSopenharmony_ci
316f08c3bdfSopenharmony_cistatic int find_domain_cpusets(char *relpath)
317f08c3bdfSopenharmony_ci{
318f08c3bdfSopenharmony_ci	struct cpuset *cp = NULL;
319f08c3bdfSopenharmony_ci	char c_relpath[PATH_MAX];
320f08c3bdfSopenharmony_ci	int ret = 0;
321f08c3bdfSopenharmony_ci
322f08c3bdfSopenharmony_ci	if (relpath == NULL) {
323f08c3bdfSopenharmony_ci		errno = -EFAULT;
324f08c3bdfSopenharmony_ci		return -1;
325f08c3bdfSopenharmony_ci	}
326f08c3bdfSopenharmony_ci
327f08c3bdfSopenharmony_ci	cp = cpuset_alloc();
328f08c3bdfSopenharmony_ci	if (cp == NULL) {
329f08c3bdfSopenharmony_ci		errno = -ENOMEM;
330f08c3bdfSopenharmony_ci		return -1;
331f08c3bdfSopenharmony_ci	}
332f08c3bdfSopenharmony_ci
333f08c3bdfSopenharmony_ci	if (cpuset_query(cp, relpath)) {
334f08c3bdfSopenharmony_ci		cpuset_free(cp);
335f08c3bdfSopenharmony_ci		return -1;
336f08c3bdfSopenharmony_ci	}
337f08c3bdfSopenharmony_ci
338f08c3bdfSopenharmony_ci	if (cpuset_cpus_weight(cp) == 0)
339f08c3bdfSopenharmony_ci		return 0;
340f08c3bdfSopenharmony_ci
341f08c3bdfSopenharmony_ci	if (cpuset_cpus_weight(cp) > 0
342f08c3bdfSopenharmony_ci	    && cpuset_get_iopt(cp, "sched_load_balance") == 1) {
343f08c3bdfSopenharmony_ci		cpusets[ncpusets] = cp;
344f08c3bdfSopenharmony_ci		ncpusets++;
345f08c3bdfSopenharmony_ci		return 0;
346f08c3bdfSopenharmony_ci	}
347f08c3bdfSopenharmony_ci
348f08c3bdfSopenharmony_ci	while_each_childdir(cpuset_mountpoint(), relpath, c_relpath,
349f08c3bdfSopenharmony_ci			    sizeof(c_relpath)) {
350f08c3bdfSopenharmony_ci		if ((ret = find_domain_cpusets(c_relpath)))
351f08c3bdfSopenharmony_ci			break;
352f08c3bdfSopenharmony_ci	}
353f08c3bdfSopenharmony_ci	end_while_each_childdir;
354f08c3bdfSopenharmony_ci
355f08c3bdfSopenharmony_ci	return ret;
356f08c3bdfSopenharmony_ci}
357f08c3bdfSopenharmony_ci
358f08c3bdfSopenharmony_cistruct bitmask **domains;
359f08c3bdfSopenharmony_ciint ndomains;
360f08c3bdfSopenharmony_ci
361f08c3bdfSopenharmony_ciint partition_domains(void)
362f08c3bdfSopenharmony_ci{
363f08c3bdfSopenharmony_ci	int num_cpusets = 0;
364f08c3bdfSopenharmony_ci	int i, j;
365f08c3bdfSopenharmony_ci	struct bitmask *cpusa = NULL, *cpusb = NULL, *cpusc = NULL;
366f08c3bdfSopenharmony_ci	int *flg = NULL;
367f08c3bdfSopenharmony_ci	int ret = 0;
368f08c3bdfSopenharmony_ci
369f08c3bdfSopenharmony_ci	num_cpusets = get_num_cpusets();
370f08c3bdfSopenharmony_ci	if (num_cpusets == 0) {
371f08c3bdfSopenharmony_ci		warnx("cpuset subsystem is't compiled into kernel.");
372f08c3bdfSopenharmony_ci		return -1;
373f08c3bdfSopenharmony_ci	}
374f08c3bdfSopenharmony_ci
375f08c3bdfSopenharmony_ci	if (!cpus_nbits) {
376f08c3bdfSopenharmony_ci		cpus_nbits = cpuset_cpus_nbits();
377f08c3bdfSopenharmony_ci		if (!cpus_nbits) {
378f08c3bdfSopenharmony_ci			warnx("nbits of cpus is wrong.");
379f08c3bdfSopenharmony_ci			return -1;
380f08c3bdfSopenharmony_ci		}
381f08c3bdfSopenharmony_ci	}
382f08c3bdfSopenharmony_ci
383f08c3bdfSopenharmony_ci	cpusa = bitmask_alloc(cpus_nbits);
384f08c3bdfSopenharmony_ci	if (cpusa == NULL) {
385f08c3bdfSopenharmony_ci		warnx("bitmask_alloc for partition domains failed.");
386f08c3bdfSopenharmony_ci		return -1;
387f08c3bdfSopenharmony_ci	}
388f08c3bdfSopenharmony_ci
389f08c3bdfSopenharmony_ci	cpusb = bitmask_alloc(cpus_nbits);
390f08c3bdfSopenharmony_ci	if (cpusb == NULL) {
391f08c3bdfSopenharmony_ci		warnx("bitmask_alloc for partition domains failed.");
392f08c3bdfSopenharmony_ci		ret = -1;
393f08c3bdfSopenharmony_ci		goto errcpusb;
394f08c3bdfSopenharmony_ci	}
395f08c3bdfSopenharmony_ci
396f08c3bdfSopenharmony_ci	cpusc = bitmask_alloc(cpus_nbits);
397f08c3bdfSopenharmony_ci	if (cpusb == NULL) {
398f08c3bdfSopenharmony_ci		warnx("bitmask_alloc for partition domains failed.");
399f08c3bdfSopenharmony_ci		ret = -1;
400f08c3bdfSopenharmony_ci		goto errcpusc;
401f08c3bdfSopenharmony_ci	}
402f08c3bdfSopenharmony_ci
403f08c3bdfSopenharmony_ci	cpusets = malloc(num_cpusets * sizeof(*cpusets));
404f08c3bdfSopenharmony_ci	if (cpusets == NULL) {
405f08c3bdfSopenharmony_ci		warnx("alloc cpusets space failed.");
406f08c3bdfSopenharmony_ci		ret = -1;
407f08c3bdfSopenharmony_ci		goto errcpusets;
408f08c3bdfSopenharmony_ci	}
409f08c3bdfSopenharmony_ci
410f08c3bdfSopenharmony_ci	if ((ret = find_domain_cpusets("/"))) {
411f08c3bdfSopenharmony_ci		warnx("find domain cpusets failed.");
412f08c3bdfSopenharmony_ci		goto errfindcpusets;
413f08c3bdfSopenharmony_ci	}
414f08c3bdfSopenharmony_ci
415f08c3bdfSopenharmony_ci	flg = malloc(num_cpusets * sizeof(int));
416f08c3bdfSopenharmony_ci	if (flg == NULL) {
417f08c3bdfSopenharmony_ci		warnx("alloc flg failed.");
418f08c3bdfSopenharmony_ci		ret = -1;
419f08c3bdfSopenharmony_ci		goto errfindcpusets;
420f08c3bdfSopenharmony_ci	}
421f08c3bdfSopenharmony_ci	memset(flg, 0, num_cpusets * sizeof(int));
422f08c3bdfSopenharmony_ci
423f08c3bdfSopenharmony_ci	ndomains = ncpusets;
424f08c3bdfSopenharmony_cirestart:
425f08c3bdfSopenharmony_ci	for (i = 0; i < ncpusets; i++) {
426f08c3bdfSopenharmony_ci		struct cpuset *cpa = cpusets[i];
427f08c3bdfSopenharmony_ci
428f08c3bdfSopenharmony_ci		if (flg[i])
429f08c3bdfSopenharmony_ci			continue;
430f08c3bdfSopenharmony_ci
431f08c3bdfSopenharmony_ci		cpuset_getcpus(cpa, cpusa);
432f08c3bdfSopenharmony_ci
433f08c3bdfSopenharmony_ci		for (j = i + 1; j < ncpusets; j++) {
434f08c3bdfSopenharmony_ci			struct cpuset *cpb = cpusets[j];
435f08c3bdfSopenharmony_ci
436f08c3bdfSopenharmony_ci			if (flg[j])
437f08c3bdfSopenharmony_ci				continue;
438f08c3bdfSopenharmony_ci
439f08c3bdfSopenharmony_ci			cpuset_getcpus(cpb, cpusb);
440f08c3bdfSopenharmony_ci			if (bitmask_intersects(cpusa, cpusb)) {
441f08c3bdfSopenharmony_ci				bitmask_or(cpusc, cpusa, cpusb);
442f08c3bdfSopenharmony_ci				cpuset_setcpus(cpa, cpusc);
443f08c3bdfSopenharmony_ci				flg[j] = 1;
444f08c3bdfSopenharmony_ci				ndomains--;
445f08c3bdfSopenharmony_ci				goto restart;
446f08c3bdfSopenharmony_ci			}
447f08c3bdfSopenharmony_ci		}
448f08c3bdfSopenharmony_ci	}
449f08c3bdfSopenharmony_ci
450f08c3bdfSopenharmony_ci	domains = malloc(ndomains * sizeof(*domains));
451f08c3bdfSopenharmony_ci	if (domains == NULL) {
452f08c3bdfSopenharmony_ci		warnx("alloc domains space failed.");
453f08c3bdfSopenharmony_ci		ret = -1;
454f08c3bdfSopenharmony_ci		goto errdomains;
455f08c3bdfSopenharmony_ci	}
456f08c3bdfSopenharmony_ci
457f08c3bdfSopenharmony_ci	for (i = 0, j = 0; i < ncpusets; i++) {
458f08c3bdfSopenharmony_ci		if (flg[i])
459f08c3bdfSopenharmony_ci			continue;
460f08c3bdfSopenharmony_ci		domains[j] = bitmask_alloc(cpus_nbits);
461f08c3bdfSopenharmony_ci		if (cpuset_getcpus(cpusets[i], domains[j])) {
462f08c3bdfSopenharmony_ci			warnx("cpuset getcpus failed.");
463f08c3bdfSopenharmony_ci			ret = -1;
464f08c3bdfSopenharmony_ci			goto errgetdomains;
465f08c3bdfSopenharmony_ci		}
466f08c3bdfSopenharmony_ci		j++;
467f08c3bdfSopenharmony_ci	}
468f08c3bdfSopenharmony_ci	goto errdomains;
469f08c3bdfSopenharmony_ci
470f08c3bdfSopenharmony_cierrgetdomains:
471f08c3bdfSopenharmony_ci	for (i = 0; i < j; i++)
472f08c3bdfSopenharmony_ci		bitmask_free(domains[i]);
473f08c3bdfSopenharmony_ci	free(domains);
474f08c3bdfSopenharmony_ci	domains = NULL;
475f08c3bdfSopenharmony_cierrdomains:
476f08c3bdfSopenharmony_ci	free(flg);
477f08c3bdfSopenharmony_cierrfindcpusets:
478f08c3bdfSopenharmony_ci	for (i = 0; i < ncpusets; i++)
479f08c3bdfSopenharmony_ci		cpuset_free(cpusets[i]);
480f08c3bdfSopenharmony_ci	free(cpusets);
481f08c3bdfSopenharmony_ci	cpusets = NULL;
482f08c3bdfSopenharmony_ci	ncpusets = 0;
483f08c3bdfSopenharmony_cierrcpusets:
484f08c3bdfSopenharmony_ci	bitmask_free(cpusc);
485f08c3bdfSopenharmony_cierrcpusc:
486f08c3bdfSopenharmony_ci	bitmask_free(cpusb);
487f08c3bdfSopenharmony_cierrcpusb:
488f08c3bdfSopenharmony_ci	bitmask_free(cpusa);
489f08c3bdfSopenharmony_ci	return ret;
490f08c3bdfSopenharmony_ci}
491f08c3bdfSopenharmony_ci
492f08c3bdfSopenharmony_ci#endif
493