static void *
thread_start(void *arg)
{
printf("Subthread starting infinite loop\n");
for (;;)
continue;
}
static void
pclock(char *msg, clockid_t cid)
{
struct timespec ts;
printf("%s", msg);
if (clock_gettime(cid, &ts) == -1)
handle_error("clock_gettime");
printf("%4ld.%03ld\n", ts.tv_sec, ts.tv_nsec / 1000000);
}
int
main(int argc, char *argv[])
{
pthread_t thread;
clockid_t cid;
int j, s;
s = pthread_create(&thread, NULL, thread_start, NULL);
if (s != 0)
handle_error_en(s, "pthread_create");
printf("Main thread sleeping\n");
sleep(1);
printf("Main thread consuming some CPU time...\n");
for (j = 0; j < 2000000; j++)
getppid();
pclock("Process total CPU time: ", CLOCK_PROCESS_CPUTIME_ID);
s = pthread_getcpuclockid(pthread_self(), &cid);
if (s != 0)
handle_error_en(s, "pthread_getcpuclockid");
pclock("Main thread CPU time: ", cid);
/* The preceding 4 lines of code could have been replaced by:
pclock("Main thread CPU time: ", CLOCK_THREAD_CPUTIME_ID); */
s = pthread_getcpuclockid(thread, &cid);
if (s != 0)
handle_error_en(s, "pthread_getcpuclockid");
pclock("Subthread CPU time: 1 ", cid);
exit(EXIT_SUCCESS); /* Terminates both threads */
}
pthread_getcpuclockid (threadid, clockid)
pthread_t threadid;
clockid_t *clockid;
{
struct pthread *pd = (struct pthread *) threadid;
/* Make sure the descriptor is valid. */
if (INVALID_TD_P (pd))
/* Not a valid thread handle. */
return ESRCH;
#ifdef CLOCK_THREAD_CPUTIME_ID
/* We need to store the thread ID in the CLOCKID variable together
with a number identifying the clock. We reserve the low 3 bits
for the clock ID and the rest for the thread ID. This is
problematic if the thread ID is too large. But 29 bits should be
fine.
将gettid() 放在了 CLOCKID变量里面
If some day more clock IDs are needed the ID part can be
enlarged. The IDs are entirely internal. */
if (pd->tid >= 1 << (8 * sizeof (*clockid) - CLOCK_IDFIELD_SIZE))
return ERANGE;
/* Store the number. 用后面3位来保存 C_T_C_I ,如果gettid()太大就失效了所以上面做了判断 */
*clockid = CLOCK_THREAD_CPUTIME_ID | (pd->tid << CLOCK_IDFIELD_SIZE);
return 0;
#else
/* We don't have a timer for that. */
return ENOENT;
#endif
}
然后看一下 clock_gettime()的 CLOCK_PROCESS_CPUTIME_ID 部分的处理
int
clock_gettime (clockid_t clock_id, struct timespec *tp)
{
/*检测上面的设置位*/
//...
#if HP_TIMING_AVAIL
if ((clock_id & ((1 << CLOCK_IDFIELD_SIZE) - 1))
== CLOCK_THREAD_CPUTIME_ID)
retval = hp_timing_gettime (clock_id, tp);
else
#endif
//...
return retval;
}
这里先省掉了一些 无关代码。
在有 timestamp register 的情况下 测试 HP_TIMING_AVAIL 就是ture,
所以我们来看看
retval = hp_timing_gettime (clock_id, tp);
这块之前的glibc 还没有独立出来 ,其实一样 关键在于
__pthread_clock_gettime();
先把hp_timing_gettime 放在一边,来看看里面的关键函数
int
__pthread_clock_gettime (clockid_t clock_id, hp_timing_t freq,
struct timespec *tp)
{
hp_timing_t tsc;
/* Get the current counter. */
HP_TIMING_NOW (tsc);
/* This is the ID of the thread we are looking for. */
pid_t tid = ((unsigned int) clock_id) >> CLOCK_IDFIELD_SIZE;
/* Compute the offset since the start time of the process.
THREAD_GETMEM 里面存放的是线程启动时候记录下的 counter
所有 */
if (tid == 0 || tid == THREAD_GETMEM (THREAD_SELF, tid))
/* 如果调用的不是当前thread, 那就要通过__find_thread_by_id (gettid())来获得 对应的pthread结构,很可惜这个宏被 _attribute__ ((visibility ("hidden"))) 放在了hiddern区 所以只能内部用,外部动态链接没办法使用 。。主要因为涉及了内部太多结构 */
tsc -= THREAD_GETMEM (THREAD_SELF, cpuclock_offset);
else
{
/* This is more complicated. We have to locate the thread based
on the ID. This means walking the list of existing
threads. */
struct pthread *thread = __find_thread_by_id (tid);
//...
/* There is a race here. The thread might terminate and the stack
become unusable. But this is the user's problem. */
tsc -= thread->cpuclock_offset;
}
/* Compute the seconds. */
tp->tv_sec = tsc / freq;
/* And the nanoseconds. This computation should be stable until
we get machines with about 16GHz frequency. */
tp->tv_nsec = ((tsc % freq) * 1000000000ull) / freq;
return 0;
}
对线程结构特定成员的赋值和取值操作 都要通过
THREAD_SETMEM 和THREAD_GETMEM 来操作
可以简单看一眼 THREAD_SETMEM
# define THREAD_SETMEM(descr, member, value)
//...
else if (sizeof (descr->member) == 4) \
asm volatile ("movl %0,%%gs:%P1" : \
: "ir" (value), \
"i" (offsetof (struct pthread, member)));
先判断成员长度 ,然后 把立即数(ir) value 放在gs段偏移为 offsetof (struct pthread, member))的位置, 也就完成了复制
补充一下: 为什么是gs段 :
其实这是gs段寄存器 每一个 pthread 都有一下的私有数据,一个是pthread_t类似于PCB ,一个是自身的堆栈可以用pthread_setstack 来设置,还有一个是TLS线程本地数据了 ,这些东西放在一个mmap区域中 ,用各自的gs寄存器地址来指向
分享到:
相关推荐
INTEL X86 rdtsc指令编程指南 ..........................................................
自己做的小程序,检测CPU主频,内嵌汇编代码,rdtsc指令的一个小应用,有详细注释
采用汇编和C两种语言,分别求取CPU当前的速度(RDTSC)
利用 rdtsc 汇编指令可以得到 CPU 内部定时器的值, 每经过一个 CPU 周期, 这个定时器就加一。 如果在一段时间内数得 CPU 的周期数, CPU工作频率 = 周期数 / 时间 为了不让其他进程和线程打扰, 必需要设置最高的...
KVM RDTSC计时器稳定器该项目旨在稳定并最小化在KVM虚拟机中运行的程序中2个RDTSC调用和vmexit(特别是cpuid)的感知时间差。 您可能需要配置constant_tsc_offset值,默认情况下为1000。 在AMD Ryzen平台上,〜1600...
陷阱RDTSC TrapRDTSC 在 Mac OS X/x86-64 上捕获并模拟rdtsc (读取时间戳计数器)和rdtscp指令。 这在使用 rdtsc 检测外部仪器的逆向工程软件时主要有用。 除了在使用, rdtsc Mac OS X 的 iCloud/Spotlight/...
RDTSC测试程序
rdtsc 我的C ++包装器,辅助函数,摘要和实验
概要 使用推测执行的虚拟机监控程序检测 内容 该存储库包含解释基于Meltdown的新虚拟化测试攻击的论文。 它们并不以任何方式广泛,仅提供有限的解释,而不会深入细节。 代码样本 该存储库提供Windows,Linux和macOS...
这款工具帮助软件直接存取RDTSC指令(读取时间标记计数器),为了能够校正不同核心之间的Time Stamp Counter(时间戳计数器)。它能够非常有效的使双核心并行运行,在双核心或即将到来的多核心中减少不一致的性能...
In ini added “DELTARDTSC which will regulate the spread RDTSC. What’s New - 1.04 Fixed bsod while loading drivers. What’s New - 1.03 Fixed bug with windows. What’s New - 1.01 Fixed bug in ...
《深入x86的内存寻址》I/O 外设硬件开发举例一.本包是原文《深入x86的内存寻址》I/O 寻址的充部分,提供PC...另外对芯片工作频率的探测也作了一定的深入,使用了CPUID、RDTSC 等指令来获取CPU硬件信息以适合程序需求。
4. RDTSC/ GetTickCount时间敏感程序段 6 5. StartupInfo结构 7 6. BeingDebugged 8 7. PEB.NtGlobalFlag , Heap.HeapFlags, Heap.ForceFlags 9 8. DebugPort: CheckRemoteDebuggerPresent()/...
4. RDTSC/ GetTickCount时间敏感程序段 7 5. StartupInfo结构 7 6. BeingDebugged 8 7. PEB.NtGlobalFlag , Heap.HeapFlags, Heap.ForceFlags 10 8. DebugPort: CheckRemoteDebuggerPresent()/...
4. RDTSC/ GetTickCount时间敏感程序段 7 5. StartupInfo结构 7 6. BeingDebugged 8 7. PEB.NtGlobalFlag , Heap.HeapFlags, Heap.ForceFlags 10 8. DebugPort: CheckRemoteDebuggerPresent()/...
4. RDTSC/ GetTickCount时间敏感程序段 7 5. StartupInfo结构 7 6. BeingDebugged 8 7. PEB.NtGlobalFlag , Heap.HeapFlags, Heap.ForceFlags 10 8. DebugPort: CheckRemoteDebuggerPresent()/...
4. RDTSC/ GetTickCount时间敏感程序段 7 5. StartupInfo结构 7 6. BeingDebugged 8 7. PEB.NtGlobalFlag , Heap.HeapFlags, Heap.ForceFlags 10 8. DebugPort: CheckRemoteDebuggerPresent()/...
4. RDTSC/ GetTickCount时间敏感程序段 7 5. StartupInfo结构 7 6. BeingDebugged 8 7. PEB.NtGlobalFlag , Heap.HeapFlags, Heap.ForceFlags 10 8. DebugPort: CheckRemoteDebuggerPresent()/...
Linux驱动程序开发第三版-英文
---[ PhantOm plugin 1.54 ]------------------------------...[+] RDTSC. [+] NtYieldExecution. [+] NtQueryObject. [+] NtQuerySystemInformation. [+] Windows hide. [+] GetProcessTimes. [+] NtSetContextThread.