diff --git a/src/main.cpp b/src/main.cpp index 247db05..3044340 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,25 @@ -//https://bugs.llvm.org/show_bug.cgi?id=24232 +//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/ + +/* + +In the Intel(R) 64 and IA-32 Architectures Software Developer's Manual Volume 3B Sec 17.13.1 it says: + +"On processors with invariant TSC support, the OS may use the TSC for wall clock timer services." + +Does this formally imply that the TSC is always synchronized across all cores? + +By default the TSC is synchronized across all cores. However, the TSC value of a core could be changed by some software subsystem using the WRMSR instruction. Take a look at quotes below and I hope they finally answer your question: + +Intel(R) 64 and IA-32 Architectures Software Developer's Manual Volume 3 (3A, 3B & 3C): System Programming Guide Order Number: 325384-044US August 2012 Page 571 17.13 TIME-STAMP COUNTER ... Constant TSC behavior ensures that the duration of each clock tick is uniform and supports the use of the TSC as a wall clock timer even if the processor core changes frequency. ... Page 572 17.13.3 Time-Stamp Counter Adjustment ... Software can modify the value of the time-stamp counter (TSC) of a logical processor by using the WRMSR instruction to write to the IA32_TIME_STAMP_COUNTER MSR (address 10H). Because such a write applies only to that logical processor, software seeking to synchronize the TSC values of multiple logical processors must perform these writes on each logical processor. It may be difficult for software to do this in a way than ensures that all logical processors will have the same value for the TSC at a given point in time. The synchronization of TSC adjustment can be simplified by using the 64-bit IA32_TSC_ADJUST MSR ( address 3BH ). Like the IA32_TIME_STAMP_COUNTER MSR, the IA32_TSC_ADJUST MSR is maintained separately for each logical processor. ... + + */ + + + #ifndef DEBUG -#define DEBUG + #define DEBUG #endif #include @@ -11,26 +30,44 @@ bool checkInvariantTSC(){ uint64_t rdx; asm volatile (".intel_syntax noprefix\t\n" \ "mov eax, 0x80000007\t\n" \ - // 80000007H\t\n" + // 080000007h\t\n" "cpuid\t\n" : "=d" (rdx) ); bool iTSC = rdx & (1<<8); //"and edx, 10000000\n") return iTSC; } //static inline -uint64_t rdtscp()// uint32_t & aux ) -{ +uint64_t rdtsc() { uint64_t raxlo,rdxho; asm volatile ( ".intel_syntax noprefix\t\n" "cpuid\n" \ //"rdtscp\n" : "=a" (raxlo), "=d" (rdxho), "=c" (aux) : : ); - "rdtsc\n" : "=a" (raxlo), "=d" (rdxho)); + "rdtscp\n" : "=a" (raxlo), "=d" (rdxho)); return (rdxho << 32) + raxlo; //| } -int main(int argc, char** argv){ - log_debugcpp(checkInvariantTSC()); - uint64_t test = rdtscp(); - log_debugcpp(test); - return 0; +//static inline +uint64_t rdtscp(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) ); + //"rdtscp\n" : "=a" (raxlo), "=d" (rdxho)); + *logicore = rcx; + return (rdxho << 32) + raxlo; //| +} + +int main(int argc, char** argv){ + bool iTSC = checkInvariantTSC(); + log_debugcpp(iTSC); + if (iTSC) { + uint64_t test = rdtsc(); + log_debugcpp(test); + uint64_t ayo = 0; + uint64_t* logicore = &ayo;//nullptr; + uint64_t testp = rdtscp(logicore); + log_debugcpp(testp << " + " << &logicore); + return 0; + } + return -1; }