1 /*
2  * This file may be redistributed under the terms of the
3  * GNU Lesser General Public License.
4  */
5 #ifndef UTIL_LINUX_CPUSET_H
6 #define UTIL_LINUX_CPUSET_H
7 
8 #include <sched.h>
9 
10 /*
11  * Fallback for old or obscure libcs without dynamically allocated cpusets
12  *
13  * The following macros are based on code from glibc.
14  *
15  * The GNU C Library is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU Lesser General Public
17  * License as published by the Free Software Foundation; either
18  * version 2.1 of the License, or (at your option) any later version.
19  */
20 #if !HAVE_DECL_CPU_ALLOC && !defined(__DragonFly__)
21 
22 # define CPU_ZERO_S(setsize, cpusetp) \
23   do {									      \
24     size_t __i;								      \
25     size_t __imax = (setsize) / sizeof (__cpu_mask);			      \
26     __cpu_mask *__bits = (cpusetp)->__bits;				      \
27     for (__i = 0; __i < __imax; ++__i)					      \
28       __bits[__i] = 0;							      \
29   } while (0)
30 
31 # define CPU_SET_S(cpu, setsize, cpusetp) \
32    ({ size_t __cpu = (cpu);						      \
33       __cpu < 8 * (setsize)						      \
34       ? (((__cpu_mask *) ((cpusetp)->__bits))[__CPUELT (__cpu)]		      \
35 	 |= __CPUMASK (__cpu))						      \
36       : 0; })
37 
38 # define CPU_ISSET_S(cpu, setsize, cpusetp) \
39    ({ size_t __cpu = (cpu);						      \
40       __cpu < 8 * (setsize)						      \
41       ? ((((__cpu_mask *) ((cpusetp)->__bits))[__CPUELT (__cpu)]	      \
42 	  & __CPUMASK (__cpu))) != 0					      \
43       : 0; })
44 
45 # define CPU_EQUAL_S(setsize, cpusetp1, cpusetp2) \
46    ({ __cpu_mask *__arr1 = (cpusetp1)->__bits;				      \
47       __cpu_mask *__arr2 = (cpusetp2)->__bits;				      \
48       size_t __imax = (setsize) / sizeof (__cpu_mask);			      \
49       size_t __i;							      \
50       for (__i = 0; __i < __imax; ++__i)				      \
51 	if (__arr1[__i] != __arr2[__i])					      \
52 	  break;							      \
53       __i == __imax; })
54 
55 extern int __cpuset_count_s(size_t setsize, const cpu_set_t *set);
56 # define CPU_COUNT_S(setsize, cpusetp)	__cpuset_count_s(setsize, cpusetp)
57 
58 # define CPU_ALLOC_SIZE(count) \
59 	  ((((count) + __NCPUBITS - 1) / __NCPUBITS) * sizeof (__cpu_mask))
60 # define CPU_ALLOC(count)	(malloc(CPU_ALLOC_SIZE(count)))
61 # define CPU_FREE(cpuset)	(free(cpuset))
62 
63 #endif /* !HAVE_DECL_CPU_ALLOC */
64 
65 
66 #define cpuset_nbits(setsize)	(8 * (setsize))
67 
68 /*
69  * The @idx parameter returns an index of the first mask from @ary array where
70  * the @cpu is set.
71  *
72  * Returns: 0 if found, otherwise 1.
73  */
cpuset_ary_isset(size_t cpu,cpu_set_t ** ary,size_t nmemb,size_t setsize,size_t * idx)74 static inline int cpuset_ary_isset(size_t cpu, cpu_set_t **ary, size_t nmemb,
75 				   size_t setsize, size_t *idx)
76 {
77 	size_t i;
78 
79 	for (i = 0; i < nmemb; i++) {
80 		if (CPU_ISSET_S(cpu, setsize, ary[i])) {
81 			*idx = i;
82 			return 0;
83 		}
84 	}
85 	return 1;
86 }
87 
88 extern int get_max_number_of_cpus(void);
89 
90 extern cpu_set_t *cpuset_alloc(int ncpus, size_t *setsize, size_t *nbits);
91 extern void cpuset_free(cpu_set_t *set);
92 
93 extern char *cpulist_create(char *str, size_t len, cpu_set_t *set, size_t setsize);
94 extern int cpulist_parse(const char *str, cpu_set_t *set, size_t setsize, int fail);
95 
96 extern char *cpumask_create(char *str, size_t len, cpu_set_t *set, size_t setsize);
97 extern int cpumask_parse(const char *str, cpu_set_t *set, size_t setsize);
98 
99 #endif /* UTIL_LINUX_CPUSET_H */
100