1 /* Copyright (C) 2006-2016 Free Software Foundation, Inc.
2 Contributed by Jakub Jelinek <jakub@redhat.com>.
4 This file is part of the GNU Offloading and Multi Processing Library
7 Libgomp is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
26 /* This is a Linux specific implementation of a CPU affinity setting. */
39 #ifdef HAVE_PTHREAD_AFFINITY_NP
41 #ifndef CPU_ALLOC_SIZE
42 #define CPU_ISSET_S(idx, size, set) CPU_ISSET(idx, set)
43 #define CPU_ZERO_S(size, set) CPU_ZERO(set)
44 #define CPU_SET_S(idx, size, set) CPU_SET(idx, set)
45 #define CPU_CLR_S(idx, size, set) CPU_CLR(idx, set)
49 gomp_init_affinity (void)
51 if (gomp_places_list
== NULL
)
53 if (!gomp_affinity_init_level (1, ULONG_MAX
, true))
57 struct gomp_thread
*thr
= gomp_thread ();
58 pthread_setaffinity_np (pthread_self (), gomp_cpuset_size
,
59 (cpu_set_t
*) gomp_places_list
[0]);
61 thr
->ts
.place_partition_off
= 0;
62 thr
->ts
.place_partition_len
= gomp_places_list_len
;
66 gomp_init_thread_affinity (pthread_attr_t
*attr
, unsigned int place
)
68 pthread_attr_setaffinity_np (attr
, gomp_cpuset_size
,
69 (cpu_set_t
*) gomp_places_list
[place
]);
73 gomp_affinity_alloc (unsigned long count
, bool quiet
)
79 if (gomp_cpusetp
== NULL
)
82 gomp_error ("Could not get CPU affinity set");
86 ret
= malloc (count
* sizeof (void *) + count
* gomp_cpuset_size
);
90 gomp_error ("Out of memory trying to allocate places list");
94 p
= (char *) (ret
+ count
);
95 for (i
= 0; i
< count
; i
++, p
+= gomp_cpuset_size
)
101 gomp_affinity_init_place (void *p
)
103 cpu_set_t
*cpusetp
= (cpu_set_t
*) p
;
104 CPU_ZERO_S (gomp_cpuset_size
, cpusetp
);
108 gomp_affinity_add_cpus (void *p
, unsigned long num
,
109 unsigned long len
, long stride
, bool quiet
)
111 cpu_set_t
*cpusetp
= (cpu_set_t
*) p
;
112 unsigned long max
= 8 * gomp_cpuset_size
;
118 gomp_error ("Logical CPU number %lu out of range", num
);
121 CPU_SET_S (num
, gomp_cpuset_size
, cpusetp
);
124 if ((stride
< 0 && num
+ stride
> num
)
125 || (stride
> 0 && num
+ stride
< num
))
128 gomp_error ("Logical CPU number %lu+%ld out of range",
137 gomp_affinity_remove_cpu (void *p
, unsigned long num
)
139 cpu_set_t
*cpusetp
= (cpu_set_t
*) p
;
140 if (num
>= 8 * gomp_cpuset_size
)
142 gomp_error ("Logical CPU number %lu out of range", num
);
145 if (!CPU_ISSET_S (num
, gomp_cpuset_size
, cpusetp
))
147 gomp_error ("Logical CPU %lu to be removed is not in the set", num
);
150 CPU_CLR_S (num
, gomp_cpuset_size
, cpusetp
);
155 gomp_affinity_copy_place (void *p
, void *q
, long stride
)
157 unsigned long i
, max
= 8 * gomp_cpuset_size
;
158 cpu_set_t
*destp
= (cpu_set_t
*) p
;
159 cpu_set_t
*srcp
= (cpu_set_t
*) q
;
161 CPU_ZERO_S (gomp_cpuset_size
, destp
);
162 for (i
= 0; i
< max
; i
++)
163 if (CPU_ISSET_S (i
, gomp_cpuset_size
, srcp
))
165 if ((stride
< 0 && i
+ stride
> i
)
166 || (stride
> 0 && (i
+ stride
< i
|| i
+ stride
>= max
)))
168 gomp_error ("Logical CPU number %lu+%ld out of range", i
, stride
);
171 CPU_SET_S (i
+ stride
, gomp_cpuset_size
, destp
);
177 gomp_affinity_same_place (void *p
, void *q
)
180 return CPU_EQUAL_S (gomp_cpuset_size
, (cpu_set_t
*) p
, (cpu_set_t
*) q
);
182 return memcmp (p
, q
, gomp_cpuset_size
) == 0;
187 gomp_affinity_finalize_place_list (bool quiet
)
191 for (i
= 0, j
= 0; i
< gomp_places_list_len
; i
++)
193 cpu_set_t
*cpusetp
= (cpu_set_t
*) gomp_places_list
[i
];
194 bool nonempty
= false;
196 CPU_AND_S (gomp_cpuset_size
, cpusetp
, cpusetp
, gomp_cpusetp
);
197 nonempty
= gomp_cpuset_popcount (gomp_cpuset_size
, cpusetp
) != 0;
199 unsigned long k
, max
= gomp_cpuset_size
/ sizeof (cpusetp
->__bits
[0]);
200 for (k
= 0; k
< max
; k
++)
201 if ((cpusetp
->__bits
[k
] &= gomp_cpusetp
->__bits
[k
]) != 0)
205 gomp_places_list
[j
++] = gomp_places_list
[i
];
211 gomp_error ("None of the places contain usable logical CPUs");
214 else if (j
< gomp_places_list_len
)
217 gomp_error ("Number of places reduced from %ld to %ld because some "
218 "places didn't contain any usable logical CPUs",
219 gomp_places_list_len
, j
);
220 gomp_places_list_len
= j
;
226 gomp_affinity_init_level (int level
, unsigned long count
, bool quiet
)
228 unsigned long i
, max
= 8 * gomp_cpuset_size
;
232 unsigned long maxcount
233 = gomp_cpuset_popcount (gomp_cpuset_size
, gomp_cpusetp
);
234 if (count
> maxcount
)
237 gomp_places_list
= gomp_affinity_alloc (count
, quiet
);
238 gomp_places_list_len
= 0;
239 if (gomp_places_list
== NULL
)
244 for (i
= 0; i
< max
&& gomp_places_list_len
< count
; i
++)
245 if (CPU_ISSET_S (i
, gomp_cpuset_size
, gomp_cpusetp
))
247 gomp_affinity_init_place (gomp_places_list
[gomp_places_list_len
]);
248 gomp_affinity_add_cpus (gomp_places_list
[gomp_places_list_len
],
250 ++gomp_places_list_len
;
256 char name
[sizeof ("/sys/devices/system/cpu/cpu/topology/"
257 "thread_siblings_list") + 3 * sizeof (unsigned long)];
258 size_t prefix_len
= sizeof ("/sys/devices/system/cpu/cpu") - 1;
259 cpu_set_t
*copy
= gomp_alloca (gomp_cpuset_size
);
264 memcpy (name
, "/sys/devices/system/cpu/cpu", prefix_len
);
265 memcpy (copy
, gomp_cpusetp
, gomp_cpuset_size
);
266 for (i
= 0; i
< max
&& gomp_places_list_len
< count
; i
++)
267 if (CPU_ISSET_S (i
, gomp_cpuset_size
, copy
))
269 sprintf (name
+ prefix_len
, "%lu/topology/%s_siblings_list",
270 i
, level
== 2 ? "thread" : "core");
271 f
= fopen (name
, "r");
274 if (getline (&line
, &linelen
, f
) > 0)
278 void *pl
= gomp_places_list
[gomp_places_list_len
];
279 gomp_affinity_init_place (pl
);
280 while (*p
&& *p
!= '\n')
282 unsigned long first
, last
;
284 first
= strtoul (p
, &p
, 10);
291 last
= strtoul (p
+ 1, &p
, 10);
292 if (errno
|| last
< first
)
295 for (; first
<= last
; first
++)
296 if (CPU_ISSET_S (first
, gomp_cpuset_size
, copy
)
297 && gomp_affinity_add_cpus (pl
, first
, 1, 0,
300 CPU_CLR_S (first
, gomp_cpuset_size
, copy
);
308 gomp_places_list_len
++;
313 if (gomp_places_list_len
== 0)
316 gomp_error ("Error reading %s topology",
317 level
== 2 ? "core" : "socket");
318 free (gomp_places_list
);
319 gomp_places_list
= NULL
;
328 gomp_affinity_print_place (void *p
)
330 unsigned long i
, max
= 8 * gomp_cpuset_size
, len
;
331 cpu_set_t
*cpusetp
= (cpu_set_t
*) p
;
332 bool notfirst
= false;
334 for (i
= 0, len
= 0; i
< max
; i
++)
335 if (CPU_ISSET_S (i
, gomp_cpuset_size
, cpusetp
))
342 fprintf (stderr
, "%lu", i
);
349 fprintf (stderr
, ":%lu", len
);
353 fprintf (stderr
, ":%lu", len
);
357 omp_get_place_num_procs (int place_num
)
359 if (place_num
< 0 || place_num
>= gomp_places_list_len
)
362 cpu_set_t
*cpusetp
= (cpu_set_t
*) gomp_places_list
[place_num
];
363 return gomp_cpuset_popcount (gomp_cpuset_size
, cpusetp
);
367 omp_get_place_proc_ids (int place_num
, int *ids
)
369 if (place_num
< 0 || place_num
>= gomp_places_list_len
)
372 cpu_set_t
*cpusetp
= (cpu_set_t
*) gomp_places_list
[place_num
];
373 unsigned long i
, max
= 8 * gomp_cpuset_size
;
374 for (i
= 0; i
< max
; i
++)
375 if (CPU_ISSET_S (i
, gomp_cpuset_size
, cpusetp
))
380 gomp_get_place_proc_ids_8 (int place_num
, int64_t *ids
)
382 if (place_num
< 0 || place_num
>= gomp_places_list_len
)
385 cpu_set_t
*cpusetp
= (cpu_set_t
*) gomp_places_list
[place_num
];
386 unsigned long i
, max
= 8 * gomp_cpuset_size
;
387 for (i
= 0; i
< max
; i
++)
388 if (CPU_ISSET_S (i
, gomp_cpuset_size
, cpusetp
))
392 ialias(omp_get_place_num_procs
)
393 ialias(omp_get_place_proc_ids
)
397 #include "../posix/affinity.c"