mirror of
https://github.com/anrieff/libcpuid
synced 2025-10-13 11:10:39 +00:00
* Support for stdin/stdout for (de)serializing cpu_raw_data_t;
* set_warn_function renamed to cpuid_set_warn_function; * Updated Doxygen documentation: added manpage output, generic mainpage intro, default module named correctly; * Updated doxy libcpuid.h documentation, fixed some bugs; * Warnings are now printed to stderr by default, not stdout; * Some constants in AMD code did not reflected their meaning well, fixed; * The cpuid_tool utility thoroughly redesigned; now a multiple-function program, perhaps close to the finalized state. git-svn-id: https://svn.code.sf.net/p/libcpuid/code/HEAD/libcpuid@19 3b4be424-7ac5-41d7-8526-f4ddcb85d872
This commit is contained in:
parent
5c348fd6bd
commit
c5c0539372
7 changed files with 638 additions and 99 deletions
|
@ -862,7 +862,7 @@ RTF_EXTENSIONS_FILE =
|
|||
# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
|
||||
# generate man pages
|
||||
|
||||
GENERATE_MAN = NO
|
||||
GENERATE_MAN = YES
|
||||
|
||||
# The MAN_OUTPUT tag is used to specify where the man pages will be put.
|
||||
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
|
||||
static int _libcpiud_errno = ERR_OK;
|
||||
|
||||
static int set_error(cpuid_error_t err)
|
||||
static int set_error(cpu_error_t err)
|
||||
{
|
||||
_libcpiud_errno = (int) err;
|
||||
return (int) err;
|
||||
|
@ -291,7 +291,10 @@ int cpuid_serialize_raw_data(struct cpu_raw_data_t* data, const char* filename)
|
|||
int i;
|
||||
FILE *f;
|
||||
|
||||
f = fopen(filename, "wt");
|
||||
if (!strcmp(filename, ""))
|
||||
f = stdout;
|
||||
else
|
||||
f = fopen(filename, "wt");
|
||||
if (!f) return set_error(ERR_OPEN);
|
||||
|
||||
fprintf(f, "version=%s\n", VERSION);
|
||||
|
@ -308,7 +311,8 @@ int cpuid_serialize_raw_data(struct cpu_raw_data_t* data, const char* filename)
|
|||
data->intel_fn4[i][0], data->intel_fn4[i][1],
|
||||
data->intel_fn4[i][2], data->intel_fn4[i][3]);
|
||||
|
||||
fclose(f);
|
||||
if (strcmp(filename, ""))
|
||||
fclose(f);
|
||||
return set_error(ERR_OK);
|
||||
}
|
||||
|
||||
|
@ -325,7 +329,10 @@ int cpuid_deserialize_raw_data(struct cpu_raw_data_t* data, const char* filename
|
|||
|
||||
raw_data_t_constructor(data);
|
||||
|
||||
f = fopen(filename, "rt");
|
||||
if (!strcmp(filename, ""))
|
||||
f = stdin;
|
||||
else
|
||||
f = fopen(filename, "rt");
|
||||
if (!f) return set_error(ERR_OPEN);
|
||||
while (fgets(line, sizeof(line), f)) {
|
||||
++cur_line;
|
||||
|
@ -360,7 +367,8 @@ int cpuid_deserialize_raw_data(struct cpu_raw_data_t* data, const char* filename
|
|||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
if (strcmp(filename, ""))
|
||||
fclose(f);
|
||||
return set_error(ERR_OK);
|
||||
}
|
||||
|
||||
|
@ -489,7 +497,7 @@ const char* cpu_feature_str(cpu_feature_t feature)
|
|||
|
||||
const char* cpuid_error(void)
|
||||
{
|
||||
const struct { cpuid_error_t error; const char *description; }
|
||||
const struct { cpu_error_t error; const char *description; }
|
||||
matchtable[] = {
|
||||
{ ERR_OK , "No error"},
|
||||
{ ERR_NO_CPUID , "CPUID instruction is not supported"},
|
||||
|
@ -513,7 +521,7 @@ const char* cpuid_lib_version(void)
|
|||
return VERSION;
|
||||
}
|
||||
|
||||
libcpuid_warn_fn_t set_warn_function(libcpuid_warn_fn_t new_fn)
|
||||
libcpuid_warn_fn_t cpuid_set_warn_function(libcpuid_warn_fn_t new_fn)
|
||||
{
|
||||
libcpuid_warn_fn_t ret = _warn_fun;
|
||||
_warn_fun = new_fn;
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef __LIBCPUID_H__
|
||||
#define __LIBCPUID_H__
|
||||
/**
|
||||
* @File libcpuid.h
|
||||
* @Author Veselin Georgiev
|
||||
|
@ -34,9 +36,21 @@
|
|||
* 0.1.0 (2008-10-15): initial adaptation from wxfractgui sources
|
||||
*/
|
||||
|
||||
/** @defgroup libcpuid @{ */
|
||||
#ifndef __LIBCPUID_H__
|
||||
#define __LIBCPUID_H__
|
||||
/** @mainpage A simple libcpuid introduction
|
||||
*
|
||||
* LibCPUID provides CPU identification and access to the CPUID and RDTSC
|
||||
* instructions on the x86.
|
||||
* <p>
|
||||
* To execute CPUID, use \ref cpu_exec_cpuid <br>
|
||||
* To execute RDTSC, use \ref cpu_rdtsc <br>
|
||||
* To fetch the CPUID info needed for CPU identification, use
|
||||
* \ref cpuid_get_raw_data <br>
|
||||
* To make sense of that data (decode, extract features), use \ref cpu_identify <br>
|
||||
* </p>
|
||||
*/
|
||||
|
||||
/** @defgroup libcpuid LibCPUID
|
||||
@{ */
|
||||
|
||||
/* Include some integer type specifications: */
|
||||
#include "libcpuid_types.h"
|
||||
|
@ -51,23 +65,22 @@ extern "C" {
|
|||
/**
|
||||
* @brief CPU vendor, as guessed from the Vendor String.
|
||||
*/
|
||||
enum _cpu_vendor_t {
|
||||
VENDOR_INTEL = 0,
|
||||
VENDOR_AMD,
|
||||
VENDOR_CYRIX,
|
||||
VENDOR_NEXGEN,
|
||||
VENDOR_TRANSMETA,
|
||||
VENDOR_UMC,
|
||||
VENDOR_CENTAUR,
|
||||
VENDOR_RISE,
|
||||
VENDOR_SIS,
|
||||
VENDOR_NSC,
|
||||
typedef enum {
|
||||
VENDOR_INTEL = 0, /*!< Intel CPU */
|
||||
VENDOR_AMD, /*!< AMD CPU */
|
||||
VENDOR_CYRIX, /*!< Cyrix CPU */
|
||||
VENDOR_NEXGEN, /*!< NexGen CPU */
|
||||
VENDOR_TRANSMETA, /*!< Transmeta CPU */
|
||||
VENDOR_UMC, /*!< x86 CPU by UMC */
|
||||
VENDOR_CENTAUR, /*!< x86 CPU by IDT */
|
||||
VENDOR_RISE, /*!< x86 CPU by Rise Technology */
|
||||
VENDOR_SIS, /*!< x86 CPU by SiS */
|
||||
VENDOR_NSC, /*!< x86 CPU by National Semiconductor */
|
||||
|
||||
NUM_CPU_VENDORS,
|
||||
NUM_CPU_VENDORS, /*!< Valid CPU vendor ids: 0..NUM_CPU_VENDORS - 1 */
|
||||
VENDOR_UNKNOWN = -1,
|
||||
};
|
||||
} cpu_vendor_t;
|
||||
#define NUM_CPU_VENDORS NUM_CPU_VENDORS
|
||||
typedef enum _cpu_vendor_t cpu_vendor_t;
|
||||
|
||||
/**
|
||||
* @brief Contains just the raw CPUID data.
|
||||
|
@ -209,7 +222,7 @@ struct cpu_id_t {
|
|||
* ...
|
||||
* struct cpu_raw_data_t raw;
|
||||
* struct cpu_id_t id;
|
||||
* if (cpuid_get_raw_data(&raw) == 0 && cpu_identify(&raw, &id)) {
|
||||
* if (cpuid_get_raw_data(&raw) == 0 && cpu_identify(&raw, &id) == 0) {
|
||||
* if (id.flags[CPU_FEATURE_SSE2]) {
|
||||
* // The CPU has SSE2...
|
||||
* ...
|
||||
|
@ -221,7 +234,7 @@ struct cpu_id_t {
|
|||
* }
|
||||
* @endcode
|
||||
*/
|
||||
enum _cpu_feature_t {
|
||||
typedef enum {
|
||||
CPU_FEATURE_FPU = 0, /*!< Floating point unit */
|
||||
CPU_FEATURE_VME, /*!< Virtual mode extension */
|
||||
CPU_FEATURE_DE, /*!< Debugging extension */
|
||||
|
@ -307,13 +320,12 @@ enum _cpu_feature_t {
|
|||
CPU_FEATURE_CONSTANT_TSC, /*!< TSC ticks at constant rate */
|
||||
// termination:
|
||||
NUM_CPU_FEATURES,
|
||||
};
|
||||
typedef enum _cpu_feature_t cpu_feature_t;
|
||||
} cpu_feature_t;
|
||||
|
||||
/**
|
||||
* @brief Describes common library error codes
|
||||
*/
|
||||
enum _cpuid_error_t {
|
||||
typedef enum {
|
||||
ERR_OK = 0, /*!< "No error" */
|
||||
ERR_NO_CPUID = -1, /*!< "CPUID instruction is not supported" */
|
||||
ERR_NO_RDTSC = -2, /*!< "RDTSC instruction is not supported" */
|
||||
|
@ -322,8 +334,7 @@ enum _cpuid_error_t {
|
|||
ERR_BADFMT = -5, /*!< "Bad file format" */
|
||||
ERR_NOT_IMP = -6, /*!< "Not implemented" */
|
||||
ERR_CPU_UNKN = -7, /*!< "Unsupported processor" */
|
||||
};
|
||||
typedef enum _cpuid_error_t cpuid_error_t;
|
||||
} cpu_error_t;
|
||||
|
||||
/**
|
||||
* @brief Internal structure, used in cpu_tsc_mark, cpu_tsc_unmark and
|
||||
|
@ -363,8 +374,9 @@ void cpu_exec_cpuid_ext(uint32_t* regs);
|
|||
/**
|
||||
* @brief Obtains the raw CPUID data
|
||||
* @param data - a pointer to cpu_raw_data_t structure
|
||||
* @returns zero if successful, and some negative number on error (@see cpuid_error_t)
|
||||
* The error message can be obtained by calling cpuid_error
|
||||
* @returns zero if successful, and some negative number on error.
|
||||
* The error message can be obtained by calling \ref cpuid_error.
|
||||
* @see cpu_error_t
|
||||
*/
|
||||
int cpuid_get_raw_data(struct cpu_raw_data_t* data);
|
||||
|
||||
|
@ -372,7 +384,7 @@ int cpuid_get_raw_data(struct cpu_raw_data_t* data);
|
|||
* @brief Writes the raw CPUID data to a text file
|
||||
* @param data - a pointer to cpu_raw_data_t structure
|
||||
* @param filename - the path of the file, where the serialized data should be
|
||||
* written
|
||||
* written. If empty, stdout will be used.
|
||||
* @note This is intended primarily for debugging. On some processor, which is
|
||||
* not currently supported or not completely recognized by cpu_identify,
|
||||
* one can still successfully get the raw data and write it to a file.
|
||||
|
@ -381,8 +393,9 @@ int cpuid_get_raw_data(struct cpu_raw_data_t* data);
|
|||
* The file is simple text format of "something=value" pairs. Version info
|
||||
* is also written, but the format is not intended to be neither backward-
|
||||
* nor forward compatible.
|
||||
* @returns zero if successful, and some negative number on error (@see cpuid_error_t)
|
||||
* The error message can be obtained by calling cpuid_error
|
||||
* @returns zero if successful, and some negative number on error.
|
||||
* The error message can be obtained by calling \ref cpuid_error.
|
||||
* @see cpu_error_t
|
||||
*/
|
||||
int cpuid_serialize_raw_data(struct cpu_raw_data_t* data, const char* filename);
|
||||
|
||||
|
@ -391,10 +404,12 @@ int cpuid_serialize_raw_data(struct cpu_raw_data_t* data, const char* filename);
|
|||
* @param data - a pointer to cpu_raw_data_t structure. The deserialized data will
|
||||
* be written here.
|
||||
* @param filename - the path of the file, containing the serialized raw data.
|
||||
* If empty, stdin will be used.
|
||||
* @note This function may fail, if the file is created by different version of
|
||||
* the library. Also, see the notes on cpuid_serialize_raw_data.
|
||||
* @returns zero if successful, and some negative number on error (@see cpuid_error_t)
|
||||
* The error message can be obtained by calling cpuid_error
|
||||
* @returns zero if successful, and some negative number on error.
|
||||
* The error message can be obtained by calling \ref cpuid_error.
|
||||
* @see cpu_error_t
|
||||
*/
|
||||
int cpuid_deserialize_raw_data(struct cpu_raw_data_t* data, const char* filename);
|
||||
|
||||
|
@ -417,8 +432,9 @@ int cpuid_deserialize_raw_data(struct cpu_raw_data_t* data, const char* filename
|
|||
* performance significantly. Specifically, avoid writing "cpu feature
|
||||
* checker" wrapping function, which calls cpu_identify and returns the
|
||||
* value of some flag, if that function is going to be called frequently.
|
||||
* @returns zero if successful, and some negative number on error (@see cpuid_error_t)
|
||||
* The error message can be obtained by calling cpuid_error
|
||||
* @returns zero if successful, and some negative number on error.
|
||||
* The error message can be obtained by calling \ref cpuid_error.
|
||||
* @see cpu_error_t
|
||||
*/
|
||||
int cpu_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* data);
|
||||
|
||||
|
@ -437,6 +453,7 @@ const char* cpu_feature_str(cpu_feature_t feature);
|
|||
* libcpuid stores an `errno'-style error status, whose description
|
||||
* can be obtained with this function.
|
||||
* @note This function is not thread-safe
|
||||
* @see cpu_error_t
|
||||
*/
|
||||
const char* cpuid_error(void);
|
||||
|
||||
|
@ -469,11 +486,12 @@ void cpu_rdtsc(uint64_t* result);
|
|||
/**
|
||||
* @brief Store TSC and timing info
|
||||
*
|
||||
* This function stores the current TSC value (@see cpu_rdtsc) and current
|
||||
* 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.
|
||||
* @see cpu_rdtsc
|
||||
*
|
||||
* @param mark [out] - a pointer to a cpu_mark_t structure
|
||||
*/
|
||||
|
@ -526,10 +544,10 @@ int cpu_clock_by_mark(struct cpu_mark_t* mark);
|
|||
* @brief 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:
|
||||
* differ from the true clock for several reasons:<br><br>
|
||||
*
|
||||
* i) The CPU might be in some power saving state, while the OS reports its
|
||||
* full-power frequency, or vice-versa.
|
||||
* full-power frequency, or vice-versa.<br>
|
||||
* ii) In some cases you can raise or lower the CPU frequency with overclocking
|
||||
* utilities and the OS will not notice.
|
||||
*
|
||||
|
@ -552,18 +570,18 @@ int cpu_clock_by_os(void);
|
|||
* 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:
|
||||
* several reasons why it might be incorrect:<br>
|
||||
*
|
||||
* 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.
|
||||
* guarantee.<br>
|
||||
* 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)
|
||||
* instead.<br>
|
||||
* iii) On SMP systems exhibiting TSC drift (see \ref cpu_rdtsc)
|
||||
*
|
||||
* the quad_check option will run four consecutive measurements and
|
||||
* then return the average of the two most-consistent results. The total
|
||||
|
@ -606,7 +624,7 @@ typedef void (*libcpuid_warn_fn_t) (const char *msg);
|
|||
* @brief 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 stdout. However,
|
||||
* debug warnings. By default, these warnings are written to stderr. However,
|
||||
* you can set a custom function that will receive those warnings.
|
||||
*
|
||||
* @param warn_fun - the warning function you want to set. If NULL, warnings
|
||||
|
@ -615,7 +633,7 @@ typedef void (*libcpuid_warn_fn_t) (const char *msg);
|
|||
* @returns the current warning function. You can use the return value to
|
||||
* keep the previous warning function and restore it at your discretion.
|
||||
*/
|
||||
libcpuid_warn_fn_t set_warn_function(libcpuid_warn_fn_t warn_fun);
|
||||
libcpuid_warn_fn_t cpuid_set_warn_function(libcpuid_warn_fn_t warn_fun);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}; // extern "C"
|
||||
|
|
|
@ -15,3 +15,4 @@ cpu_clock_by_os
|
|||
cpu_clock_measure
|
||||
cpu_clock
|
||||
cpuid_lib_version
|
||||
cpuid_set_warn_function
|
||||
|
|
|
@ -41,7 +41,7 @@ void match_features(const struct feature_map_t* matchtable, int count, uint32_t
|
|||
|
||||
static void default_warn(const char *msg)
|
||||
{
|
||||
printf("%s", msg);
|
||||
fprintf(stderr, "%s", msg);
|
||||
}
|
||||
|
||||
libcpuid_warn_fn_t _warn_fun = default_warn;
|
||||
|
|
|
@ -39,8 +39,7 @@ enum _amd_code_t {
|
|||
ATHLON_XP_BARTON,
|
||||
ATHLON_XP_M,
|
||||
ATHLON_XP_M_LV,
|
||||
ATHLON_64,
|
||||
ATHLON_64_MANCHESTER,
|
||||
ATHLON,
|
||||
ATHLON_MP,
|
||||
MOBILE_ATHLON64,
|
||||
ATHLON_FX,
|
||||
|
@ -102,7 +101,7 @@ const struct match_entry_t cpudb_amd[] = {
|
|||
{ 6, 4, -1, -1, -1, NO_CODE, "Athlon (ThunderBird)" },
|
||||
|
||||
{ 6, 6, -1, -1, -1, NO_CODE, "Unknown Athlon" },
|
||||
{ 6, 6, -1, -1, -1, ATHLON_64, "Athlon (Palomino)" },
|
||||
{ 6, 6, -1, -1, -1, ATHLON, "Athlon (Palomino)" },
|
||||
{ 6, 6, -1, -1, -1, ATHLON_MP, "Athlon MP (Palomino)" },
|
||||
{ 6, 6, -1, -1, -1, DURON, "Duron (Palomino)" },
|
||||
{ 6, 6, -1, -1, -1, ATHLON_XP, "Athlon XP" },
|
||||
|
@ -111,7 +110,7 @@ const struct match_entry_t cpudb_amd[] = {
|
|||
{ 6, 7, -1, -1, -1, DURON, "Duron (Morgan)" },
|
||||
|
||||
{ 6, 8, -1, -1, -1, NO_CODE, "Athlon XP" },
|
||||
{ 6, 8, -1, -1, -1, ATHLON_64, "Athlon XP" },
|
||||
{ 6, 8, -1, -1, -1, ATHLON, "Athlon XP" },
|
||||
{ 6, 8, -1, -1, -1, ATHLON_XP, "Athlon XP" },
|
||||
{ 6, 8, -1, -1, -1, DURON, "Duron (Applebred)" },
|
||||
{ 6, 8, -1, -1, -1, SEMPRON, "Sempron (Thoroughbred)" },
|
||||
|
@ -122,7 +121,7 @@ const struct match_entry_t cpudb_amd[] = {
|
|||
{ 6, 8, -1, -1, -1, ATHLON_XP_M_LV, "Mobile Athlon (Thoroughbred)" },
|
||||
|
||||
{ 6, 10, -1, -1, -1, NO_CODE, "Athlon XP (Barton)" },
|
||||
{ 6, 10, -1, -1, -1, ATHLON_64, "Athlon XP (Barton)" },
|
||||
{ 6, 10, -1, -1, -1, ATHLON, "Athlon XP (Barton)" },
|
||||
{ 6, 10, -1, -1, -1, ATHLON_XP_BARTON, "Athlon XP (Barton)" },
|
||||
{ 6, 10, -1, -1, -1, SEMPRON, "Sempron (Barton)" },
|
||||
{ 6, 10, -1, -1, -1, SEMPRON_64_256K, "Sempron (Barton)" },
|
||||
|
@ -280,7 +279,7 @@ static amd_code_t decode_amd_codename_part1(const char *bs)
|
|||
if (strstr(bs, "Athlon(tm) XP")) return ATHLON_XP;
|
||||
if (strstr(bs, "Athlon(tm) MP")) return ATHLON_MP;
|
||||
if (strstr(bs, "Duron")) return DURON;
|
||||
if (strstr(bs, "Athlon")) return ATHLON_64;
|
||||
if (strstr(bs, "Athlon")) return ATHLON;
|
||||
}
|
||||
|
||||
return NO_CODE;
|
||||
|
@ -290,8 +289,6 @@ static void decode_amd_codename(struct cpu_raw_data_t* raw, struct cpu_id_t* dat
|
|||
{
|
||||
amd_code_t code = decode_amd_codename_part1(data->brand_str);
|
||||
|
||||
if (code == ATHLON_64 && data->l2_cache == 512)
|
||||
code = ATHLON_64_MANCHESTER;
|
||||
if (code == ATHLON_XP && data->l2_cache == 512)
|
||||
code = ATHLON_XP_BARTON;
|
||||
if (code == ATHLON_64_512K && data->l2_cache > 512)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue