mirror of
https://github.com/anrieff/libcpuid
synced 2025-01-23 20:06:41 +00:00
Removed C++ style comments; added CPU clock measuring code
git-svn-id: https://svn.code.sf.net/p/libcpuid/code/HEAD/libcpuid@29 3b4be424-7ac5-41d7-8526-f4ddcb85d872
This commit is contained in:
parent
7774c94046
commit
9cf8005f3a
12 changed files with 179 additions and 30 deletions
|
@ -240,6 +240,7 @@ static int parse_cmdline(int argc, char** argv)
|
|||
recog = 1;
|
||||
}
|
||||
if (!strcmp(arg, "--clock-rdtsc")) {
|
||||
need_clockreport = 1;
|
||||
need_timed_clockreport = 1;
|
||||
recog = 1;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
int cpuid_exists_by_eflags(void)
|
||||
{
|
||||
#ifdef __x86_64__
|
||||
return 1; // CPUID is always present on the x86_64
|
||||
return 1; /* CPUID is always present on the x86_64 */
|
||||
#else
|
||||
# ifdef __GNUC__
|
||||
int result;
|
||||
|
@ -70,9 +70,9 @@ int cpuid_exists_by_eflags(void)
|
|||
return (result != 0);
|
||||
# else
|
||||
# error "Unsupported compiler"
|
||||
# endif // _MSC_VER
|
||||
# endif // __GNUC__
|
||||
#endif // __x86_64__
|
||||
# endif /* _MSC_VER */
|
||||
# endif /* __GNUC__ */
|
||||
#endif /* __x86_64__ */
|
||||
}
|
||||
|
||||
void exec_cpiud(uint32_t *regs)
|
||||
|
@ -133,7 +133,7 @@ void exec_cpiud(uint32_t *regs)
|
|||
:"m"(regs)
|
||||
:"memory", "eax"
|
||||
);
|
||||
# endif // __x86_64__
|
||||
# endif /* __x86_64__ */
|
||||
#else
|
||||
# ifdef _MSC_VER
|
||||
__asm {
|
||||
|
@ -162,7 +162,7 @@ void exec_cpiud(uint32_t *regs)
|
|||
}
|
||||
# else
|
||||
# error "Unsupported compiler"
|
||||
# endif // _MSC_VER
|
||||
# endif /* _MSC_VER */
|
||||
#endif
|
||||
|
||||
}
|
||||
|
@ -186,7 +186,7 @@ void cpu_rdtsc(uint64_t* result)
|
|||
};
|
||||
# else
|
||||
# error "Unsupported compiler"
|
||||
# endif // _MSC_VER
|
||||
#endif // __GNUC__
|
||||
# endif /* _MSC_VER */
|
||||
#endif /* __GNUC__ */
|
||||
*result = (uint64_t)low_part + (((uint64_t) hi_part) << 32);
|
||||
}
|
||||
|
|
|
@ -30,4 +30,4 @@
|
|||
int cpuid_exists_by_eflags(void);
|
||||
void exec_cpiud(uint32_t *regs);
|
||||
|
||||
#endif // __ASM_BITS_H__
|
||||
#endif /* __ASM_BITS_H__ */
|
||||
|
|
|
@ -64,8 +64,8 @@ static int parse_token(const char* expected_token, const char *token,
|
|||
int veax, vebx, vecx, vedx;
|
||||
int index;
|
||||
|
||||
if (*recognized) return 1; // already recognized
|
||||
if (strncmp(token, expected_token, strlen(expected_token))) return 1; // not what we search for
|
||||
if (*recognized) return 1; /* already recognized */
|
||||
if (strncmp(token, expected_token, strlen(expected_token))) return 1; /* not what we search for */
|
||||
sprintf(format, "%s[%%d]", expected_token);
|
||||
*recognized = 1;
|
||||
if (1 == sscanf(token, format, &index) && index >=0 && index < limit) {
|
||||
|
@ -134,7 +134,7 @@ static int get_total_cpus(void)
|
|||
}
|
||||
return 1;
|
||||
}
|
||||
#endif // GET_TOTAL_CPUS_DEFINED
|
||||
#endif /* GET_TOTAL_CPUS_DEFINED */
|
||||
|
||||
|
||||
static void load_features_common(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
|
||||
|
@ -353,7 +353,7 @@ int cpuid_deserialize_raw_data(struct cpu_raw_data_t* data, const char* filename
|
|||
strncpy(token, line, i);
|
||||
token[i] = '\0';
|
||||
value = &line[i + 1];
|
||||
// try to recognize the line
|
||||
/* try to recognize the line */
|
||||
recognized = 0;
|
||||
if (!strcmp(token, "version")) {
|
||||
recognized = 1;
|
||||
|
|
|
@ -318,7 +318,7 @@ typedef enum {
|
|||
CPU_FEATURE_100MHZSTEPS,/*!< 100 MHz multiplier control */
|
||||
CPU_FEATURE_HWPSTATE, /*!< Hardware P-state control */
|
||||
CPU_FEATURE_CONSTANT_TSC, /*!< TSC ticks at constant rate */
|
||||
// termination:
|
||||
/* termination: */
|
||||
NUM_CPU_FEATURES,
|
||||
} cpu_feature_t;
|
||||
|
||||
|
@ -636,10 +636,10 @@ typedef void (*libcpuid_warn_fn_t) (const char *msg);
|
|||
libcpuid_warn_fn_t cpuid_set_warn_function(libcpuid_warn_fn_t warn_fun);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}; // extern "C"
|
||||
}; /* extern "C" */
|
||||
#endif
|
||||
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif // __LIBCPUID_H__
|
||||
#endif /* __LIBCPUID_H__ */
|
||||
|
|
|
@ -39,4 +39,4 @@
|
|||
#define MAX_EXT_CPUID_LEVEL 32
|
||||
#define MAX_INTELFN4_LEVEL 4
|
||||
|
||||
#endif // __LIBCPUID_CONSTANTS_H__
|
||||
#endif /* __LIBCPUID_CONSTANTS_H__ */
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#if defined(HAVE_STDINT_H)
|
||||
# include <stdint.h>
|
||||
#else
|
||||
// we have to provide our own:
|
||||
/* we have to provide our own: */
|
||||
# if !defined(HAVE_INT32_T) && !defined(__int32_t_defined)
|
||||
typedef int int32_t;
|
||||
# endif
|
||||
|
@ -53,4 +53,4 @@ typedef unsigned long long uint64_t;
|
|||
|
||||
#endif
|
||||
|
||||
#endif // __LIBCPUID_TYPES_H__
|
||||
#endif /* __LIBCPUID_TYPES_H__ */
|
||||
|
|
|
@ -53,4 +53,4 @@ __attribute__((format(printf, 1, 2)))
|
|||
|
||||
extern libcpuid_warn_fn_t _warn_fun;
|
||||
|
||||
#endif // __LIBCPUID_UTIL_H__
|
||||
#endif /* __LIBCPUID_UTIL_H__ */
|
||||
|
|
158
libcpuid/rdtsc.c
158
libcpuid/rdtsc.c
|
@ -23,33 +23,181 @@
|
|||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "libcpuid.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
static void sys_precise_clock(uint64_t *result)
|
||||
{
|
||||
LARGE_INTEGER freq, counter;
|
||||
QueryPerformanceCounter(&counter);
|
||||
QueryPerformanceFrequency(&freq);
|
||||
double c = counter.QuadPart;
|
||||
double f = freq.QuadPart;
|
||||
result = (uint64_t) ( c * 1000000.0 / f );
|
||||
}
|
||||
#else
|
||||
/* assuming Linux, Mac OS or other POSIX */
|
||||
#include <sys/time.h>
|
||||
static void sys_precise_clock(uint64_t *result)
|
||||
{
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
*result = (uint64_t) tv.tv_sec * (uint64_t) 1000000 +
|
||||
(uint64_t) tv.tv_usec;
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
/* out = a - b */
|
||||
static void mark_t_subtract(struct cpu_mark_t* a, struct cpu_mark_t* b, struct cpu_mark_t *out)
|
||||
{
|
||||
out->tsc = a->tsc - b->tsc;
|
||||
out->sys_clock = a->sys_clock - b->sys_clock;
|
||||
}
|
||||
|
||||
void cpu_tsc_mark(struct cpu_mark_t* mark)
|
||||
{
|
||||
cpu_rdtsc(&mark->tsc);
|
||||
sys_precise_clock(&mark->sys_clock);
|
||||
}
|
||||
|
||||
void cpu_tsc_unmark(struct cpu_mark_t* mark)
|
||||
{
|
||||
struct cpu_mark_t temp;
|
||||
cpu_tsc_mark(&temp);
|
||||
mark_t_subtract(&temp, mark, mark);
|
||||
}
|
||||
|
||||
|
||||
int cpu_clock_by_mark(struct cpu_mark_t* mark)
|
||||
{
|
||||
return 1400; // FIXME
|
||||
uint64_t result;
|
||||
|
||||
/* Check if some subtraction resulted in a negative number: */
|
||||
if ((mark->tsc >> 63) != 0 || (mark->sys_clock >> 63) != 0) return -1;
|
||||
|
||||
/* Divide-by-zero check: */
|
||||
if (mark->sys_clock == 0) return -1;
|
||||
|
||||
/* Check if the result fits in 32bits */
|
||||
result = mark->tsc / mark->sys_clock;
|
||||
if (result > (uint64_t) 0x7fffffff) return -1;
|
||||
return (int) result;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
int cpu_clock_by_os(void)
|
||||
{
|
||||
HKEY key;
|
||||
char buff[20];
|
||||
DWORD size = 20;
|
||||
int result;
|
||||
|
||||
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\\~MHz", 0, KEY_READ, &key) != ERROR_SUCCESS)
|
||||
return -1;
|
||||
|
||||
if (RegQueryValueEx(key, "~MHz", NULL, NULL, (LPBYTE) buff, (LPDWORD) &size) != ERROR_SUCCESS) {
|
||||
RegCloseKey(key);
|
||||
return -1;
|
||||
}
|
||||
buff[size] = 0;
|
||||
RegCloseKey(key);
|
||||
|
||||
if (1 != sscanf(buff, "%d", &result))
|
||||
return -1;
|
||||
return result;
|
||||
}
|
||||
#else
|
||||
/* Assuming Linux with /proc/cpuinfo */
|
||||
int cpu_clock_by_os(void)
|
||||
{
|
||||
return 1400; // FIXME
|
||||
FILE *f;
|
||||
char line[1024], *s;
|
||||
int result;
|
||||
|
||||
f = fopen("/proc/cpuinfo", "rt");
|
||||
if (!f) return -1;
|
||||
|
||||
while (fgets(line, sizeof(line), f)) {
|
||||
if (!strncmp(line, "cpu MHz", 7)) {
|
||||
s = strchr(line, ':');
|
||||
if (s && 1 == sscanf(s, ":%d.", &result)) {
|
||||
fclose(f);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
return -1;
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
/* Emulate doing useful CPU intensive work */
|
||||
static int busy_loop(int amount)
|
||||
{
|
||||
int i, j, k, s = 0;
|
||||
static volatile int data[42] = {32, 12, -1, 5, 23, 0 };
|
||||
for (i = 0; i < amount; i++)
|
||||
for (j = 0; j < 65536; j++)
|
||||
for (k = 0; k < 42; k++)
|
||||
s += data[k];
|
||||
return s;
|
||||
}
|
||||
|
||||
int cpu_clock_measure(int millis, int triple_check)
|
||||
int cpu_clock_measure(int millis, int quad_check)
|
||||
{
|
||||
return 1400; // FIXME
|
||||
struct cpu_mark_t begin[4], end[4], temp, temp2;
|
||||
int results[4], cycles, n, k, i, j, bi, bj, mdiff, diff, _zero = 0;
|
||||
uint64_t tl;
|
||||
|
||||
if (millis < 1) return -1;
|
||||
tl = millis * (uint64_t) 1000;
|
||||
if (quad_check)
|
||||
tl /= 4;
|
||||
n = quad_check ? 4 : 1;
|
||||
cycles = 1;
|
||||
for (k = 0; k < n; k++) {
|
||||
cpu_tsc_mark(&begin[k]);
|
||||
end[k] = begin[k];
|
||||
do {
|
||||
/* Run busy loop, and fool the compiler that we USE the garbishy
|
||||
value it calculates */
|
||||
_zero |= (1 & busy_loop(cycles));
|
||||
cpu_tsc_mark(&temp);
|
||||
mark_t_subtract(&temp, &end[k], &temp2);
|
||||
/* If busy loop is too short, increase it */
|
||||
if (temp2.sys_clock < tl / 8)
|
||||
cycles *= 2;
|
||||
end[k] = temp;
|
||||
} while (end[k].sys_clock - begin[k].sys_clock < tl);
|
||||
mark_t_subtract(&end[k], &begin[k], &temp);
|
||||
results[k] = cpu_clock_by_mark(&temp);
|
||||
}
|
||||
if (n == 1) return results[k];
|
||||
mdiff = 0x7fffffff;
|
||||
bi = bj = -1;
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = i + 1; j < 4; j++) {
|
||||
diff = results[i] - results[j];
|
||||
if (diff < 0) diff = -diff;
|
||||
if (diff < mdiff) {
|
||||
mdiff = diff;
|
||||
bi = i;
|
||||
bj = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (results[bi] == -1) return -1;
|
||||
return (results[bi] + results[bj] + _zero) / 2;
|
||||
}
|
||||
|
||||
int cpu_clock(void)
|
||||
{
|
||||
return 1400; // FIXME
|
||||
int result;
|
||||
result = cpu_clock_by_os();
|
||||
if (result <= 0)
|
||||
result = cpu_clock_measure(200, 1);
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -28,4 +28,4 @@
|
|||
|
||||
int cpuid_identify_amd(struct cpu_raw_data_t* raw, struct cpu_id_t* data);
|
||||
|
||||
#endif // __RECOG_AMD_H__
|
||||
#endif /* __RECOG_AMD_H__ */
|
||||
|
|
|
@ -108,7 +108,7 @@ const struct match_entry_t cpudb_intel[] = {
|
|||
{ 6, 5, -1, -1, -1, CELERON , "P-II Celeron (no L2)" },
|
||||
{ 6, 6, -1, -1, -1, CELERON , "P-II Celeron (128K)" },
|
||||
|
||||
/* ////////////////////////////////////////////////// */
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
{ 6, 7, -1, -1, -1, NO_CODE , "Pentium III (Katmai)" },
|
||||
{ 6, 8, -1, -1, -1, NO_CODE , "Pentium III (Coppermine)"},
|
||||
|
@ -125,7 +125,7 @@ const struct match_entry_t cpudb_intel[] = {
|
|||
{ 6, 10, -1, -1, -1, CELERON , "P-III Celeron" },
|
||||
{ 6, 11, -1, -1, -1, CELERON , "P-III Celeron" },
|
||||
|
||||
/* ////////////////////////////////////////////////// */
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
{ 6, 9, -1, -1, -1, NO_CODE , "Unknown Pentium M" },
|
||||
{ 6, 9, -1, -1, -1, MOBILE_PENTIUM_M , "Unknown Pentium M" },
|
||||
|
@ -139,7 +139,7 @@ const struct match_entry_t cpudb_intel[] = {
|
|||
{ 6, 12, -1, -1, -1, ATOM_DUALCORE , "Atom (Dual Core)" },
|
||||
{ 6, 12, -1, -1, -1, ATOM_SILVERTHORNE , "Atom (Silverthorne)" },
|
||||
|
||||
/* ////////////////////////////////////////////////// */
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
{ 6, 14, -1, -1, -1, NO_CODE , "Unknown Yonah" },
|
||||
{ 6, 14, -1, -1, -1, CORE_SOLO , "Yonah (Core Solo)" },
|
||||
|
|
|
@ -28,4 +28,4 @@
|
|||
|
||||
int cpuid_identify_intel(struct cpu_raw_data_t* raw, struct cpu_id_t* data);
|
||||
|
||||
#endif //__RECOG_INTEL_H__
|
||||
#endif /*__RECOG_INTEL_H__*/
|
||||
|
|
Loading…
Reference in a new issue