3-2
/*
* TaskQueS.c
*
* Sample code for "Multithreading Applications in Win32"
* This is from Chapter 3, Listing 3-2
*
* Call ThreadFunc NUM_TASKS times, using
* no more than THREAD_POOL_SIZE threads.
* This version uses WaitForSingleObject,
* which gives a very suboptimal solution.
*
* Build command: cl /MD TaskQueS.c
*/
#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include "MtVerify.h"
DWORD WINAPI ThreadFunc(LPVOID);
#define THREAD_POOL_SIZE 3
#define MAX_THREAD_INDEX THREAD_POOL_SIZE-1
#define NUM_TASKS 6
int main()
{
HANDLE hThrds[THREAD_POOL_SIZE];
int slot = 0;
DWORD threadId;
int i;
DWORD exitCode;
/* i= 1 2 3 4 5 6 7 8 9
* Start Thread X X X X X X
* Wait on thread X X X X X X
*/
for (i=1; i<=NUM_TASKS; i++)
{
if (i > THREAD_POOL_SIZE)
{
WaitForSingleObject(hThrds[slot], INFINITE);
MTVERIFY( GetExitCodeThread(hThrds[slot], &exitCode) );
printf("Slot %d terminated\n", exitCode );
MTVERIFY( CloseHandle(hThrds[slot]) );
}
MTVERIFY( hThrds[slot] = CreateThread(NULL,
0,
ThreadFunc,
(LPVOID)slot,
0,
&threadId ) );
printf("Launched thread #%d (slot %d)\n", i, slot);
if (++slot > MAX_THREAD_INDEX)
slot = 0;
}
for (slot=0; slot<THREAD_POOL_SIZE; slot++)
{
WaitForSingleObject(hThrds[slot], INFINITE);
MTVERIFY( CloseHandle(hThrds[slot]) );
}
printf("All slots terminated\n");
return EXIT_SUCCESS;
}
/*
* This function just calls Sleep for
* a random amount of time, thereby
* simulating some tasks that takes time.
*
* The param "n" is the index into
* the handle array, kept for informational
* purposes.
*/
DWORD WINAPI ThreadFunc(LPVOID n)
{
srand( GetTickCount() );
Sleep((rand()%8)*500+500);
printf("Slot %d idle\n", n);
return ((DWORD)n);
}
od
00401000 /$ 81EC 1C010000 sub esp, 11C
00401006 |. 53 push ebx
00401007 |. 55 push ebp
00401008 |. 8B2D 20204000 mov ebp, dword ptr [<&KERNEL32.WaitF>; kernel32.WaitForSingleObject
0040100E |. 56 push esi
0040100F |. 57 push edi
00401010 |. 33F6 xor esi, esi
00401012 |. BB 01000000 mov ebx, 1
00401017 |> 83FB 03 /cmp ebx, 3
0040101A |. 7E 3F |jle short 0040105B
0040101C |. 8B7CB4 20 |mov edi, dword ptr [esp+esi*4+20]
00401020 |. 6A FF |push -1
00401022 |. 57 |push edi
00401023 |. FFD5 |call ebp
00401025 |. 8D4424 18 |lea eax, dword ptr [esp+18]
00401029 |. 50 |push eax ; /pExitCode
0040102A |. 57 |push edi ; |hThread
0040102B |. FF15 1C204000 |call dword ptr [<&KERNEL32.GetExitCo>; \GetExitCodeThread
00401031 |. 85C0 |test eax, eax
00401033 |. 0F84 A7000000 |je 004010E0
00401039 |. 8B4C24 18 |mov ecx, dword ptr [esp+18]
0040103D |. 51 |push ecx ; /<%d>
0040103E |. 68 30314000 |push 00403130 ; |format = "Slot %d terminated",LF,""
00401043 |. FF15 34204000 |call dword ptr [<&MSVCRTD.printf>] ; \printf
00401049 |. 83C4 08 |add esp, 8
0040104C |. 57 |push edi ; /hObject
0040104D |. FF15 18204000 |call dword ptr [<&KERNEL32.CloseHand>; \CloseHandle
00401053 |. 85C0 |test eax, eax
00401055 |. 0F84 05010000 |je 00401160
0040105B |> 8D5424 1C |lea edx, dword ptr [esp+1C]
0040105F |. 52 |push edx ; /pThreadId
00401060 |. 6A 00 |push 0 ; |CreationFlags = 0
00401062 |. 56 |push esi ; |pThreadParm
00401063 |. 68 E0124000 |push 004012E0 ; |ThreadFunction = TaskQueS.004012E0
00401068 |. 6A 00 |push 0 ; |StackSize = 0
0040106A |. 6A 00 |push 0 ; |pSecurity = NULL
0040106C |. FF15 14204000 |call dword ptr [<&KERNEL32.CreateThr>; \CreateThread
00401072 |. 85C0 |test eax, eax
00401074 |. 8944B4 20 |mov dword ptr [esp+esi*4+20], eax
00401078 |. 0F84 62010000 |je 004011E0
0040107E |. 56 |push esi ; /<%d>
0040107F |. 53 |push ebx ; |<%d>
00401080 |. 68 10314000 |push 00403110 ; |format = "Launched thread #%d (slot %d)",LF,""
00401085 |. FF15 34204000 |call dword ptr [<&MSVCRTD.printf>] ; \printf
0040108B |. 83C4 0C |add esp, 0C
0040108E |. 46 |inc esi
0040108F |. 83FE 02 |cmp esi, 2
00401092 |. 7E 02 |jle short 00401096
00401094 |. 33F6 |xor esi, esi
00401096 |> 43 |inc ebx
00401097 |. 83FB 06 |cmp ebx, 6
0040109A |.^ 0F8E 77FFFFFF \jle 00401017
004010A0 |. 33DB xor ebx, ebx
004010A2 |. 8D7C24 20 lea edi, dword ptr [esp+20]
004010A6 |> 8B37 /mov esi, dword ptr [edi]
004010A8 |. 6A FF |push -1
004010AA |. 56 |push esi
004010AB |. FFD5 |call ebp
004010AD |. 56 |push esi ; /hObject
004010AE |. FF15 18204000 |call dword ptr [<&KERNEL32.CloseHand>; \CloseHandle
004010B4 |. 85C0 |test eax, eax
004010B6 |. 0F84 A4010000 |je 00401260
004010BC |. 43 |inc ebx
004010BD |. 83C7 04 |add edi, 4
004010C0 |. 83FB 03 |cmp ebx, 3
004010C3 |.^ 7C E1 \jl short 004010A6
004010C5 |. 68 F8304000 push 004030F8 ; /format = "All slots terminated",LF,""
004010CA |. FF15 34204000 call dword ptr [<&MSVCRTD.printf>] ; \printf
004010D0 |. 83C4 04 add esp, 4
004010D3 |. 33C0 xor eax, eax
004010D5 |. 5F pop edi
004010D6 |. 5E pop esi
004010D7 |. 5D pop ebp
004010D8 |. 5B pop ebx
004010D9 |. 81C4 1C010000 add esp, 11C
004010DF |. C3 retn
thread
004012E0 |. 56 push esi
004012E1 |. FF15 24204000 call dword ptr [<&KERNEL32.GetTickCou>; [GetTickCount
004012E7 |. 50 push eax ; /seed
004012E8 |. FF15 3C204000 call dword ptr [<&MSVCRTD.srand>] ; \srand
004012EE |. 83C4 04 add esp, 4
004012F1 |. FF15 38204000 call dword ptr [<&MSVCRTD.rand>] ; [rand
004012F7 |. 25 07000080 and eax, 80000007
004012FC |. 79 05 jns short 00401303
004012FE |. 48 dec eax
004012FF |. 83C8 F8 or eax, FFFFFFF8
00401302 |. 40 inc eax
00401303 |> 40 inc eax
00401304 |. 8D0480 lea eax, dword ptr [eax+eax*4]
00401307 |. 8D0480 lea eax, dword ptr [eax+eax*4]
0040130A |. 8D0480 lea eax, dword ptr [eax+eax*4]
0040130D |. C1E0 02 shl eax, 2
00401310 |. 50 push eax ; /Timeout
00401311 |. FF15 00204000 call dword ptr [<&KERNEL32.Sleep>] ; \Sleep
00401317 |. 8B7424 08 mov esi, dword ptr [esp+8]
0040131B |. 56 push esi ; /<%d>
0040131C |. 68 44314000 push 00403144 ; |format = "Slot %d idle",LF,""
00401321 |. FF15 34204000 call dword ptr [<&MSVCRTD.printf>] ; \printf
00401327 |. 83C4 08 add esp, 8
0040132A |. 8BC6 mov eax, esi
0040132C |. 5E pop esi
0040132D \. C2 0400 retn 4
ida