libcpuid
0.2.2
|
Data Structures | |
struct | cpu_raw_data_t |
Contains just the raw CPUID data. More... | |
struct | cpu_id_t |
This contains the recognized CPU features/info. More... | |
struct | cpu_mark_t |
Internal structure, used in cpu_tsc_mark, cpu_tsc_unmark and cpu_clock_by_mark. More... | |
struct | cpu_list_t |
a structure that holds a list of processor names More... | |
Macros | |
#define | NUM_CPU_VENDORS NUM_CPU_VENDORS |
#define | CPU_INVALID_VALUE 0x3fffffff |
Typedefs | |
typedef void(* | libcpuid_warn_fn_t) (const char *msg) |
Functions | |
int | cpuid_get_total_cpus (void) |
Returns the total number of CPUs even if CPUID is not present. More... | |
int | cpuid_present (void) |
Checks if the CPUID instruction is supported. More... | |
void | cpu_exec_cpuid (uint32_t eax, uint32_t *regs) |
Executes the CPUID instruction. More... | |
void | cpu_exec_cpuid_ext (uint32_t *regs) |
Executes the CPUID instruction with the given input registers. More... | |
int | cpuid_get_raw_data (struct cpu_raw_data_t *data) |
Obtains the raw CPUID data from the current CPU. More... | |
int | cpuid_serialize_raw_data (struct cpu_raw_data_t *data, const char *filename) |
Writes the raw CPUID data to a text file. More... | |
int | cpuid_deserialize_raw_data (struct cpu_raw_data_t *data, const char *filename) |
Reads raw CPUID data from file. More... | |
int | cpu_identify (struct cpu_raw_data_t *raw, struct cpu_id_t *data) |
Identifies the CPU. More... | |
const char * | cpu_feature_str (cpu_feature_t feature) |
Returns the short textual representation of a CPU flag. More... | |
const char * | cpuid_error (void) |
Returns textual description of the last error. More... | |
void | cpu_rdtsc (uint64_t *result) |
Executes RDTSC. More... | |
void | cpu_tsc_mark (struct cpu_mark_t *mark) |
Store TSC and timing info. More... | |
void | cpu_tsc_unmark (struct cpu_mark_t *mark) |
Calculate TSC and timing difference. More... | |
int | cpu_clock_by_mark (struct cpu_mark_t *mark) |
Calculates the CPU clock. More... | |
int | cpu_clock_by_os (void) |
Returns the CPU clock, as reported by the OS. More... | |
int | cpu_clock_measure (int millis, int quad_check) |
Measure the CPU clock frequency. More... | |
int | cpu_clock_by_ic (int millis, int runs) |
Measure the CPU clock frequency using instruction-counting. More... | |
int | cpu_clock (void) |
Get the CPU clock frequency (all-in-one method) More... | |
const char * | cpuid_lib_version (void) |
Returns the libcpuid version. More... | |
libcpuid_warn_fn_t | cpuid_set_warn_function (libcpuid_warn_fn_t warn_fun) |
Sets the warning print function. More... | |
void | cpuid_set_verbosiness_level (int level) |
Sets the verbosiness level. More... | |
cpu_vendor_t | cpuid_get_vendor (void) |
Obtains the CPU vendor from CPUID from the current CPU. More... | |
void | cpuid_get_cpu_list (cpu_vendor_t vendor, struct cpu_list_t *list) |
Gets a list of all known CPU names from a specific vendor. More... | |
void | cpuid_free_cpu_list (struct cpu_list_t *list) |
Frees a CPU list. More... | |
struct msr_driver_t * | cpu_msr_driver_open (void) |
Starts/opens a driver, needed to read MSRs (Model Specific Registers) More... | |
struct msr_driver_t * | cpu_msr_driver_open_core (unsigned core_num) |
Similar to cpu_msr_driver_open, but accept one parameter. More... | |
int | cpu_rdmsr (struct msr_driver_t *handle, uint32_t msr_index, uint64_t *result) |
Reads a Model-Specific Register (MSR) More... | |
int | cpu_rdmsr_range (struct msr_driver_t *handle, uint32_t msr_index, uint8_t highbit, uint8_t lowbit, uint64_t *result) |
Similar to cpu_rdmsr, but extract a range of bits. More... | |
int | cpu_msrinfo (struct msr_driver_t *handle, cpu_msrinfo_request_t which) |
Reads extended CPU information from Model-Specific Registers. More... | |
int | cpu_msr_driver_close (struct msr_driver_t *handle) |
Closes an open MSR driver. More... | |
enum cpu_error_t |
Describes common library error codes.
enum cpu_feature_t |
CPU feature identifiers.
Usage:
enum cpu_hint_t |
enum cpu_vendor_t |
CPU vendor, as guessed from the Vendor String.
int cpu_clock | ( | void | ) |
Get the CPU clock frequency (all-in-one method)
This is an all-in-one method for getting the CPU clock frequency. It tries to use the OS for that. If the OS doesn't have this info, it uses cpu_clock_measure with 200ms time interval and quadruple checking.
int cpu_clock_by_ic | ( | int | millis, |
int | runs | ||
) |
Measure the CPU clock frequency using instruction-counting.
millis | - how much time to allocate for each run, in milliseconds |
runs | - how many runs to perform |
The function performs a busy-wait cycle using a known number of "heavy" (SSE) instructions. These instructions run at (more or less guaranteed) 1 IPC rate, so by running a busy loop for a fixed amount of time, and measuring the amount of instructions done, the CPU clock is accurately measured.
Of course, this function is still affected by the power-saving schemes, so the warnings as of cpu_clock_measure() still apply. However, this function is immune to problems with detection, related to the Intel Nehalem's "Turbo" mode, where the internal clock is raised, but the RDTSC rate is unaffected.
The function will run for about (millis * runs) milliseconds. You can make only a single busy-wait run (runs == 1); however, this can be affected by task scheduling (which will break the counting), so allowing more than one run is recommended. As run length is not imperative for accurate readings (e.g., 50ms is sufficient), you can afford a lot of short runs, e.g. 10 runs of 50ms or 20 runs of 25ms.
Recommended values - millis = 50, runs = 4. For more robustness, increase the number of runs.
NOTE: on Bulldozer and later CPUs, the busy-wait cycle runs at 1.4 IPC, thus the results are skewed. This is corrected internally by dividing the resulting value by 1.4. However, this only occurs if the thread is executed on a single CMT module - if there are other threads competing for resources, the results are unpredictable. Make sure you run cpu_clock_by_ic() on a CPU that is free from competing threads, or if there are such threads, they shouldn't exceed the number of modules. On a Bulldozer X8, that means 4 threads.
int cpu_clock_by_mark | ( | struct cpu_mark_t * | mark | ) |
Calculates the CPU clock.
mark | - pointer to a cpu_mark_t structure, which has been initialized with cpu_tsc_mark and later `stopped' with cpu_tsc_unmark. |
int cpu_clock_by_os | ( | void | ) |
Returns the CPU clock, as reported by the OS.
This function uses OS-specific functions to obtain the CPU clock. It may differ from the true clock for several reasons:
i) The CPU might be in some power saving state, while the OS reports its full-power frequency, or vice-versa.
ii) In some cases you can raise or lower the CPU frequency with overclocking utilities and the OS will not notice.
int cpu_clock_measure | ( | int | millis, |
int | quad_check | ||
) |
Measure the CPU clock frequency.
millis | - How much time to waste in the busy-wait cycle. In millisecs. Useful values 10 - 1000 |
quad_check | - Do a more thorough measurement if nonzero (see the explanation). |
The function performs a busy-wait cycle for the given time and calculates the CPU frequency by the difference of the TSC values. The accuracy of the calculation depends on the length of the busy-wait cycle: more is better, but 100ms should be enough for most purposes.
While this will calculate the CPU frequency correctly in most cases, there are several reasons why it might be incorrect:
i) RDTSC doesn't guarantee it will run at the same clock as the CPU. Apparently there aren't CPUs at the moment, but still, there's no guarantee.
ii) The CPU might be in a low-frequency power saving mode, and the CPU might be switched to higher frequency at any time. If this happens during the measurement, the result can be anywhere between the low and high frequencies. Also, if you're interested in the high frequency value only, this function might return the low one instead.
iii) On SMP systems exhibiting TSC drift (see cpu_rdtsc)
the quad_check option will run four consecutive measurements and then return the average of the two most-consistent results. The total runtime of the function will still be `millis' - consider using a bit more time for the timing interval.
Finally, for benchmarking / CPU intensive applications, the best strategy is to use the cpu_tsc_mark() / cpu_tsc_unmark() / cpu_clock_by_mark() method. Begin by mark()-ing about one second after application startup (allowing the power-saving manager to kick in and rise the frequency during that time), then unmark() just before application finishing. The result will most acurately represent at what frequency your app was running.
void cpu_exec_cpuid | ( | uint32_t | eax, |
uint32_t * | regs | ||
) |
Executes the CPUID instruction.
eax | - the value of the EAX register when executing CPUID |
regs | - the results will be stored here. regs[0] = EAX, regs[1] = EBX, ... |
void cpu_exec_cpuid_ext | ( | uint32_t * | regs | ) |
Executes the CPUID instruction with the given input registers.
regs | - Input/output. Prior to executing CPUID, EAX, EBX, ECX and EDX will be set to regs[0], regs[1], regs[2] and regs[3]. After CPUID, this array will contain the results. |
const char* cpu_feature_str | ( | cpu_feature_t | feature | ) |
Returns the short textual representation of a CPU flag.
feature | - the feature, whose textual representation is wanted. |
int cpu_identify | ( | struct cpu_raw_data_t * | raw, |
struct cpu_id_t * | data | ||
) |
Identifies the CPU.
raw | - Input - a pointer to the raw CPUID data, which is obtained either by cpuid_get_raw_data or cpuid_deserialize_raw_data. Can also be NULL, in which case the functions calls cpuid_get_raw_data itself. |
data | - Output - the decoded CPU features/info is written here. |
int cpu_msr_driver_close | ( | struct msr_driver_t * | handle | ) |
Closes an open MSR driver.
This function unloads the MSR driver opened by cpu_msr_driver_open and frees any resources associated with it.
handle | - a handle to the MSR reader driver, as created by cpu_msr_driver_open |
struct msr_driver_t* cpu_msr_driver_open | ( | void | ) |
Starts/opens a driver, needed to read MSRs (Model Specific Registers)
On systems that support it, this function will create a temporary system driver, that has privileges to execute the RDMSR instruction. After the driver is created, you can read MSRs by calling cpu_rdmsr
struct msr_driver_t* cpu_msr_driver_open_core | ( | unsigned | core_num | ) |
Similar to cpu_msr_driver_open, but accept one parameter.
This function works on certain operating systems (GNU/Linux, FreeBSD)
core_num | specify the core number for MSR. The first core number is 0. The last core number is cpuid_get_total_cpus - 1. |
int cpu_msrinfo | ( | struct msr_driver_t * | handle, |
cpu_msrinfo_request_t | which | ||
) |
Reads extended CPU information from Model-Specific Registers.
handle | - a handle to an open MSR driver, |
which | - which info field should be returned. A list of available information entities is listed in the cpu_msrinfo_request_t enum. |
- | if the requested information is available for the current processor model, the respective value is returned. if no information is available, or the CPU doesn't support the query, the special value CPU_INVALID_VALUE is returned |
int cpu_rdmsr | ( | struct msr_driver_t * | handle, |
uint32_t | msr_index, | ||
uint64_t * | result | ||
) |
Reads a Model-Specific Register (MSR)
If the CPU has MSRs (as indicated by the CPU_FEATURE_MSR flag), you can read a MSR with the given index by calling this function.
There are several prerequisites you must do before reading MSRs: 1) You must ensure the CPU has RDMSR. Check the CPU_FEATURE_MSR flag in cpu_id_t::flags 2) You must ensure that the CPU implements the specific MSR you intend to read. 3) You must open a MSR-reader driver. RDMSR is a privileged instruction and needs ring-0 access in order to work. This temporary driver is created by calling cpu_msr_driver_open
handle | - a handle to the MSR reader driver, as created by cpu_msr_driver_open |
msr_index | - the numeric ID of the MSR you want to read |
result | - a pointer to a 64-bit integer, where the MSR value is stored |
int cpu_rdmsr_range | ( | struct msr_driver_t * | handle, |
uint32_t | msr_index, | ||
uint8_t | highbit, | ||
uint8_t | lowbit, | ||
uint64_t * | result | ||
) |
Similar to cpu_rdmsr, but extract a range of bits.
handle | - a handle to the MSR reader driver, as created by cpu_msr_driver_open |
msr_index | - the numeric ID of the MSR you want to read |
highbit | - the high bit in range, must be inferior to 64 |
lowbit | - the low bit in range, must be equal or superior to 0 |
result | - a pointer to a 64-bit integer, where the MSR value is stored |
void cpu_rdtsc | ( | uint64_t * | result | ) |
Executes RDTSC.
The RDTSC (ReaD Time Stamp Counter) instruction gives access to an internal 64-bit counter, which usually increments at each clock cycle. This can be used for various timing routines, and as a very precise clock source. It is set to zero on system startup. Beware that may not increment at the same frequency as the CPU. Consecutive calls of RDTSC are, however, guaranteed to return monotonically-increasing values.
result | - a pointer to a 64-bit unsigned integer, where the TSC value will be stored |
void cpu_tsc_mark | ( | struct cpu_mark_t * | mark | ) |
Store TSC and timing info.
This function stores the current TSC value and current time info from a precise OS-specific clock source in the cpu_mark_t structure. The sys_clock field contains time with microsecond resolution. The values can later be used to measure time intervals, number of clocks, FPU frequency, etc.
mark | [out] - a pointer to a cpu_mark_t structure |
void cpu_tsc_unmark | ( | struct cpu_mark_t * | mark | ) |
Calculate TSC and timing difference.
mark | - input/output: a pointer to a cpu_mark_t sturcture, which has already been initialized by cpu_tsc_mark. The difference in TSC and time will be written here. |
This function calculates the TSC and time difference, by obtaining the current TSC and timing values and subtracting the contents of the `mark' structure from them. Results are written in the same structure.
Example:
int cpuid_deserialize_raw_data | ( | struct cpu_raw_data_t * | data, |
const char * | filename | ||
) |
Reads raw CPUID data from file.
data | - a pointer to cpu_raw_data_t structure. The deserialized data will be written here. |
filename | - the path of the file, containing the serialized raw data. If empty, stdin will be used. |
const char* cpuid_error | ( | void | ) |
Returns textual description of the last error.
libcpuid stores an `errno'-style error status, whose description can be obtained with this function.
void cpuid_free_cpu_list | ( | struct cpu_list_t * | list | ) |
Frees a CPU list.
This function deletes all the memory associated with a CPU list, as obtained by cpuid_get_cpu_list()
list | - the list to be free()'d. |
void cpuid_get_cpu_list | ( | cpu_vendor_t | vendor, |
struct cpu_list_t * | list | ||
) |
Gets a list of all known CPU names from a specific vendor.
This function compiles a list of all known CPU (code)names (i.e. the possible values of cpu_id_t::cpu_codename) for the given vendor.
There are about 100 entries for Intel and AMD, and a few for the other vendors. The list is written out in approximate chronological introduction order of the parts.
vendor | the vendor to be queried |
list | [out] the resulting list will be written here. NOTE: As the memory is dynamically allocated, be sure to call cpuid_free_cpu_list() after you're done with the data |
int cpuid_get_raw_data | ( | struct cpu_raw_data_t * | data | ) |
Obtains the raw CPUID data from the current CPU.
data | - a pointer to cpu_raw_data_t structure |
int cpuid_get_total_cpus | ( | void | ) |
Returns the total number of CPUs even if CPUID is not present.
Number | of CPUs available |
cpu_vendor_t cpuid_get_vendor | ( | void | ) |
Obtains the CPU vendor from CPUID from the current CPU.
const char* cpuid_lib_version | ( | void | ) |
Returns the libcpuid version.
int cpuid_present | ( | void | ) |
Checks if the CPUID instruction is supported.
1 | if CPUID is present |
0 | the CPU doesn't have CPUID. |
int cpuid_serialize_raw_data | ( | struct cpu_raw_data_t * | data, |
const char * | filename | ||
) |
Writes the raw CPUID data to a text file.
data | - a pointer to cpu_raw_data_t structure |
filename | - the path of the file, where the serialized data should be written. If empty, stdout will be used. |
void cpuid_set_verbosiness_level | ( | int | level | ) |
Sets the verbosiness level.
When the verbosiness level is above zero, some functions might print diagnostic information about what are they doing. The higher the level is, the more detail is printed. Level zero is guaranteed to omit all such output. The output is written using the same machinery as the warnings,
level | the desired verbosiness level. Useful values 0..2 inclusive |
libcpuid_warn_fn_t cpuid_set_warn_function | ( | libcpuid_warn_fn_t | warn_fun | ) |
Sets the warning print function.
In some cases, the internal libcpuid machinery would like to emit useful debug warnings. By default, these warnings are written to stderr. However, you can set a custom function that will receive those warnings.
warn_fun | - the warning function you want to set. If NULL, warnings are disabled. The function takes const char* argument. |