加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

多线程 – x86保留EFLAGS位1 == 0:这怎么可能发生?

发布时间:2020-12-15 03:12:18 所属栏目:Java 来源:网络整理
导读:我正在使用Win32 API来停止/启动/检查/更改线程状态.一般工作得很好.有时它会失败,我正试图追查原因. 我有一个线程通过以下方式强制其他线程上的上下文切换: thread stopfetch processor state into windows context blockread thread registers from windo
我正在使用Win32 API来停止/启动/检查/更改线程状态.一般工作得很好.有时它会失败,我正试图追查原因.

我有一个线程通过以下方式强制其他线程上的上下文切换:

thread stop
fetch processor state into windows context block
read thread registers from windows context block to my own context block
write thread registers from another context block into windows context block
restart thread

这非常好用……但……很少,上下文切换似乎失败了.
(症状:我的多线程系统在执行奇怪的寄存器内容的奇怪地方时高高飘扬).

上下文控制通过以下方式完成:

if ((suspend_count=SuspendThread(WindowsThreadHandle))<0)
   { printf("TimeSlicer Suspend Thread failure");
      ...
   }
...
Context.ContextFlags = (CONTEXT_INTEGER | CONTEXT_CONTROL | CONTEXT_FLOATING_POINT);
if (!GetThreadContext(WindowsThreadHandle,&Context))
   {   printf("Context fetch failure");
       ...
   }

call ContextSwap(&Context); // does the context swap

if (ResumeThread(WindowsThreadHandle)<0)
   {  printf("Thread resume failure");
        ...
   }

没有任何打印语句被执行.我得出结论,Windows认为上下文操作都是可靠的.

哦,是的,我确实知道什么时候停止的线程没有计算[例如,在系统功能中]并且不会尝试停止/上下文切换它.我知道这一点,因为每个执行除计算之外的任何事情的线程都设置了一个特定于线程的“请勿触摸我”标志,而它正在进行非计算. (设备驱动程序程序员会将此视为“中断禁用”指令的等效项).

所以,我想知道上下文块的内容的可靠性.
我在上下文块中提取的各种寄存器值上添加了各种健全性测试;你实际上可以确定ESP是正常的(在TIB中定义的堆栈区域的范围内),PC在我期望的程序中或在系统调用中等等.这里没有惊喜.

我决定检查条件代码位(EFLAGS)是否被正确读出;如果这是错误的,它将导致切换任务在其状态为时采取“错误的分支”
恢复.因此,我添加了以下代码,以验证所声称的EFLAGS寄存器包含的内容根据英特尔参考手册(http://en.wikipedia.org/wiki/FLAGS_register)仅显示为EFLAGS.

mov        eax,Context.EFlags[ebx]  ; ebx points to Windows Context block
   mov        ecx,eax                ; check that we seem to have flag bits
   and        ecx,0FFFEF32Ah         ; where we expect constant flag bits to be
   cmp        ecx,000000202h         ; expected state of constant flag bits
   je         @f
   breakpoint                         ; trap if unexpected flag bit status
@@:

在我的Win 7 AMD Phenom II X6 1090T(hex core)上,
它会偶尔陷入断点,ECX = 0200h.在我的Win 7 Intel i7系统上失败.我会忽略这一点,
除了它暗示EFLAGS没有正确存储,我怀疑.

根据我对英特尔(以及AMD)参考手册的阅读,第1位保留,值始终为“1”.不是我在这里看到的.

显然,MS通过在线程停止上执行复杂的操作来填充上下文块.我希望他们准确地存储状态.该位未正确存储.
如果他们没有正确存储这个位,他们还存储了什么?

为什么这个位的值有时/应该为零的任何解释?

编辑:我的代码转储寄存器和堆栈捕获断点.
堆栈区域包含上下文块作为局部变量.
EAX和上下文块中EFLAGS的适当偏移量中的堆栈中的值都包含值0244h.所以上下文块中的值确实是错误的.

EDIT2:我将掩码和比较值更改为

and        ecx,0FFFEF328h         ; was FFEF32Ah where we expect flag bits to be
    cmp        ecx,000000200h

这似乎可靠运行,没有任何抱怨.显然,Win7没有正确执行eflags的第1位,看起来并不重要.

仍然对解释感兴趣,但显然这不是我偶尔的上下文切换崩溃的来源.

解决方法

微软有着悠久的历史,在没有真正使用过的地方徘徊一些. Raymond Chen给出了很多例子,例如使用非字节对齐的指针的低位.

在这种情况下,Windows可能需要将其某些线程上下文存储在现有的CONTEXT结构中,并决定在EFLAGS中使用其他未使用的位.无论如何你都无法做任何事情,当你调用SetThreadContext时,Windows会得到这一点.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读