sketch. time to thread
This commit is contained in:
parent
64727ac279
commit
8b9e1a38cb
2 changed files with 241 additions and 1 deletions
|
|
@ -1,3 +1,10 @@
|
|||
/*
|
||||
* THREADIN THE LINUS: https://linux.die.net/man/2/sched_setaffinity
|
||||
*/
|
||||
/*
|
||||
*THREADIN THE WINDOS: https://learn.microsoft.com/en-us/windows/win32/procthread/process-and-thread-functions
|
||||
*/
|
||||
|
||||
//clangbug: https://bugs.llvm.org/show_bug.cgi?id=24232
|
||||
//tsc synced across cpu intel: https://community.intel.com/t5/Software-Tuning-Performance/TSCs-per-logical-processor-Per-socket/m-p/1121318
|
||||
//lfence: https://hadibrais.wordpress.com/2018/05/14/the-significance-of-the-x86-lfence-instruction/
|
||||
|
|
@ -28,7 +35,7 @@ Intel(R) 64 and IA-32 Architectures Software Developer's Manual Volume 3 (3A, 3B
|
|||
#define WIN32_LEAN_AND_MEAN
|
||||
#define _WIN32_WINNT _WIN32_WINNT_WIN10 //0x0A00
|
||||
#define MAX_KEY_LENGTH 255
|
||||
#define MAX_VALUE_NAME 32768
|
||||
#define MAX_VALUE_NAME 32767
|
||||
#include <Windows.h>
|
||||
#include <winreg.h>
|
||||
#include <stringapiset.h>
|
||||
|
|
|
|||
233
src/tmrtsc.hpp
Normal file
233
src/tmrtsc.hpp
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
//TODO It's threadin' time
|
||||
|
||||
#ifdef _WIN64
|
||||
//TODO mirame esta
|
||||
#ifndef DEBUG
|
||||
#define DEBUG
|
||||
#endif
|
||||
#define UNICODE
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define _WIN32_WINNT _WIN32_WINNT_WIN10 //0x0A00
|
||||
#define MAX_KEY_LENGTH 255
|
||||
#define MAX_VALUE_NAME 32767
|
||||
#include <Windows.h>
|
||||
#include <winreg.h>
|
||||
#include <stringapiset.h>
|
||||
#include <synchapi.h>
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include "debug.h"
|
||||
|
||||
namespace tmr {
|
||||
|
||||
#ifdef _WIN64
|
||||
enum winReturnValues{
|
||||
CANT_OPEN_KEY = -1,
|
||||
CANT_RETRIEVE_KEY_INFO = -2,
|
||||
CANT_READ_DATA_FROM_VALUE = -3,
|
||||
CANT_RETRIEVE_FREQUENCY = -4
|
||||
};
|
||||
#endif
|
||||
enum ReturnValues {
|
||||
OPERATION_SUCCESSFUL = 0,
|
||||
INVARIANT_TSC_NOT_AVAILABLE = -1,
|
||||
UNSUPPORTED_CPU = -2,
|
||||
CANT_READ_FREQUENCY_FROM_SYSTEM = -3,
|
||||
ART_NOT_REPORTED = -4
|
||||
};
|
||||
|
||||
class TSCTimer {
|
||||
|
||||
private:
|
||||
static TSCTimer timer;
|
||||
static char* vendorName;
|
||||
static int64_t baseFreq = ART_NOT_REPORTED;
|
||||
|
||||
bool availableRDTSCP;
|
||||
int64_t art; //reserved
|
||||
|
||||
TSCtimer () {
|
||||
availableRDTSCP = (checkRDTSCP()) ? true : false;
|
||||
}
|
||||
|
||||
#ifdef _WIN64
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
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 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 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:
|
||||
static int getTimer(TSCTimer* timer = nullptr) {
|
||||
if (!checkInvariantTSC) return INVARIANT_TSC_NOT_SUPPORTED;
|
||||
|
||||
const char vendorNames[2][13] = {
|
||||
{"AuthenticAMD\0"},
|
||||
{"GenuineIntel\0"}
|
||||
};
|
||||
vendorName = readVendorName();
|
||||
|
||||
if (strcmp(vendorName, vendorNames[1]))
|
||||
baseFreq = intelRetrieveART();
|
||||
if (baseFreq == ART_NOT_REPORTED)
|
||||
baseFreq = getFreqFromSystem();
|
||||
if (baseFreq < OPERATION_SUCCESSFUL)
|
||||
return CANT_READ_FREQUENCY_FROM_SYSTEM;
|
||||
|
||||
timer = new TSCTimer();
|
||||
return OPERATION_SUCCESSFUL;
|
||||
}
|
||||
|
||||
uint64_t getTimeStamp(){
|
||||
if (availableRDTSCP)
|
||||
return readRDTSCP();
|
||||
else
|
||||
return readRDTSC();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue