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 个周期执行一次检查。否则大约每个核心时钟周期检查一次。
我有一个程序,它有一个主线程和一个第二线程。第二个线程修改一个全局变量,然后将在主线程中使用。但是不知何故,我在第二个线程中所做的更改并没有显示在主线程中。
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 个周期执行一次检查。否则大约每个核心时钟周期检查一次。