; Listing5-4.asm ; ; A program that demonstrates a deadlock. option casemap:none option prologue:none include aoalib.inc ;AoA library + constants includelib aoalib.lib ;Link in aoalib library include c:\masm32\include64\win64.inc include c:\masm32\include64\kernel32.inc includelib c:\masm32\lib64\kernel32.lib .const ; Program title: align word ttlStr byte "Listing 5-4", 0 .data align qword Resource1 CRITICAL_SECTION {} Resource2 CRITICAL_SECTION {} hEvent1 qword ? hEvent2 qword ? .code saveRBX textequ <[rbp-8]> ; Here is Thread1: Thread1 proc public push rbp mov rbp, rsp sub rsp, 64 mov saveRBX, rbx mov ebx, 100 ;Loop 100 times rptLoop: lea rcx, Resource1 call EnterCriticalSection mov ecx, 100 call Sleep ifndef do2 lea rcx, Resource2 call EnterCriticalSection endif mov edx, ebx call print byte "Thread1: %d", nl, 0 lea rcx, Resource1 call LeaveCriticalSection ifndef do2 lea rcx, Resource2 call LeaveCriticalSection endif dec ebx jnz rptLoop mov rcx, hEvent1 ;Get event handle call SetEvent ; Terminate the thread: xor rax, rax ;Return result mov rbx, saveRBX leave ret Thread1 endp ; Here is Thread2. Note that the order of the EnterCriticalSection ; calls have changed from Thread1: Thread2 proc public push rbp mov rbp, rsp sub rsp, 64 mov saveRBX, rbx mov ebx, 100 ;Loop 100 times rptLoop: ifndef do2 lea rcx, Resource2 call EnterCriticalSection endif mov ecx, 100 call Sleep lea rcx, Resource1 call EnterCriticalSection mov edx, ebx ;Get thread event call print byte "Thread2: %d", nl, 0 ifndef do2 lea rcx, Resource2 call LeaveCriticalSection endif lea rcx, Resource1 call LeaveCriticalSection dec ebx jnz rptLoop mov rcx, hEvent2 ;Get event handle call SetEvent ; Terminate the thread: xor rax, rax ;Return result mov rbx, saveRBX leave ret Thread2 endp ; Here is the main assembly language function. public asmMain asmMain proc push rbp mov rbp, rsp sub rsp, 64 mov [rbp-8], rbx ; Initialize all the critical sections and events: lea rcx, Resource1 call InitializeCriticalSection ifndef do2 lea rcx, Resource2 call InitializeCriticalSection endif xor ecx, ecx ;No security attributes xor edx, edx ;Auto-reset mode xor r8d, r8d ;Initial: unsignaled xor r9, r9 ;No event ID; local call CreateEvent mov hEvent1, rax xor ecx, ecx ;No security attributes xor edx, edx ;Auto-reset mode xor r8d, r8d ;Initial: unsignaled xor r9, r9 ;No event ID; local call CreateEvent mov hEvent2, rax ; Start the threads running: call print byte "Creating Thread1", nl, 0 xor rcx, rcx ;No security attributes xor rdx, rdx ;Default stack size lea r8, Thread1 ;Address of thread code mov r9, hEvent1 ;Thread parameter xor rax, rax ;Default thread flags mov [rsp+32], rax ;Must pass on stack. mov [rsp+40], rax ;Don't save threadID. call CreateThread call print byte "Creating Thread2", nl, 0 xor rcx, rcx ;No security attributes xor rdx, rdx ;Default stack size lea r8, Thread2 ;Address of thread code mov r9, hEvent2 ;Thread parameter xor rax, rax ;Default thread flags mov [rsp+32], rax ;Must pass on stack. mov [rsp+40], rax ;Don't save threadID. call CreateThread ; Wait until the two threads complete: mov ecx, 2 lea rdx, hEvent1 ;Array of 2 dwords (hEvent1, hEvent2) mov r8d, 1 ;Wait for all signals mov r9d, INFINITE call WaitForMultipleObjects ; Clean up everything: lea rcx, Resource1 call DeleteCriticalSection ifndef do2 lea rcx, Resource2 call DeleteCriticalSection endif mov rcx, hEvent1 call CloseHandle ; Terminate the program. mov rbx, [rbp-8] leave ret ;Returns to caller asmMain endp end