Still learning the D(ll)
This commit is contained in:
parent
d3ef419a85
commit
dcf3cd2ac2
2 changed files with 88 additions and 64 deletions
1
buildlib.bat
Normal file
1
buildlib.bat
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
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
|
||||||
147
src/tmrtsc.hpp
147
src/tmrtsc.hpp
|
|
@ -1,10 +1,7 @@
|
||||||
//TODO It's threadin' time
|
//TODO It's threadin' time
|
||||||
|
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
//TODO mirame esta
|
#define LIB_EXPORT __declspec(dllexport)
|
||||||
#ifndef DEBUG
|
|
||||||
#define DEBUG
|
|
||||||
#endif
|
|
||||||
#define UNICODE
|
#define UNICODE
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#define _WIN32_WINNT _WIN32_WINNT_WIN10 //0x0A00
|
#define _WIN32_WINNT _WIN32_WINNT_WIN10 //0x0A00
|
||||||
|
|
@ -14,47 +11,105 @@
|
||||||
#include <winreg.h>
|
#include <winreg.h>
|
||||||
#include <stringapiset.h>
|
#include <stringapiset.h>
|
||||||
#include <synchapi.h>
|
#include <synchapi.h>
|
||||||
|
#else
|
||||||
|
#define LIB_EXPORT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* #if _WIN64
|
||||||
|
* extern "C" {)
|
||||||
|
* #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_AVAILABLE = -1,
|
INVARIANT_TSC_NOT_SUPPORTED = -1,
|
||||||
UNSUPPORTED_CPU = -2,
|
UNSUPPORTED_CPU = -2,
|
||||||
CANT_READ_FREQUENCY_FROM_SYSTEM = -3,
|
CANT_READ_FREQUENCY_FROM_SYSTEM = -3,
|
||||||
ART_NOT_REPORTED = -4
|
ART_NOT_REPORTED = -4
|
||||||
};
|
};
|
||||||
|
|
||||||
class TSCTimer {
|
class LIB_EXPORT TSCTimer {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static TSCTimer timer;
|
static TSCTimer timer;
|
||||||
static char* vendorName;
|
|
||||||
static int64_t baseFreq = ART_NOT_REPORTED;
|
|
||||||
|
|
||||||
|
char* vendorName;
|
||||||
|
int64_t baseFreq = ART_NOT_REPORTED;
|
||||||
bool availableRDTSCP;
|
bool availableRDTSCP;
|
||||||
int64_t art; //reserved
|
int64_t art; //reserved
|
||||||
|
|
||||||
TSCtimer () {
|
TSCTimer (char* vendorName, int64_t baseFreq) {
|
||||||
|
this->vendorName = vendorName;
|
||||||
|
this->baseFreq = baseFreq;
|
||||||
availableRDTSCP = (checkRDTSCP()) ? true : false;
|
availableRDTSCP = (checkRDTSCP()) ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~TSCTimer () {
|
||||||
|
free(vendorName);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 () {
|
||||||
|
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(){
|
||||||
|
//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
|
||||||
|
|
||||||
int64_t getFreqFromSystem(){
|
static int64_t getFreqFromSystem(){
|
||||||
//TODO: close opened key
|
//TODO: close opened key
|
||||||
const WORD STRING_SIZE = 4;
|
const WORD STRING_SIZE = 4;
|
||||||
const WCHAR COMPARE_TARGET[STRING_SIZE + 1] = L"~MHz";
|
const WCHAR COMPARE_TARGET[STRING_SIZE + 1] = L"~MHz";
|
||||||
|
|
@ -129,15 +184,6 @@ namespace tmr {
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool checkRDTSCP(){ //Generic
|
bool checkRDTSCP(){ //Generic
|
||||||
uint64_t rdx;
|
uint64_t rdx;
|
||||||
asm volatile (".intel_syntax noprefix\t\n" \
|
asm volatile (".intel_syntax noprefix\t\n" \
|
||||||
|
|
@ -149,40 +195,6 @@ namespace tmr {
|
||||||
return RDTSCP;
|
return RDTSCP;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t intelCheckART(){
|
|
||||||
//TODO: Find a valid Intel CPU to debug ART route
|
|
||||||
//if (freq == nullptr) return -
|
|
||||||
|
|
||||||
uint64_t 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 << " " << *freq);
|
|
||||||
return TSCFreq;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t readRDTSC() {
|
uint64_t readRDTSC() {
|
||||||
uint64_t raxlo,rdxho;
|
uint64_t raxlo,rdxho;
|
||||||
asm volatile ( ".intel_syntax noprefix\t\n"
|
asm volatile ( ".intel_syntax noprefix\t\n"
|
||||||
|
|
@ -203,13 +215,14 @@ namespace tmr {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static int getTimer(TSCTimer* timer = nullptr) {
|
static int getTimer(TSCTimer* timer = nullptr) {
|
||||||
if (!checkInvariantTSC) return INVARIANT_TSC_NOT_SUPPORTED;
|
if (!checkInvariantTSC()) return INVARIANT_TSC_NOT_SUPPORTED;
|
||||||
|
//TODO debug dis
|
||||||
const char vendorNames[2][13] = {
|
const char vendorNames[2][13] = {
|
||||||
{"AuthenticAMD\0"},
|
{"AuthenticAMD"},
|
||||||
{"GenuineIntel\0"}
|
{"GenuineIntel"}
|
||||||
};
|
};
|
||||||
vendorName = readVendorName();
|
char* vendorName = readVendorName();
|
||||||
|
int64_t baseFreq;
|
||||||
|
|
||||||
if (strcmp(vendorName, vendorNames[1]))
|
if (strcmp(vendorName, vendorNames[1]))
|
||||||
baseFreq = intelRetrieveART();
|
baseFreq = intelRetrieveART();
|
||||||
|
|
@ -218,7 +231,7 @@ namespace tmr {
|
||||||
if (baseFreq < OPERATION_SUCCESSFUL)
|
if (baseFreq < OPERATION_SUCCESSFUL)
|
||||||
return CANT_READ_FREQUENCY_FROM_SYSTEM;
|
return CANT_READ_FREQUENCY_FROM_SYSTEM;
|
||||||
|
|
||||||
timer = new TSCTimer();
|
timer = new TSCTimer(vendorName, baseFreq);
|
||||||
return OPERATION_SUCCESSFUL;
|
return OPERATION_SUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -229,5 +242,15 @@ namespace tmr {
|
||||||
return readRDTSC();
|
return readRDTSC();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
uint64_t getBaseFrequency(){
|
||||||
|
return baseFreq;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* #ifdef _WIN64
|
||||||
|
* }
|
||||||
|
* #endif
|
||||||
|
*/
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue