The following is a test piece for starting and closing threads looking for the fastest way to perform this task while not locking the machine up. I have tried a number of techniques for getting the signalled state of the 4 threads in the test and so far the API WaitForMultipleObjects() gives both end the bests, speed and processor usage. I have left the commented out runtime code in the thread proc there as this allowed a loop test in the caller running the 4 threads 4096 times for a total of 16384 threads started and closed.
I am going to have to play with the API functions that wait for a signalled state to see if there are any suitable to stop a thread without wasting large amounts of processor time so that I can try using one in the taile end of a thread so it can loop back and be re-used but among the things that I need to quantify is whether its faster just to start new threads or re-use existing ones.
This is the code.
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
include \masm32\include\masm32rt.inc
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
comment * -----------------------------------------------------
Build this template with
"CONSOLE ASSEMBLE AND LINK"
----------------------------------------------------- *
start_thread PROTO :DWORD
work_thread PROTO :DWORD
THREAD_ARGS STRUCT
flag dd ? ; thread start flag
arg1 dd ?
arg2 dd ?
arg3 dd ?
arg4 dd ?
arg5 dd ?
arg6 dd ?
arg7 dd ?
arg8 dd ?
THREAD_ARGS ENDS
.code
start:
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
call main
inkey
exit
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
main proc
LOCAL thst :THREAD_ARGS
LOCAL th_arr[4] :DWORD ; thread handle array, 4 x DWORD = 16 bytes
LOCAL cntr :DWORD
; -------------------------------
; load the THREAD_ARGS structure
; -------------------------------
mov DWORD PTR thst.arg1, 1
mov DWORD PTR thst.arg2, 2
mov DWORD PTR thst.arg3, 3
mov DWORD PTR thst.arg4, 4
mov cntr, 4096
@@:
; -----------------------------------------------
; start the four threads writing handles to array
; -----------------------------------------------
m2m th_arr[0], rv(start_thread,ADDR thst)
m2m th_arr[4], rv(start_thread,ADDR thst)
m2m th_arr[8], rv(start_thread,ADDR thst)
m2m th_arr[12], rv(start_thread,ADDR thst)
invoke WaitForMultipleObjects,4,ADDR th_arr,TRUE,5000 ; 5 seconds time out
; ------------------------
; close the thread handles
; ------------------------
invoke CloseHandle,th_arr[0]
invoke CloseHandle,th_arr[4]
invoke CloseHandle,th_arr[8]
invoke CloseHandle,th_arr[12]
sub cntr, 1
jnz @B
ret
main endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
start_thread proc pstruct:DWORD
LOCAL tID :DWORD
LOCAL hThread :DWORD
push esi
mov esi, pstruct
mov (THREAD_ARGS PTR [esi]).flag, 1 ; set the flag
mov hThread, rv(CreateThread,NULL,NULL,ADDR work_thread,pstruct,NULL,ADDR tID)
; ---------------------------------------------
; block new threads from starting until args
; are saved in the current thread being created
; ---------------------------------------------
spinlock:
cmp (THREAD_ARGS PTR [esi]).flag, 0 ; loop until created thread clears the flag
jne spinlock
; ---------------------------------------------
mov eax, hThread
pop esi
ret
start_thread endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
work_thread proc pstruct:DWORD
LOCAL args[4]:DWORD
; --------------------------------------------------------------
; load the args to local array before the caller flag is cleared
; --------------------------------------------------------------
mov eax, pstruct
m2m args[0], (THREAD_ARGS PTR [eax]).arg1
m2m args[4], (THREAD_ARGS PTR [eax]).arg2
m2m args[8], (THREAD_ARGS PTR [eax]).arg3
m2m args[12], (THREAD_ARGS PTR [eax]).arg4
; ------------------------------------
; release the thread starter procedure
; ------------------------------------
mov (THREAD_ARGS PTR [eax]).flag, 0 ; clear the flag
; ********************************************************************
; ************* Thread specific runtime code goes here ***************
; ********************************************************************
; invoke SleepEx,1,0 ; <<<< uncomment this to make the task really slow.
; print str$(args[0])
; print str$(args[4])
; print str$(args[8])
; print str$(args[12])
; print ":"
; ********************************************************************
; ********************************************************************
; ********************************************************************
; -------------------------------------
; set the thread exit code if necessary
; -------------------------------------
invoke ExitThread,0
ret
work_thread endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
end start