CPUInfo
CPUInfo collects information on CPU-Memory subsystem, and builds
hierarchy which consists of following objects:
-
Node - on NUMA systems - collection of processors and memory where all processors may uniformly access memory. On UMA systems there is only single root Node
-
Chip - single processor package
-
Core - single processor core
-
Strand - hardware thread. Minimum CPU object capable of running software thread
-
Cache - in-CPU memory. Each cache subdevice has its own object in CPUInfo hierarchy
CPUInfo is purely hierarchial: Nodes -> Chip -> Core -> Strand. Cache devices
may be bound to Core or to Chip objects.
Each object has corresponding structure which contains its properties andhi_cpu_objtype_t
value, see following table:
Type | structure |
hi_cpu_objtype_t |
Naming schema |
Node |
hi_cpu_node_t |
HI_CPU_NODE |
node:NODEID |
Chip |
hi_cpu_chip_t |
HI_CPU_CHIP |
chip:CHIPID |
Core | (not used) |
HI_CPU_CORE |
core:CHIPID:COREID |
Strand | (not used) |
HI_CPU_STRAND |
strand:CHIPID:COREID:STRANDID |
Cache |
hi_cpu_cache_t |
HI_CPU_CACHE |
cache:LEVEL:CACHEID where LEVEL is l1, l2, l3 or tlb |
Linux
Reads information about cpus (that are considered as NUMA-nodes)
from SYSFS directory /sys/devices/system/node
. Frequency and CPU
model is provided by /proc/cpuinfo
CPU frequency is taken from cpufreq
driver if from /sys/devices/system/cpu
.
If it is not possible, CPUInfo reads frequency /proc/cpuinfo
file.
To determine cache relationship with CPU objects it uses shared_cpu_list
file
on SYSFS.
NOTE: Node ids are also reliable on Linux, so they may be used in mbind()
calls
Solaris
Uses liblgrp to gather NUMA nodes, kstat to collect information about CPUs and
picl daemon to find caches.
picl daemon only operates with processor instances, so there is hard to determine if
cache is assigned to chip or core. So code uses simple assumption: it compares cache_id
from kstat within chip. If it differs, last level cache is individual for cores,
otherwise it is shared between them.
Windows
Uses Windows registry HKLM\HARDWARE\DESCRIPTION\System\CentralProcessor\
to get processor frequency and name (alterable by user, but most reliable way
Windows provides).
Whole logic is build upon GetLogicalProcessorInformation()
call which also
provides relationships
NOTE: Windows 7 and 2008 R2 (64-bit versions) support processor groups
which allow them to go beyound 64 processor limit. CPUInfo doesn't support
them, so it is limited to 64 bit
NOTE: Windows provides only free amount of memory on per-node basis,
so we currently use this value also for total amount memory (wrong!)
Functions
HI_CPU_CACHEID
Generates ID of the cache
#define HI_CPU_CACHEID(level, type)
HI_CPU_FROM_OBJ, HI_CPU_PARENT_OBJ, HI_CPU_PARENT, HI_CPU_TO_OBJ
Conversion macros
#define HI_CPU_FROM_OBJ(object) #define HI_CPU_TO_OBJ(object) #define HI_CPU_PARENT_OBJ(object) #define HI_CPU_PARENT(object)
hi_cpu_detach, hi_cpu_attach
public
Attaches/detaches CPU objects
REFERENCE
hi_obj_attach
hi_obj_detach
STATIC_INLINE void hi_cpu_attach(hi_cpu_object_t* object, hi_cpu_object_t* parent) STATIC_INLINE void hi_cpu_detach(hi_cpu_object_t* object, hi_cpu_object_t* parent)
hi_cpu_find
public
Find cpu object by it's name
ARGUMENTS
-
name - - name of CPU object
RETURN VALUES
cpu object descriptor or NULL if it wasn't found
REFERENCE
hi_cpu_find_byid
STATIC_INLINE hi_cpu_object_t* hi_cpu_find(const char* name)
hi_cpu_find_byid
Find CPU object by it's type and id. More confortable than searching by object name.
Walks global list, than walk parents if needed
If parent == NULL, parents aren't checked
void* hi_cpu_find_byid(hi_cpu_object_t* parent, hi_cpu_objtype_t type, int id)
hi_cpu_list
public
STATIC_INLINE list_head_t* hi_cpu_list(boolean_t reprobe)
hi_cpu_num_cpus, hi_cpu_num_cores, hi_cpu_mem_total
public
Returns total count of Strands, Cores or memory available to system
LIBEXPORT int hi_cpu_num_cpus(void) LIBEXPORT int hi_cpu_num_cores(void) LIBEXPORT size_t hi_cpu_mem_total(void)
hi_cpu_mask
public
Create cpumask for cpu object
For caches processes nearest core/chip object (parent)
For other cpu objects - processes all child strands
For null creates mask that includes all strands
LIBEXPORT int hi_cpu_mask(hi_cpu_object_t* object, cpumask_t* mask)
Types
hi_cpu_cache_type_t
typedef enum { HI_CPU_CACHE_UNIFIED, HI_CPU_CACHE_DATA, HI_CPU_CACHE_INSTRUCTION, } hi_cpu_cache_type_t;
hi_cpu_objtype_t
typedef enum { HI_CPU_NODE, HI_CPU_CHIP, HI_CPU_CORE, HI_CPU_STRAND, HI_CPU_CACHE } hi_cpu_objtype_t;
hi_cpu_stat_t
typedef struct { uint32_t nodes; uint32_t mem_total; uint32_t mem_free; } hi_cpu_stat_t;
hi_cpu_node_t
Descriptor of Node
MEMBERS
-
cm_mem_total - Total amount of memory of this node
-
cm_mem_free - Free memory of this node (DEPRECATED)
typedef struct { uint64_t cm_mem_total; uint64_t cm_mem_free; } hi_cpu_node_t;
hi_cpu_chip_t
Descriptor of Chip
MEMBERS
-
cp_name - Stock name of CPU chip
-
cp_freq - CPU frequency in MHz
typedef struct { AUTOSTRING char* cp_name; uint64_t cp_freq; } hi_cpu_chip_t;
hi_cpu_core_t
typedef struct { int unused; } hi_cpu_core_t;
hi_cpu_strand_t
typedef struct { int unused; } hi_cpu_strand_t;
hi_cpu_cache_t
Descriptor of Cache
MEMBERS
-
c_level - level of cache. For TLB units it is set to
HI_CPU_CACHE_TLB_LEVEL
-
c_type - what information can keep this cache: data, instructions or both
-
c_size - size of cache in bytes
-
c_associativity - associativity of cache
-
c_unit_size.line - size of cache line for memory cache
-
c_unit_size.page - up to four page sizes this TLB unit may keep
NOTES
TLB units also considered as cache objects, but this information is rarely provided by OS (Solaris is best).
typedef struct { int c_level; hi_cpu_cache_type_t c_type; uint32_t c_size; int c_associativity; union { int line; long page[4]; } c_unit_size; } hi_cpu_cache_t;
typedef struct hi_cpu_object
Main CPUInfo descriptor
Each object as id
which is unique across all objects of that type
(except for caches).
Most of object ids are generated by HostInfo, but for Strand objects they are
taken from operating system, so they may be reused in various API calls like CPU mask
creation.
MEMBERS
-
hdr - HIObject header
-
c_cpu_name - name of CPU object (same as
hdr.name
) -
id - object id
-
type - object type
-
node - for Nodes - descriptor of type
hi_cpu_node_t
-
chip - for Chips - descriptor of type
hi_cpu_chip_t
-
cache - for Caches - descriptor of type
hi_cpu_cache_t
typedef struct hi_cpu_object { hi_object_header_t hdr; #define c_cpu_name hdr.name int id; hi_cpu_objtype_t type; union { hi_cpu_node_t node; hi_cpu_chip_t chip; hi_cpu_core_t core; hi_cpu_strand_t strand; hi_cpu_cache_t cache; }; } hi_cpu_object_t;