Я пишу код в NASM (64 бит) в Windows для запуска четырех одновременных потоков (каждый из которых назначен отдельному ядру) на четырехъядерном компьютере с Windows x86-64.Ниже приведен мой код реализации потока.Каждый поток вызывает одну и ту же программу.
Код показан ниже в точной последовательности, в которой он указан в исходном файле (без раздела .data и некоторого сокращенного кода).Каждый поток (ядро) выполняет Test_Function в большом массиве.Первое ядро начинается с нуля элемента данных, второе ядро начинается с 1, третье ядро начинается с 2, четвертое ядро начинается с 3, а каждое ядро увеличивается на четыре (например, 0, 4, 8, 12).По окончании Test_Function завершает работу в label_899.Они записывают свои результаты в соответствующие местоположения в общем массиве, созданном с помощью malloc.
Мой вопрос: куда мне идти после того, как все темы закончены на label_899?Затем потоки возвращаются к последней строке ThreadStart (после jl label_0), где выполняется очистка?Test_Function завершает работу с ret, поэтому я предполагаю, что он возвращает управление в раздел создания экземпляра потока (ThreadStart).
К сожалению, вся информация, которую я прочитал об этом, фокусируется на создании единого потока.Некоторые ресурсы говорят о синхронизации потоков во время работы, но я не нашел ничего общего с тем, что происходит после завершения всех потоков.
Спасибо за любую помощь.Я бы опубликовал полный пример, но я пока не знаю, как его завершить, и это мой вопрос.
ThreadStart:
mov rbp,rsp ; preserve caller's stack frame
mov rdi,ThreadInfo ; two element array
sub rsp,32 ; Shadow space
label_0:
mov rax,StartByte
mov [rdi],rax ; 0, 8, 16, or 24
mov rax,[JumpCount]
mov [rdi+8],rax ; number of cores (4 in this example)
push 0 ; Creation flags, start immediately (may want to delay until all created)
push 0 ; ThreadID
mov rcx,0 ; lpThreadAttributes (Security Attributes)
mov rdx,0 ; dwStackSize
mov r8,Test_Function ; lpStartAddress (function pointer)
mov r9,rdi ; lpParameter
call CreateThread
mov rax,8
add [StartByte],rax
mov rax,[TreadCount]
add rax,1
mov [TreadCount],rax
cmp rax,4
jl label_0
[ Code to do cleanup if needed after the four threads finish ]
mov rsp,rbp
jmp final_out
;______
Test_Function:
xor rcx,rcx
mov [loop_counter_401],rcx
label_401:
lea rdi,[rel numbers_ptr]
mov rbp,qword [rdi] ; Pointer
mov rcx,[loop_counter_401]
mov rax,[numbers_length]
cmp rcx,rax
jge label_899
movsd xmm0,qword[rbp+rcx]
movsd [num_float],xmm0
add rcx,32 ;8 -- add 32 for four loops, not 8
mov [loop_counter_401],rcx
[ MORE CODE]
jmp label_401
label_899:
ret
;______
final_out:
mov rdi,Return_Pointer_Array
mov rax,r15
mov [rdi+0],rax
mov rax,r14
mov [rdi+8],rax
mov rax,rdi
ret
Обновление 030119
Ниже приведен код, который создает потоки, как сейчас.Ранее я думал, что это не удалось в CreateThread, но это не так.Теперь происходит сбой из-за проблемы с кодом, который я вызываю, и я сейчас отлаживаю его.Я отправлю назад с моими результатами.Ошибка может быть в том, как я написал код для WaitForMultipleObjects.
Показан код создания потока, а не код, вызываемый потоками.
mov rdi,ThreadInfo
mov rax,StartByte
mov [rdi+8],rax ; 0, 8, 16, or 24
; _____
; Create Threads
mov rcx,0 ; lpThreadAttributes (Security Attributes)
mov rdx,0 ; dwStackSize
mov r8,Test_Function ; lpStartAddress (function pointer)
mov rax,rdi
mov r9,rax ; lpParameter (array of data passed to each core)
mov rax,0
mov [rsp+40],rax ; use default creation flags
mov rax,[ThreadCount]
mov [rsp+32],rax ; ThreadID
call CreateThread
; Move the handle into ThreadHandles array (returned in rax)
mov rdi,ThreadHandles
mov rcx,[StartByte]
mov [rdi+rcx],rax
mov rax,8
add [StartByte],rax
mov rax,[ThreadCount]
add rax,1
mov [ThreadCount],rax
cmp rax,4
jl label_0
; _____
; Wait
mov rcx,rax ; number of handles
mov rdx,ThreadHandles ; pointer to handles array
mov r8,1 ; wait for all threads to complete
mov r9,1000 ; milliseconds to wait
call WaitForMultipleObjects
; _____
;[ Code to do cleanup if needed after the four threads finish ]
mov rsp,rbp
jmp label_900