mirror of
				https://sourceware.org/git/glibc.git
				synced 2025-10-28 23:34:53 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			137 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			137 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* Iterate over all CPUs, for CPU-specific diagnostics.
 | |
|    Copyright (C) 2024 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 */
 |