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
|
/* Iterate over all CPUs, for CPU-specific diagnostics.
Copyright (C) 2024-2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#ifndef DL_ITERATE_CPU_H
#define DL_ITERATE_CPU_H
#include <dl-affinity.h>
#include <stdbool.h>
struct dl_iterate_cpu
{
/* Sequential iteration count, starting at 0. */
unsigned int processor_index;
/* Requested CPU. Can be -1 if affinity could not be set. */
int requested_cpu;
/* Observed current CPU. -1 if unavailable. */
int actual_cpu;
/* Observed node ID for the CPU. -1 if unavailable. */
int actual_node;
/* Internal fields to implement the iteration. */
/* Affinity as obtained by _dl_iterate_cpu_init, using
_dl_getaffinity. Space for 8,192 CPUs. */
unsigned long int mask_reference[8192 / sizeof (unsigned long int) / 8];
/* This array is used by _dl_setaffinity calls. */
unsigned long int mask_request[8192 / sizeof (unsigned long int) / 8];
/* Return value from the initial _dl_getaffinity call. */
int length_reference;
};
static void
_dl_iterate_cpu_init (struct dl_iterate_cpu *dic)
{
dic->length_reference
= _dl_getaffinity (dic->mask_reference, sizeof (dic->mask_reference));
/* Prepare for the first _dl_iterate_cpu_next call. */
dic->processor_index = -1;
dic->requested_cpu = -1;
}
static bool
_dl_iterate_cpu_next (struct dl_iterate_cpu *dic)
{
++dic->processor_index;
if (dic->length_reference > 0)
{
/* Search for the next CPU to switch to. */
while (true)
{
++dic->requested_cpu;
/* Array index and bit number within the array. */
unsigned int long_index
= dic->requested_cpu / sizeof (unsigned long int) / 8;
unsigned int bit_index
= dic->requested_cpu % (sizeof (unsigned long int) * 8);
if (long_index * sizeof (unsigned long int) >= dic->length_reference)
/* All possible CPUs have been covered. */
return false;
unsigned long int bit = 1UL << bit_index;
if (dic->mask_reference[long_index] & bit)
{
/* The CPU is available. Try to select it. */
dic->mask_request[long_index] = bit;
if (_dl_setaffinity (dic->mask_request,
(long_index + 1)
* sizeof (unsigned long int)) < 0)
{
/* Record that we could not perform a CPU request. */
dic->length_reference = -1;
if (dic->processor_index > 0)
/* We already reported something. There is no need to
continue because the new data is probably not useful. */
return false;
}
/* Clear the bit in case the next iteration switches to the
next long value. */
dic->mask_request[long_index] = 0;
/* We found a CPU to run on. */
break;
}
}
}
else
{
/* No way to set CPU affinity. Iterate just once. */
if (dic->processor_index > 0)
return false;
}
/* Fill in the actual CPU information. CPU pinning may not actually
be effective, depending on the container host. */
unsigned int cpu, node;
if (_dl_getcpu (&cpu, &node) < 0)
{
/* No CPU information available. */
dic->actual_cpu = -1;
dic->actual_node = -1;
}
else
{
dic->actual_cpu = cpu;
dic->actual_node = node;
}
return true;
}
#endif /* DL_ITERATE_CPU_H */
|