Nasm - 在不同线程中更改变量

Nasm - Change variable in different threads

我有一个程序,它有一个主线程和一个第二线程。第二个线程修改一个全局变量,然后将在主线程中使用。但是不知何故,我在第二个线程中所做的更改并没有显示在主线程中。

section .bss USE32
  global var
  var resd 1

section .text USE32
  ..start:
  push 0
  push 0
  push 0
  push .second
  push 0
  push 0
  call [CreateThread]
  mov eax, 1
  cmp [var], eax ; --> the content of var and '1' are not the same. Which is confusing since I set the content of var to '1' in the second thread
  ;the other code here is not important

.second:
  mov eax, 1
  mov [var], eax
  ret

(这是我在循环中创建线程的真实程序的简化;。)

你没有join新线程(等待它退出);当 CreateThread returns 到主线程时,没有理由假设它已经完成(甚至完全开始)。

如果你想对线程启动开销 + 内核间延迟进行基准测试,你可以旋转等待直到你在 [var] 中看到一个非零值,然后计算需要多少次迭代。

   ...
   call  [CreateThread]
   mov   edi, 1
   cmp   [var], edi
   je   .zero_latency    ; if var already changed

   rdtsc                 ; could put an lfence before and/or after this to serialize execution
   mov  ecx, eax         ; save low half of EDX:EAX cycle count; should be short enough that the interval fits in 32 bits
   xor  esi, esi
  .spin:
   inc  esi            ; ++spin_count
   pause               ; optional, but avoids memory-order mis-speculation when var changes
   cmp  [var], edi
   jne .spin

   rdtsc
   sub  eax, ecx        ; reference cycles since CreateThread returned
   ...
 .zero_latency:         ; jump here if the value already changed before the first iteration

请注意 rdtsc 参考 周期内测量,而不是核心时钟周期,因此涡轮很重要。如果间隔小于 2^32(例如,在参考频率为 4.2 GHz 的 CPU 上大约 1 秒,比我们预期的长得多,则只执行 64 位减法的低 32 位在这里)。

esi 是旋转计数。在循环中使用 pause,您将在 Skylake 及更高版本上每 100 个周期执行一次检查,或者在更早的 Intel 上每 5 个周期执行一次检查。否则大约每个核心时钟周期检查一次。