Compare commits
No commits in common. "e9b478d56925ac19c2ce59b4cac206c11db9f90d" and "dcf3cd2ac2744e829593120076327a9db92f6d23" have entirely different histories.
e9b478d569
...
dcf3cd2ac2
9 changed files with 191 additions and 308 deletions
|
|
@ -1,5 +0,0 @@
|
||||||
REM MS yo me cago en tus putisimos muertos que cojones es este bug centenario estupido y miserable con los parametros?
|
|
||||||
REM este comentario es de cuando me lo encontre hace rato, pero me hace gracia, asi que se queda
|
|
||||||
|
|
||||||
CALL buildlib.bat
|
|
||||||
CALL buildtest.bat
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
REM MS yo me cago en tus putisimos muertos que cojones es este bug centenario estupido y miserable con los parametros?
|
|
||||||
REM este comentario es de cuando me lo encontre hace rato, pero me hace gracia, asi que se queda
|
|
||||||
|
|
||||||
CALL builddlib.bat
|
|
||||||
CALL builddtest.bat
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
clang++ -DDEBUG -D_DEBUG -shared src\tmrtsc.cpp -o build\libtmrtscd.dll -Wall -Wextra -Wpedantic -std=c++11 -g -gcodeview -Wl,-pdb= -L C:\capybara\libclang\x86_64-w64-mingw32\bin -Wl,-Bstatic -l c++ -l unwind --verbose
|
|
||||||
|
|
||||||
REM -lmsvcrt -lucrtbase -lvcruntime140_app
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
clang++ -DDEBUG -D_DEBUG -dynamic src\test\test.cpp -o build\testd.exe -Wall -Wextra -Wpedantic -std=c++11 -g -gcodeview -Wl,-pdb= -L C:\capybara\libclang\x86_64-w64-mingw32\bin -L D:\Contenido\Capybara\Cositas\tmr\build -Wl,-Bstatic -l c++ -l unwind -Wl,-Bdynamic -l tmrtsc --verbose
|
|
||||||
|
|
||||||
REM -fms-runtime-lib dll_dbgx
|
|
||||||
REM -lmsvcrt -lucrtbase -lvcruntime140_app
|
|
||||||
|
|
@ -1,2 +1 @@
|
||||||
clang++ -shared src\tmrtsc.cpp -o build\libtmrtsc.dll -Wall -Wextra -Wpedantic -std=c++11 -L C:\capybara\libclang\x86_64-w64-mingw32\bin -Wl,-Bstatic -l c++ -l unwind --verbose
|
clang++ -D DEBUG src\tmrtsc.hpp -Wall -Wextra -Wpedantic -std=c++11 -g -gcodeview -Wl,-pdb= -L C:\capybara\libclang\x86_64-w64-mingw32\bin -l c++ -l unwind --verbose
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
clang++ -dynamic src\test\test.cpp -o build\test.exe -Wall -Wextra -Wpedantic -std=c++11 -L C:\capybara\libclang\x86_64-w64-mingw32\bin -L D:\Contenido\Capybara\Cositas\tmr\build -Wl,-Bstatic -l c++ -l unwind -Wl,-Bdynamic -l tmrtsc --verbose
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
#ifdef _WIN64
|
|
||||||
#define UNICODE
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
|
||||||
#define DllImport __declspec( dllimport )
|
|
||||||
#define _MT
|
|
||||||
#define _DLL
|
|
||||||
#include <Windows.h>
|
|
||||||
#include <libloaderapi.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "../debug.h"
|
|
||||||
#include "../tmrtsc.hpp"
|
|
||||||
|
|
||||||
using namespace tmr;
|
|
||||||
|
|
||||||
#ifdef _WIN64
|
|
||||||
int main(int argc, char** argv){
|
|
||||||
HMODULE dell;
|
|
||||||
DWORD fracaso;
|
|
||||||
//DllImport TSCTimer* timer;
|
|
||||||
int sleep = 1000;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* dell = LoadLibraryExW(TEXT("libtmrtsc.dll"), NULL, NULL);
|
|
||||||
* if (dell == NULL) {
|
|
||||||
* fracaso = GetLastError();
|
|
||||||
* return -1;
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
TSCTimer* timer = nullptr;
|
|
||||||
timer = TSCTimer::getTimer();
|
|
||||||
if(timer == nullptr)
|
|
||||||
return -2;
|
|
||||||
uint64_t t1 = timer->getTimeStamp();
|
|
||||||
Sleep(sleep);
|
|
||||||
uint64_t t2 = timer->getTimeStamp();
|
|
||||||
uint64_t fr = timer->getBaseFrequency();
|
|
||||||
std::cout << "Siestecita de: " << sleep << " ms" << std::endl;
|
|
||||||
std::cout << "Windows Momento: \nt1: " << t1 << " t2: " << t2 << " fr: " << fr << std::endl;
|
|
||||||
std::cout << "restita: " << t2-t1 << std::endl;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
int main(int argc, char** argv){
|
|
||||||
return -9;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
209
src/tmrtsc.cpp
209
src/tmrtsc.cpp
|
|
@ -1,209 +0,0 @@
|
||||||
//TODO juntar heaps?
|
|
||||||
#include "tmrtsc.hpp"
|
|
||||||
|
|
||||||
#if _WIN64
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace tmr {
|
|
||||||
|
|
||||||
TSCTimer::TSCTimer(char* vendorName, int64_t baseFreq) {
|
|
||||||
this->vendorName = vendorName;
|
|
||||||
this->baseFreq = baseFreq;
|
|
||||||
this->availableRDTSCP = (checkRDTSCP()) ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
TSCTimer::~TSCTimer () {
|
|
||||||
free(vendorName);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TSCTimer::checkInvariantTSC() {
|
|
||||||
uint64_t rdx;
|
|
||||||
asm volatile (".intel_syntax noprefix\t\n" \
|
|
||||||
"mov eax, 0x80000007\t\n" \
|
|
||||||
"cpuid\t\n" : "=d" (rdx) );
|
|
||||||
bool iTSC = rdx & (1<<8);
|
|
||||||
return iTSC;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
char* TSCTimer::readVendorName () {
|
|
||||||
char* palabritas = (char*)malloc(sizeof(char) * 13);
|
|
||||||
uint8_t siguienteLetra = 0;
|
|
||||||
uint64_t regs[3];
|
|
||||||
asm volatile ( ".intel_syntax noprefix\t\n" \
|
|
||||||
"mov eax, 0x0\t\n" \
|
|
||||||
"cpuid\t\n" : "=b" (regs[0]), "=c" (regs[2]), "=d" (regs[1]) );
|
|
||||||
int byte = 0;
|
|
||||||
for (int reg = 0; reg < 3; reg++, byte = 0){
|
|
||||||
char* charifiedReg = (char*)®s[reg];
|
|
||||||
for(; byte < 4; byte++, siguienteLetra++ ){
|
|
||||||
palabritas[siguienteLetra] = charifiedReg[byte];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
palabritas[siguienteLetra] = '\0';
|
|
||||||
return palabritas;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t TSCTimer::intelRetrieveART(){
|
|
||||||
//TODO: Find a valid Intel CPU to debug ART route
|
|
||||||
//if (freq == nullptr) return -
|
|
||||||
|
|
||||||
uint64_t raxde, rbxnum, rcxhz;
|
|
||||||
asm volatile ( ".intel_syntax noprefix\t\n" \
|
|
||||||
"mov eax, 0x15\t\n" \
|
|
||||||
"cpuid\t\n" : "=a" (raxde), "=b" (rbxnum), "=c" (rcxhz) );
|
|
||||||
log_debugcpp("hmm " << raxde << " " << rbxnum << " " << rcxhz);
|
|
||||||
if (rbxnum == 0 || rcxhz == 0) return ART_NOT_REPORTED;
|
|
||||||
int64_t TSCFreq = (rcxhz * rbxnum)/raxde;
|
|
||||||
//*freq = TSCFreq;
|
|
||||||
log_debugcpp("raxo " << TSCFreq << " " << TSCFreq);
|
|
||||||
return TSCFreq;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _WIN64
|
|
||||||
|
|
||||||
int64_t TSCTimer::getFreqFromSystem(){
|
|
||||||
//TODO: close opened key
|
|
||||||
const WORD STRING_SIZE = 4;
|
|
||||||
const WCHAR COMPARE_TARGET[STRING_SIZE + 1] = L"~MHz";
|
|
||||||
DWORD longestDataSize;
|
|
||||||
|
|
||||||
LSTATUS status;
|
|
||||||
HKEY key;
|
|
||||||
DWORD numValues;
|
|
||||||
|
|
||||||
WCHAR valName[MAX_VALUE_NAME]; //uint32_t wtf
|
|
||||||
DWORD valLen = MAX_VALUE_NAME;
|
|
||||||
|
|
||||||
LPBYTE dataContent = nullptr;
|
|
||||||
DWORD dataLen;
|
|
||||||
|
|
||||||
status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"), 0,
|
|
||||||
KEY_QUERY_VALUE, &key);
|
|
||||||
if(status != ERROR_SUCCESS) return CANT_OPEN_KEY;
|
|
||||||
|
|
||||||
status = RegQueryInfoKey(
|
|
||||||
key, // key handle
|
|
||||||
NULL, // buffer for class name
|
|
||||||
NULL, // size of class string
|
|
||||||
NULL, // reserved
|
|
||||||
NULL, // num of subkeys
|
|
||||||
NULL, // longest subkey size
|
|
||||||
NULL, // longest class string
|
|
||||||
&numValues, // num of values for this key
|
|
||||||
NULL, // longest value name
|
|
||||||
&longestDataSize, // longest value data
|
|
||||||
NULL, // security descriptor
|
|
||||||
NULL); // last write time
|
|
||||||
if(status != ERROR_SUCCESS) return CANT_RETRIEVE_KEY_INFO;
|
|
||||||
|
|
||||||
dataLen = sizeof(REG_QWORD) * (longestDataSize);
|
|
||||||
dataContent = (LPBYTE)malloc(dataLen);
|
|
||||||
for (DWORD i = 0; i < numValues; i++){
|
|
||||||
valLen = MAX_VALUE_NAME;
|
|
||||||
dataLen = sizeof(REG_QWORD) * (longestDataSize);
|
|
||||||
status = RegEnumValueW(key,
|
|
||||||
i,
|
|
||||||
valName,
|
|
||||||
&valLen,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
dataContent,
|
|
||||||
&dataLen
|
|
||||||
);
|
|
||||||
|
|
||||||
if(status != ERROR_SUCCESS) return CANT_READ_DATA_FROM_VALUE;
|
|
||||||
|
|
||||||
if (CSTR_EQUAL == CompareStringEx(
|
|
||||||
LOCALE_NAME_INVARIANT,
|
|
||||||
NORM_LINGUISTIC_CASING,
|
|
||||||
valName,
|
|
||||||
valLen,
|
|
||||||
COMPARE_TARGET,
|
|
||||||
STRING_SIZE,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
0
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
LPDWORD PMHz = (LPDWORD)dataContent;
|
|
||||||
DWORD MHz = *PMHz;
|
|
||||||
free(dataContent);
|
|
||||||
return MHz * 1000000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return CANT_READ_DATA_FROM_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool TSCTimer::checkRDTSCP(){ //Generic
|
|
||||||
uint64_t rdx;
|
|
||||||
asm volatile (".intel_syntax noprefix\t\n" \
|
|
||||||
"mov eax, 0x80000001\t\n" \
|
|
||||||
// 080000007h\t\n"
|
|
||||||
"cpuid\t\n" : "=d" (rdx) );
|
|
||||||
bool RDTSCP = rdx & (1<<27);
|
|
||||||
//"and edx, 10000000\n")
|
|
||||||
return RDTSCP;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t TSCTimer::readRDTSC() {
|
|
||||||
uint64_t raxlo,rdxho;
|
|
||||||
asm volatile ( ".intel_syntax noprefix\t\n"
|
|
||||||
"lfence\n" \
|
|
||||||
"rdtsc\n" \
|
|
||||||
"lfence\n" : "=a" (raxlo), "=d" (rdxho));
|
|
||||||
return (rdxho << 32) + raxlo; //|
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t TSCTimer::readRDTSCP(uint64_t* logicore) {
|
|
||||||
uint64_t raxlo,rdxho, rcx;
|
|
||||||
asm volatile ( ".intel_syntax noprefix\t\n"
|
|
||||||
"rdtscp\t\n"
|
|
||||||
"lfence\t\n": "=a" (raxlo), "=d" (rdxho), "=c" (rcx) );
|
|
||||||
if (logicore != nullptr) *logicore = rcx;
|
|
||||||
return (rdxho << 32) + raxlo; //|
|
|
||||||
}
|
|
||||||
|
|
||||||
TSCTimer* TSCTimer::getTimer() {
|
|
||||||
if (!checkInvariantTSC()) return nullptr;
|
|
||||||
//TODO debug dis
|
|
||||||
const char vendorNames[2][13] = {
|
|
||||||
{"AuthenticAMD"},
|
|
||||||
{"GenuineIntel"}
|
|
||||||
};
|
|
||||||
char* vendorName = readVendorName();
|
|
||||||
int64_t baseFreq = ART_NOT_REPORTED;
|
|
||||||
|
|
||||||
if (strcmp(vendorName, vendorNames[1]) == 0)
|
|
||||||
baseFreq = intelRetrieveART();
|
|
||||||
if (baseFreq == ART_NOT_REPORTED)
|
|
||||||
baseFreq = getFreqFromSystem();
|
|
||||||
if (baseFreq < OPERATION_SUCCESSFUL)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
//timer =
|
|
||||||
return new TSCTimer(vendorName, baseFreq);
|
|
||||||
//return OPERATION_SUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t TSCTimer::getTimeStamp(){
|
|
||||||
if (availableRDTSCP)
|
|
||||||
return readRDTSCP();
|
|
||||||
else
|
|
||||||
return readRDTSC();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t TSCTimer::getBaseFrequency(){
|
|
||||||
return baseFreq;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef _WIN64
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
221
src/tmrtsc.hpp
221
src/tmrtsc.hpp
|
|
@ -1,5 +1,4 @@
|
||||||
//TODO It's threadin' time
|
//TODO It's threadin' time
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
#define LIB_EXPORT __declspec(dllexport)
|
#define LIB_EXPORT __declspec(dllexport)
|
||||||
|
|
@ -8,8 +7,6 @@
|
||||||
#define _WIN32_WINNT _WIN32_WINNT_WIN10 //0x0A00
|
#define _WIN32_WINNT _WIN32_WINNT_WIN10 //0x0A00
|
||||||
#define MAX_KEY_LENGTH 255
|
#define MAX_KEY_LENGTH 255
|
||||||
#define MAX_VALUE_NAME 32767
|
#define MAX_VALUE_NAME 32767
|
||||||
#define _MT
|
|
||||||
#define _DLL
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <winreg.h>
|
#include <winreg.h>
|
||||||
#include <stringapiset.h>
|
#include <stringapiset.h>
|
||||||
|
|
@ -23,22 +20,22 @@
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
|
/*
|
||||||
#if _WIN64
|
* #if _WIN64
|
||||||
extern "C" {
|
* extern "C" {)
|
||||||
#endif
|
* #endif
|
||||||
|
*/
|
||||||
namespace tmr {
|
namespace tmr {
|
||||||
|
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
enum winReturnValues{
|
enum LIB_EXPORT winReturnValues{
|
||||||
CANT_OPEN_KEY = -1,
|
CANT_OPEN_KEY = -1,
|
||||||
CANT_RETRIEVE_KEY_INFO = -2,
|
CANT_RETRIEVE_KEY_INFO = -2,
|
||||||
CANT_READ_DATA_FROM_VALUE = -3,
|
CANT_READ_DATA_FROM_VALUE = -3,
|
||||||
CANT_RETRIEVE_FREQUENCY = -4
|
CANT_RETRIEVE_FREQUENCY = -4
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
enum ReturnValues {
|
enum LIB_EXPORT ReturnValues {
|
||||||
OPERATION_SUCCESSFUL = 0,
|
OPERATION_SUCCESSFUL = 0,
|
||||||
INVARIANT_TSC_NOT_SUPPORTED = -1,
|
INVARIANT_TSC_NOT_SUPPORTED = -1,
|
||||||
UNSUPPORTED_CPU = -2,
|
UNSUPPORTED_CPU = -2,
|
||||||
|
|
@ -49,49 +46,211 @@ namespace tmr {
|
||||||
class LIB_EXPORT TSCTimer {
|
class LIB_EXPORT TSCTimer {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//static TSCTimer timer;
|
static TSCTimer timer;
|
||||||
|
|
||||||
char* vendorName;
|
char* vendorName;
|
||||||
int64_t baseFreq = ART_NOT_REPORTED;
|
int64_t baseFreq = ART_NOT_REPORTED;
|
||||||
bool availableRDTSCP = false;
|
bool availableRDTSCP;
|
||||||
int64_t art; //reserved
|
int64_t art; //reserved
|
||||||
|
|
||||||
TSCTimer(char* vendorName, int64_t baseFreq);
|
TSCTimer (char* vendorName, int64_t baseFreq) {
|
||||||
|
this->vendorName = vendorName;
|
||||||
|
this->baseFreq = baseFreq;
|
||||||
|
availableRDTSCP = (checkRDTSCP()) ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
~TSCTimer();
|
~TSCTimer () {
|
||||||
|
free(vendorName);
|
||||||
|
}
|
||||||
|
|
||||||
static bool checkInvariantTSC();
|
static bool checkInvariantTSC() {
|
||||||
|
uint64_t rdx;
|
||||||
|
asm volatile (".intel_syntax noprefix\t\n" \
|
||||||
|
"mov eax, 0x80000007\t\n" \
|
||||||
|
"cpuid\t\n" : "=d" (rdx) );
|
||||||
|
bool iTSC = rdx & (1<<8);
|
||||||
|
return iTSC;
|
||||||
|
}
|
||||||
|
|
||||||
static char* readVendorName ();
|
|
||||||
|
static char* readVendorName () {
|
||||||
|
char* palabritas = (char*)malloc(sizeof(char) * 13);
|
||||||
|
uint8_t siguienteLetra = 0;
|
||||||
|
uint64_t regs[3];
|
||||||
|
asm volatile ( ".intel_syntax noprefix\t\n" \
|
||||||
|
"mov eax, 0x0\t\n" \
|
||||||
|
"cpuid\t\n" : "=b" (regs[0]), "=c" (regs[2]), "=d" (regs[1]) );
|
||||||
|
int byte = 0;
|
||||||
|
for (int reg = 0; reg < 3; reg++, byte = 0){
|
||||||
|
char* charifiedReg = (char*)®s[reg];
|
||||||
|
for(; byte < 4; byte++, siguienteLetra++ ){
|
||||||
|
palabritas[siguienteLetra] = charifiedReg[byte];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
palabritas[siguienteLetra] = '\0';
|
||||||
|
return palabritas;
|
||||||
|
}
|
||||||
|
|
||||||
static int64_t intelRetrieveART();
|
static int64_t intelRetrieveART(){
|
||||||
|
//TODO: Find a valid Intel CPU to debug ART route
|
||||||
|
//if (freq == nullptr) return -
|
||||||
|
|
||||||
|
uint64_t raxde, rbxnum, rcxhz;
|
||||||
|
asm volatile ( ".intel_syntax noprefix\t\n" \
|
||||||
|
"mov eax, 0x15\t\n" \
|
||||||
|
"cpuid\t\n" : "=a" (raxde), "=b" (rbxnum), "=c" (rcxhz) );
|
||||||
|
log_debugcpp("hmm " << raxde << " " << rbxnum << " " << rcxhz);
|
||||||
|
if (rbxnum == 0 || rcxhz == 0) return ART_NOT_REPORTED;
|
||||||
|
int64_t TSCFreq = (rcxhz * rbxnum)/raxde;
|
||||||
|
//*freq = TSCFreq;
|
||||||
|
log_debugcpp("raxo " << TSCFreq << " " << TSCFreq);
|
||||||
|
return TSCFreq;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
|
|
||||||
static int64_t getFreqFromSystem();
|
static int64_t getFreqFromSystem(){
|
||||||
|
//TODO: close opened key
|
||||||
|
const WORD STRING_SIZE = 4;
|
||||||
|
const WCHAR COMPARE_TARGET[STRING_SIZE + 1] = L"~MHz";
|
||||||
|
DWORD longestDataSize;
|
||||||
|
|
||||||
|
LSTATUS status;
|
||||||
|
HKEY key;
|
||||||
|
DWORD numValues;
|
||||||
|
|
||||||
|
WCHAR valName[MAX_VALUE_NAME]; //uint32_t wtf
|
||||||
|
DWORD valLen = MAX_VALUE_NAME;
|
||||||
|
|
||||||
|
LPBYTE dataContent = nullptr;
|
||||||
|
DWORD dataLen;
|
||||||
|
|
||||||
|
status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"), 0,
|
||||||
|
KEY_QUERY_VALUE, &key);
|
||||||
|
if(status != ERROR_SUCCESS) return CANT_OPEN_KEY;
|
||||||
|
|
||||||
|
status = RegQueryInfoKey(
|
||||||
|
key, // key handle
|
||||||
|
NULL, // buffer for class name
|
||||||
|
NULL, // size of class string
|
||||||
|
NULL, // reserved
|
||||||
|
NULL, // num of subkeys
|
||||||
|
NULL, // longest subkey size
|
||||||
|
NULL, // longest class string
|
||||||
|
&numValues, // num of values for this key
|
||||||
|
NULL, // longest value name
|
||||||
|
&longestDataSize, // longest value data
|
||||||
|
NULL, // security descriptor
|
||||||
|
NULL); // last write time
|
||||||
|
if(status != ERROR_SUCCESS) return CANT_RETRIEVE_KEY_INFO;
|
||||||
|
|
||||||
|
dataLen = sizeof(REG_QWORD) * (longestDataSize);
|
||||||
|
dataContent = (LPBYTE)malloc(dataLen);
|
||||||
|
for (DWORD i = 0; i < numValues; i++){
|
||||||
|
valLen = MAX_VALUE_NAME;
|
||||||
|
dataLen = sizeof(REG_QWORD) * (longestDataSize);
|
||||||
|
status = RegEnumValueW(key,
|
||||||
|
i,
|
||||||
|
valName,
|
||||||
|
&valLen,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
dataContent,
|
||||||
|
&dataLen
|
||||||
|
);
|
||||||
|
|
||||||
|
if(status != ERROR_SUCCESS) return CANT_READ_DATA_FROM_VALUE;
|
||||||
|
|
||||||
|
if (CSTR_EQUAL == CompareStringEx(
|
||||||
|
LOCALE_NAME_INVARIANT,
|
||||||
|
NORM_LINGUISTIC_CASING,
|
||||||
|
valName,
|
||||||
|
valLen,
|
||||||
|
COMPARE_TARGET,
|
||||||
|
STRING_SIZE,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
0
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
LPDWORD PMHz = (LPDWORD)dataContent;
|
||||||
|
DWORD MHz = *PMHz;
|
||||||
|
free(dataContent);
|
||||||
|
return MHz * 1000000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CANT_READ_DATA_FROM_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool checkRDTSCP();
|
bool checkRDTSCP(){ //Generic
|
||||||
|
uint64_t rdx;
|
||||||
|
asm volatile (".intel_syntax noprefix\t\n" \
|
||||||
|
"mov eax, 0x80000001\t\n" \
|
||||||
|
// 080000007h\t\n"
|
||||||
|
"cpuid\t\n" : "=d" (rdx) );
|
||||||
|
bool RDTSCP = rdx & (1<<27);
|
||||||
|
//"and edx, 10000000\n")
|
||||||
|
return RDTSCP;
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t readRDTSC();
|
uint64_t readRDTSC() {
|
||||||
|
uint64_t raxlo,rdxho;
|
||||||
|
asm volatile ( ".intel_syntax noprefix\t\n"
|
||||||
|
"lfence\n" \
|
||||||
|
"rdtsc\n" \
|
||||||
|
"lfence\n" : "=a" (raxlo), "=d" (rdxho));
|
||||||
|
return (rdxho << 32) + raxlo; //|
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t readRDTSCP(uint64_t* logicore = nullptr );
|
uint64_t readRDTSCP(uint64_t* logicore = nullptr ) {
|
||||||
|
uint64_t raxlo,rdxho, rcx;
|
||||||
|
asm volatile ( ".intel_syntax noprefix\t\n"
|
||||||
|
"rdtscp\t\n"
|
||||||
|
"lfence\t\n": "=a" (raxlo), "=d" (rdxho), "=c" (rcx) );
|
||||||
|
if (logicore != nullptr) *logicore = rcx;
|
||||||
|
return (rdxho << 32) + raxlo; //|
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// static int getTimer(TSCTimer* timer = nullptr);
|
static int getTimer(TSCTimer* timer = nullptr) {
|
||||||
static TSCTimer* getTimer();
|
if (!checkInvariantTSC()) return INVARIANT_TSC_NOT_SUPPORTED;
|
||||||
|
//TODO debug dis
|
||||||
|
const char vendorNames[2][13] = {
|
||||||
|
{"AuthenticAMD"},
|
||||||
|
{"GenuineIntel"}
|
||||||
|
};
|
||||||
|
char* vendorName = readVendorName();
|
||||||
|
int64_t baseFreq;
|
||||||
|
|
||||||
|
if (strcmp(vendorName, vendorNames[1]))
|
||||||
|
baseFreq = intelRetrieveART();
|
||||||
|
if (baseFreq == ART_NOT_REPORTED)
|
||||||
|
baseFreq = getFreqFromSystem();
|
||||||
|
if (baseFreq < OPERATION_SUCCESSFUL)
|
||||||
|
return CANT_READ_FREQUENCY_FROM_SYSTEM;
|
||||||
|
|
||||||
uint64_t getTimeStamp();
|
timer = new TSCTimer(vendorName, baseFreq);
|
||||||
|
return OPERATION_SUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t getBaseFrequency();
|
uint64_t getTimeStamp(){
|
||||||
|
if (availableRDTSCP)
|
||||||
|
return readRDTSCP();
|
||||||
|
else
|
||||||
|
return readRDTSC();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t getBaseFrequency(){
|
||||||
|
return baseFreq;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
#ifdef _WIN64
|
* #ifdef _WIN64
|
||||||
}
|
* }
|
||||||
#endif
|
* #endif
|
||||||
|
*/
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue