/*----------------------------------------------------- Script for AdSense -----------------------------------------------------*/ /* */ /* Footer ----------------------------------------------- */ #footer { clear: both; text-align: center; color: #333333; } #footer .widget { margin:.5em; padding-top: 20px; font-size: 85%; line-height: 1.5em; text-align: left; } /** Page structure tweaks for layout editor wireframe */ body#layout #header { width: 750px; } -->

Friday, April 23, 2010

Thread Synchronization in User Mode:1

All threads in the system must have access to system resources such as heaps, serial ports, files, windows, and countless others. If one thread requests exclusive access to a resource, other threads cannot get their work done.
Threads need to communicate with each other in two basic situations:
When you have multiple threads accessing a shared resource in such a way that the resource does not become corrupt
When one thread needs to notify one or more other threads that a specific task has been completed.

Windows offers many facilities to make thread synchronization easy.

atomic access: A big part of thread synchronization has to do with atomic access—a thread's ability to access a resource with the guarantee that no other thread will access that same resource at the same time. Let's look at a simple example:

// Define a global variable.
long g_x = 0;

DWORD WINAPI ThreadFunc1(PVOID pvParam) {

DWORD WINAPI ThreadFunc2(PVOID pvParam) {

MOV EAX, [g_x] ; Thread 1: Move 0 into a register.
INC EAX ; Thread 1: Increment the register to 1.

MOV EAX, [g_x] ; Thread 2: Move 0 into a register.
INC EAX ; Thread 2: Increment the register to 1.
MOV [g_x], EAX ; Thread 2: Store 1 back in g_x.

MOV [g_x], EAX ; Thread 1: Store 1 back in g_x.

If the code executes this way, the final value in g_x is 1—not 2 as you expect! This is pretty scary.
To solve the problem above, we need something simple. We need a way to guarantee that the incrementing of the value is done atomically—that is, without interruption. The interlocked family of functions provides the solution we need.

// The long variable shared by many threads
LONG g_x;

// Incorrect way to increment the long

// Correct way to increment the long
InterlockedExchangeAdd(&g_x, 1);

interlocked functions assert a hardware signal on the bus that prevents another CPU from accessing the same memory address.

No comments: