win32 programming lesson 11: user-mode thread sync (aka: how to crash your machine without really...
TRANSCRIPT
![Page 1: Win32 Programming Lesson 11: User-mode Thread Sync (aka: How to crash your machine without really trying…)](https://reader034.vdocuments.site/reader034/viewer/2022051401/5697bff71a28abf838cbe9cc/html5/thumbnails/1.jpg)
Win32 ProgrammingLesson 11: User-mode Thread Sync(aka: How to crash your machine without really trying…)
![Page 2: Win32 Programming Lesson 11: User-mode Thread Sync (aka: How to crash your machine without really trying…)](https://reader034.vdocuments.site/reader034/viewer/2022051401/5697bff71a28abf838cbe9cc/html5/thumbnails/2.jpg)
Where are we? We’ve got thread basics worked out… even
priorities But right now, all the examples are sort-of
contrived… Need to understand how to communicate
from thread to thread
![Page 3: Win32 Programming Lesson 11: User-mode Thread Sync (aka: How to crash your machine without really trying…)](https://reader034.vdocuments.site/reader034/viewer/2022051401/5697bff71a28abf838cbe9cc/html5/thumbnails/3.jpg)
Thread Problems When we share data between threads, bad
things can happen Look at the following example code… What’s wrong? Can replace using “interlocked” functions
![Page 4: Win32 Programming Lesson 11: User-mode Thread Sync (aka: How to crash your machine without really trying…)](https://reader034.vdocuments.site/reader034/viewer/2022051401/5697bff71a28abf838cbe9cc/html5/thumbnails/4.jpg)
InterlockedExchangeAdd LONG InterlockedExchangeAdd (
PLONG plAddend,LONG lIncrement
); What could be simpler – promises Atomic
access to *plAddend
![Page 5: Win32 Programming Lesson 11: User-mode Thread Sync (aka: How to crash your machine without really trying…)](https://reader034.vdocuments.site/reader034/viewer/2022051401/5697bff71a28abf838cbe9cc/html5/thumbnails/5.jpg)
Family LONG InterlockedExchange(
PLONG plTarget, LONG lValue);
PVOID InterlockedExchangePointer( PVOID* ppvTarget, PVOID pvValue);
![Page 6: Win32 Programming Lesson 11: User-mode Thread Sync (aka: How to crash your machine without really trying…)](https://reader034.vdocuments.site/reader034/viewer/2022051401/5697bff71a28abf838cbe9cc/html5/thumbnails/6.jpg)
Spinlock… // Global variable indicating whether a shared re
source is in use or not
BOOL g_fResourceInUse = FALSE;
void Func1() { // Wait to access the resource. while (InterlockedExchange ( &g_fResourceInUse, TRUE) == TRUE) Sleep(0);
// Access the resource. // We no longer need to access the resource. InterlockedExchange(&g_fResourceInUse, FALSE); }
![Page 7: Win32 Programming Lesson 11: User-mode Thread Sync (aka: How to crash your machine without really trying…)](https://reader034.vdocuments.site/reader034/viewer/2022051401/5697bff71a28abf838cbe9cc/html5/thumbnails/7.jpg)
Spinlocks (cntd) Be careful on a single processor machine Is Sleep(0) the best call? Why?
![Page 8: Win32 Programming Lesson 11: User-mode Thread Sync (aka: How to crash your machine without really trying…)](https://reader034.vdocuments.site/reader034/viewer/2022051401/5697bff71a28abf838cbe9cc/html5/thumbnails/8.jpg)
More Interlocked Calls… PVOID InterlockedCompareExchange(
PLONG plDestination, LONG lExchange, LONG lComparand);
PVOID InterlockedCompareExchangePointer( PVOID* ppvDestination, PVOID pvExchange, PVOID pvComparand);
Basically, update on equality…
![Page 9: Win32 Programming Lesson 11: User-mode Thread Sync (aka: How to crash your machine without really trying…)](https://reader034.vdocuments.site/reader034/viewer/2022051401/5697bff71a28abf838cbe9cc/html5/thumbnails/9.jpg)
Cashing in… (groan) When a CPU accesses memory, it does not
read a single byte, but instead fills a “cache line” (32 or 64 bytes, aligned on a 32 or 64 byte boundary)
If the cache becomes dirty it is flushed Has a huge impact on how to design data
structures for speed
![Page 10: Win32 Programming Lesson 11: User-mode Thread Sync (aka: How to crash your machine without really trying…)](https://reader034.vdocuments.site/reader034/viewer/2022051401/5697bff71a28abf838cbe9cc/html5/thumbnails/10.jpg)
_declspec(align32) See MSDN Basically, forces alignment on a cache
boundary See: declspec example…
![Page 11: Win32 Programming Lesson 11: User-mode Thread Sync (aka: How to crash your machine without really trying…)](https://reader034.vdocuments.site/reader034/viewer/2022051401/5697bff71a28abf838cbe9cc/html5/thumbnails/11.jpg)
DON’T DO THIS! volatile BOOL g_fFinishedCalculation = FALSE;
int WINAPI WinMain(...) { CreateThread(..., RecalcFunc, ...); // Wait for the recalculation to complete. while (!g_fFinishedCalculation) ; }
DWORD WINAPI RecalcFunc(PVOID pvParam) { // Perform the recalculation. g_fFinishedCalculation = TRUE; return(0);}
![Page 12: Win32 Programming Lesson 11: User-mode Thread Sync (aka: How to crash your machine without really trying…)](https://reader034.vdocuments.site/reader034/viewer/2022051401/5697bff71a28abf838cbe9cc/html5/thumbnails/12.jpg)
Volatile? Well? Oops (optimizer…):
; Copy the value into a register Label: MOV Reg0, [g_fFinishedCalculation] TEST Reg0, 0; Is the value 0? JMP Reg0 == 0, Label; The register is 0, try again ... ; The register is not 0 (end of loop)
![Page 13: Win32 Programming Lesson 11: User-mode Thread Sync (aka: How to crash your machine without really trying…)](https://reader034.vdocuments.site/reader034/viewer/2022051401/5697bff71a28abf838cbe9cc/html5/thumbnails/13.jpg)
Critical Section Can mark a code section as critical This prevents any other thread accessing the
resources within the critical section Other threads do still get scheduled though…
![Page 14: Win32 Programming Lesson 11: User-mode Thread Sync (aka: How to crash your machine without really trying…)](https://reader034.vdocuments.site/reader034/viewer/2022051401/5697bff71a28abf838cbe9cc/html5/thumbnails/14.jpg)
Look at this… const int MAX_TIMES = 1000;
int g_nIndex = 0; DWORD g_dwTimes[MAX_TIMES];
DWORD WINAPI FirstThread(PVOID pvParam) { while (g_nIndex < MAX_TIMES) { g_dwTimes[g_nIndex] = GetTickCount(); g_nIndex++; } return(0);} DWORD WINAPI SecondThread(PVOID pvParam) { while (g_nIndex < MAX_TIMES) { g_nIndex++; g_dwTimes[g_nIndex - 1] = GetTickCount(); } return(0); }
![Page 15: Win32 Programming Lesson 11: User-mode Thread Sync (aka: How to crash your machine without really trying…)](https://reader034.vdocuments.site/reader034/viewer/2022051401/5697bff71a28abf838cbe9cc/html5/thumbnails/15.jpg)
Fixed.. const int MAX_TIMES = 1000;
int g_nIndex = 0; DWORD g_dwTimes[MAX_TIMES];CRITICAL_SECTION g_cs;
DWORD WINAPI FirstThread(PVOID pvParam) { while (g_nIndex < MAX_TIMES) { EnterCriticalSection(&g_cs); g_dwTimes[g_nIndex] = GetTickCount(); g_nIndex++; LeaveCriticalSection(&g_cs); } return(0);} DWORD WINAPI SecondThread(PVOID pvParam) { while (g_nIndex < MAX_TIMES) { EnterCriticalSection(&g_cs); g_nIndex++; g_dwTimes[g_nIndex - 1] = GetTickCount(); LeaveCriticalSection(&g_cs); } return(0); }
![Page 16: Win32 Programming Lesson 11: User-mode Thread Sync (aka: How to crash your machine without really trying…)](https://reader034.vdocuments.site/reader034/viewer/2022051401/5697bff71a28abf838cbe9cc/html5/thumbnails/16.jpg)
But… You MUST remember to leave a critical
section else no other thread can use the resource
And the Devil really is in the details
![Page 17: Win32 Programming Lesson 11: User-mode Thread Sync (aka: How to crash your machine without really trying…)](https://reader034.vdocuments.site/reader034/viewer/2022051401/5697bff71a28abf838cbe9cc/html5/thumbnails/17.jpg)
Initialization Before you can use a CRITICAL SECTION
you must initialize it VOID InitializeCriticalSection(PCRITICAL_SE
CTION pcs); Results undefined if you don’t do this… BTW, what do you notice about the return?
![Page 18: Win32 Programming Lesson 11: User-mode Thread Sync (aka: How to crash your machine without really trying…)](https://reader034.vdocuments.site/reader034/viewer/2022051401/5697bff71a28abf838cbe9cc/html5/thumbnails/18.jpg)
Entering… If no thread is using the resource, continue Else put the calling thread into a WAIT state VOID EnterCriticalSection(PCRITICAL_SE
CTION pcs); Can use:
BOOL TryEnterCriticalSection(PCRITICAL_SECTION pcs);
Don’t wait: return TRUE/FALSE
![Page 19: Win32 Programming Lesson 11: User-mode Thread Sync (aka: How to crash your machine without really trying…)](https://reader034.vdocuments.site/reader034/viewer/2022051401/5697bff71a28abf838cbe9cc/html5/thumbnails/19.jpg)
Leaving VOID LeaveCriticalSection(PCRITICAL_SE
CTION pcs); If we’re done with this Section check for any
other threads waiting and mark 1 as schedulable
VOID DeleteCriticalSection(PCRITICAL_SECTION pcs);
![Page 20: Win32 Programming Lesson 11: User-mode Thread Sync (aka: How to crash your machine without really trying…)](https://reader034.vdocuments.site/reader034/viewer/2022051401/5697bff71a28abf838cbe9cc/html5/thumbnails/20.jpg)
Tips Use ONE critical section per shared resource Access multiple resources using multiple
critical sections Don’t hold on to a critical section for a long
time
![Page 21: Win32 Programming Lesson 11: User-mode Thread Sync (aka: How to crash your machine without really trying…)](https://reader034.vdocuments.site/reader034/viewer/2022051401/5697bff71a28abf838cbe9cc/html5/thumbnails/21.jpg)
Next… Thread Synchronization with Kernel objects