Critical Sections

A critical section allows you to protect certain fragments of the program to ensure that only one thread is executed in this section at a time. Consider the functions for working with critical sections.

  • InitializeCriticalSection Creates an object called the critical section. It accepts the only parametera pointer to the CRITICAL_SECTION structure. The fields of this structure are used only by internal procedures; therefore, their meaning is of no importance for application programmers.

     CRITICAL_SECTION STRUCT       DebugInfo      DWORD  ?       LockCount      LONG   ?       RecursionCount LONG   ?       OwningThread   HANDLE ?       LockSemaphore  HANDLE ?       SpinCount      DWORD  ?     CRITICAL_SECTION ENDS 
  • EnterCriticalSection Enters the critical section. After executing this function, the current thread becomes the owner of the specified critical section. If another thread calls this function, it will enter the waiting state. This function accepts the same parameter as the previous one.

  • LeaveCriticalSection Leaves the critical section. After that, the second thread stopped by the EnterCriticalSection function will become the owner of the critical section. The LeaveCriticalSection function accepts the same parameter as the previous functions.

  • DeleteCriticalSection Deletes the critical section object. The parameter of this function is similar to the parameters of the previous functions.

Programmatically, it is possible to determine several critical section objects, with which several threads will operate . When describing critical sections, I intentionally mention only threads. Different processes cannot use this synchronization object.

Now, consider the example illustrating the use of critical section. The idea of the program presented in Listing 15.3 is as follows : Two threads from time to time call the procedure that displays the next character from the string into the window. As a result of such competing operation, the string must be printed. Part of the procedure that outputs the next character is made the critical section; therefore, only one thread at a time outputs data into the window.

Listing 15.3: Synchronizing two threads using a critical section
image from book
 ; The THREAD2.INC file ; Constants ; This message arrives when the window is closed WM_DESTROY               equ 2 ; This message arrives when the window is created WM_CREATE                equ 1 ; This message arrives when the left mouse button is clicked ; in the window area WM_LBUTTONDOWN           equ 201h ; This message arrives when the right mouse button is clicked ; in the window area WM_RBUTTONDOWN           equ 204h ; Window properties CS_VREDRAW               equ lh CS_HREDRAW               equ 2h CS_GLOBALCLASS           equ 4000h WS_OVERLAPPEDWINDOW      equ 000CF0000H Stylcl                   equ CS_HREDRAW+CS_VREDRAW+CS_GLOBALCLASS DXO                      equ 300 DYO                      equ 200 ; Color components RED                      equ 50 GREEN                    equ 50 BLUE                     equ 255 RGBW                     equ (RED or (GREEN shl 8)) or (BLUE shl 16 RGBT                     equ 255 ; Red ; Standard icon identifier IDI_APPLICATION          equ 32512 ; Cursor identifier IDC_CROSS                equ 32515 ; Display mode---Normal SW_SHOWNORMAL            equ 1 ; Prototypes of external procedures IFDEF MASM         EXTERN Sleep@4:NEAR         EXTERN CreateThread@24:NEAR         EXTERN InitializeCriticalSection@4:NEAR         EXTERN EnterCriticalSection@4:NEAR         EXTERN LeaveCriticalSection@4:NEAR         EXTERN DeleteCriticalSection@4:NEAR         EXTERN GetTextExtentPoint32A@16:NEAR         EXTERN CreateWindowExA@48:NEAR         EXTERN DefWindowProcA@16:NEAR         EXTERN DispatchMessageA@4:NEAR         EXTERN ExitProcess@4:NEAR         EXTERN GetMessageA@16:NEAR         EXTERN GetModuleHandleA@4:NEAR         EXTERN LoadCursorA@8:NEAR         EXTERN LoadIconA@8:NEAR         EXTERN PostQuitMessage@4:NEAR         EXTERN RegisterClassA@4:NEAR         EXTERN ShowWindow@8:NEAR         EXTERN TranslateMessage@4: NEAR         EXTERN UpdateWindow@4:NEAR         EXTERN TextOutA@20:NEAR         EXTERN CreateSolidBrush@4:NEAR         EXTERN SetBkColor@8:NEAR         EXTERN SetTextColor@8:NEAR         EXTERN GetDC@4:NEAR         EXTERN DeleteDC@4:NEAR ELSE         EXTERN DeleteDC@4:NEAR         EXTERN Sleep:NEAR         EXTERN CreateThread:NEAR         EXTERN InitializeCriticalSection:NEAR         EXTERN EnterCriticalSection:NEAR         EXTERN LeaveCriticalSection:NEAR         EXTERN DeleteCriticalSection:NEAR         EXTERN GetTextExtentPoint32A:NEAR         EXTERN CreateWindowExA:NEAR         EXTERN DefWindowProcA:NEAR         EXTERN DispatchMessageA:NEAR         EXTERN ExitProcess:NEAR         EXTERN GetMessageA:NEAR         EXTERN GetModuleHandleA:NEAR         EXTERN LoadCursorA:NEAR         EXTERN LoadlconA:NEAS         EXTERN PostQuitMessage:NEAR         EXTERN RegisterClassA:NEAR         EXTERN ShowWindow:NEAR         EXTERN TranslateMessage:NEAR         EXTERN UpdateWindow:NEAR         EXTERN TextOutA:NEAR         EXTERN CreateSolidBrush:NEAR         EXTERN SetBkColor:NEAR         EXTERN SetTextColor:NEAR         EXTERN GetDC:NEAR         EXTERN DeleteDC:NEAR         Sleep@4 = Sleep          CreateThread@24 = CreateThread          InitializeCriticalSection@4 = InitializeCriticalSection          EnterCriticalSection@4 = EnterCriticalSection          LeaveCriticalSection@4 = LeaveCriticalSection          DeleteCriticalSection@4 = DeleteCriticalSection          GetTextExtentPoint32A@16 = GetTextExtentPoint32A          CreateWindowExA@48 = CreateWindowExA          DefWindowProcA@16 = DefWindowProcA          DispatchMessageA@4 = DispatchMessageA          ExitProcess@4 = ExitProcess          GetMessageA@16 = GetMessageA          GetModuleHandleA@4 = GetModuleHandleA          LoadCursorA@8 = Load-CursorA          LoadIconA@8 = LoadIconA          PostQuitMessage@4 = PostQuitMessage          RegisterClassA@4 = RegisterClassA          ShowWindow@8 = ShowWindow          TranslateMessage@4 = TranslateMessage          UpdateWindow@4 = UpdateWindow          TextOutA@20 = TextOutA          CreateSolidBrush@4 = CreateSolidBrush          SetBkColor@8 = SetBkColor          SetTextColor@8 = SetTextColor          GetDC@4 = GetDC          DeleteDC@4 = DeleteDC ENDIF ; Structures ; Message structure MSGSTRUCT STRUC         MSHWND           DD ?         MSMESSAGE        DD ?         MSWPARAM         DD ?         MSLPARAM         DD ?         MSTIME           DD ?         MSPT             DD ? MSGSTRUCT ENDS ;---------- WNDCLASS STRUC         CLSSTYLE         DD ?         CLSLPFNWNDPROC   DD ?         CLSCBCLSEXTRA    DD ?         CLSCBWNDEXTRA    DD ?         CLSHINSTANCE     DD ?         CLSHICON         DD ?         CLSHCURSOR       DD ?         CLSHBRBACKGROUND DD ?         MENNAME          DD ?         CLSNAME          DD ? WNDCLASS ENDS ; Structure for working with the critical section CRIT STRUC         DD ?         DD ?         DD ?         DD ?         DD ?         DD ? CRIT ENDS ; Structure for determining the text length SIZET STRUC         X1  DWORD ?         Y1  DWORD ? SIZET ENDS ; The THREAD2.ASM file .586P ; Flat memory model .MODEL FLAT, stdcall ;----------------------------------------------- include thread2.inc ; INCLUDELIB directives IFDEF MASM         includelib c:\masm32\lib\user32.lib         includelib c:\masm32\lib\kernel32.lib         includelib c:\masm32\lib\gdi32.lib ELSE         includelib c:\tasm32\lib\import32.lib ENDIF ;----------------------------------------------- ; Data segment _DATA SEGMENT         NEWHWND   DD 0         MSG       MSGSTRUCT <?>         WC        WNDCLASS  <?>         SZT       SIZET  <?>         HINST     DD 0         TITLENAME DB 'Output into the window using two threads', 0         NAM   DB 'CLASS32', 0         XT    DWORD 30         YT    DWORD 30         HW    DD ?         DC    DD ?         TEXT  DB 'Text in window is red', 0         SPA   DB '            '               DB '            ', 0         IND   DD 0         SK    CRIT <?>         THR1  DD ?         THR2  DD ?         FLAG1 DD 0         FLAG2 DD 0 _DATA ENDS ; Code segment _TEXT SEGMENT START: ; Get the application descriptor         PUSH 0         CALL GetModuleHandleA@4         MOV  [HINST], EAX REG_CLASS: ; Fill the window structure ; Style         MOV   [WC.CLSSTYLE], stylcl ; Message-handling procedure         MOV   [WC.CLSLPFNWNDPROC], OFFSET WNDPROC         MOV   [WC.CLSCBCLSEXTRA], 0         MOV   [WC.CLSCBWNDEXTRA], 0         MOV   EAX, [HINST]         MOV   [WC.CLSHINSTANCE], EAX ;---------- Window icon         PUSH  IDI_APPLICATION         PUSH 0         CALL LoadIconA@8         MOV   [WC.CLSHICON], EAX ;---------- Window cursor         PUSH IDC_CROSS         PUSH 0         CALL LoadCursorA@8         MOV   [WC.CLSHCURSOR], EAX ;----------         PUSH  RGBW ; Brush color         CALL  CreateSolidBrush@4 ; Create a brush         MOV   [WC.CLSHBRBACKGROUND], EAX         MOV   DWORD PTR [WC.MENNAME], 0         MOV   DWORD PTR [WC.CLSNAME], OFFSET NAM         PUSH  OFFSET WC         CALL  RegisterClassA@4 ; Create a window of the registered class         PUSH  0         PUSH  [HINST]         PUSH  0         PUSH  0         PUSH  DY0       ; DYO - Window height         PUSH  DX0       ; DXO - Window width         PUSH  100       ; Y-coordinate         PUSH  100       ; X-coordinate         PUSH  WS_OVERLAPPEDWINDOW         PUSH  OFFSET TITLENAME ; Window name         PUSH  OFFSET NAM    ; Class name         PUSH  0         CALL  CreateWindowExA@48 ; Check for an error         CMP   EAX, 0         JZ    _ERR         MOV   [NEWHWND], EAX ; Window descriptor ;----------------------------------         PUSH  SW_SHOWNORMAL         PUSH  [NEWHWND]         CALL  ShowWindow@8 ; Show the newly-created window ;----------------------------------         PUSH  [NEWHWND]         CALL  UpdateWindow@4 ; Redraw the visible part of the window ; Message-processing loop MSG_LOOP:         PUSH  0         PUSH  0         PUSH  0         PUSH  OFFSET MSG         CALL  GetMessageA@16         CMP   AX, 0         JE    END_LOOP         PUSH  OFFSET MSG         CALL  TranslateMessage@4         PUSH  OFFSET MSG         CALL  DispatchMessageA@4         JMP   MSG_LOOP END_LOOP: ; Exit the program (close the process)         PUSH  [MSG.MSWPARAM]         CALL  ExitProcess@4 _ERR:         JMP   END_LOOP ;---------------------------------- ; Window procedure ; Position of parameters in the stack ; [EBP+014H]  ; LPARAM ; [EBP+10H]   ; WAPARAM ; [EBP+0CH]   ; MES ; [EBP+8]   ; HWND WNDPROC    PROC         PUSH  EBP         MOV   EBP, ESP         PUSH  EBX         PUSH  ESI         PUSH  EDI         CMP   DWORD PTR [EBP+0CH], WM_DESTROY         JE    WMDESTROY         CMP   DWORD PTR [EBP+0CH], WM_CREATE         JE    WMCREATE         CMP   DWORD PTR [EBP+0CH], WM_LBUTTONDOWN         JNE   CONTIN ; Check the start flag         CMP   FLAG1, 0         JNE   DEFWNDPROC         MOV   FLAG1, 1 ; Initialize pointers         LEA   EAX, TEXT         MOV   IND, EAX         MOV   XT, 30 ; Start the first thread         PUSH  OFFSET THR1         PUSH  0         PUSH  EAX         PUSH  OFFSET THREAD1         PUSH  0         PUSH  0         CALL  CreateThread@24 ; Start the second thread         PUSH  OFFSET THR2         PUSH  0         PUSH  EAX         PUSH  OFFSET THREAD2         PUSH  0         PUSH  0         CALL  CreateThread@24.         JMP   DEFWNDPROC CONTIN:         CMP   DWORD PTR [EBP+0CH], WM_RBUTTONDOWN         JNE   DEFWNDPROC ; Check the start flag         CMP   FLAG2, 0         JNE   DEFWNDPROC         MOV   FLAG2, 1 ; Initialize pointers         LEA   EAX, SPA         MOV   IND, EAX         MOV   XT, 30 ; Start the first thread         PUSH  OFFSET THR1         PUSH  0         PUSH  EAX         PUSH  OFFSET THREAD1         PUSH  0         PUSH  0         CALL  CreateThread@24 ; Start the second thread         PUSH  OFFSET THR2         PUSH  0         PUSH  EAX         PUSH  OFFSET THREAD2         PUSH  0         PUSH  0         CALL  CreateThread@24         JMP   DEFWNDPROC WMCREATE:         MOV   EAX, DWORD PTR [EBP+08H] ; Store the window descriptor in a global variable         MOV   HW, EAX ; Initialize the critical section         PUSH  OFFSET SK         CALL  InitializeCriticalSection@4         MOV   EAX, 0         JMP   FINISH DEFWNDPROC:         PUSH  DWORD PTR [EBP+14H]         PUSH  DWORD PTR [EBP+10H]         PUSH  DWORD PTR [EBP+0CH]         PUSH  DWORD PTR [EBP+08H]         CALL  DefWindowProcA@16         JMP   FINISH WMDESTROY: ; Delete the critical section         PUSH  OFFSET SK         CALL  DeleteCriticalSection@4         PUSH  0         CALL  PostQuitMessage@4 ; WM_QUIT         MOV   EAX, 0 FINISH:         POP   EDI         POP   ESI         POP   EBX         POP   EBP         RET   16 WNDPROC    ENDP ; Output OUTSTR PROC ; Check whether the text has finished         MOV    EBX, IND         CMP    BYTE PTR [EBX], 0         JNE    NO_0         RET NO_0: ; Enter the critical section         PUSH   OFFSET SK         CALL   EnterCriticalSection@4 ;-----------------         PUSH   HW         CALL   GetDC@4         MOV    DC, EAX ;----------------- Background color = Window color         PUSH   RGBW         PUSH   EAX         CALL   SetBkColor@8 ;----------------- Text color (red)         PUSH   RGBT         PUSH   DC         CALL   SetTextColor@8 ;----------------- Output the text         PUSH   1         PUSH   IND         PUSH   YT         PUSH   XT         PUSH   DC         CALL   TextOutA@20 ; Compute the text length in pixels         PUSH   OFFSET SZT         PUSH   1         PUSH   IND         PUSH   DC         CALL   GetTextExtentPoint32A@16 ; Increase the pointers         MOV    EAX, SZT.X1         ADD    XT, EAX         INC    IND ;----------------- Close the context         PUSH   DC         CALL   DeleteDC@4 ; Exit the critical section         PUSH   OFFSET SK         CALL   LeaveCriticalSection@4         RET OUTSTR ENDP ; First thread THREAD1 PROC LO1: ; Check whether the end of the text has been reached         MOV    EBX, IND         CMP    BYTE PTR [EBX], 0         JE     _END1 ; Output the next character         CALL   OUTSTR  ; Delay         PUSH   1000         CALL   Sleep@4         JMP    LO1 _END1:         RET    4 THREAD1 ENDP ; Second thread THREAD2 PROC LO2: ; Check whether the end of the text has been reached         MOV    EBX, IND         CMP    BYTE PTR [EBX], 0         JE     _END2 ; Output the next character         CALL   OUTSTR ; Delay         PUSH   1000         CALL   Sleep@4         JMP    LO2 _END2:         RET    4 THREAD2 ENDP _TEXT ENDS END START 
image from book
 

To translate the THREAD2.ASM program presented in Listing 15.3, issue the following commands using MASM32:

 ML /c /coff /DMASM thread2.asm     LINK / SUBSYSTEM :WINDOWS thread2.obj 

Issue the following commands using TASM32:

 TASM32 /ml thread2.asm     TLINK32 -aa thread2.obj 

When the user clicks the left mouse button in the window area, the program starts string output. When the user clicks the right mouse button, the displayed string is erased. Flags FLAG1 and FLAG2 are introduced to ensure that string output and blank string output could be carried out only once. To slow text output, the delay ( Sleep ) is introduced into the loop for calling the OUTSTR procedure in each thread. Note that the letters mainly appear in pairs. This can be explained because when one of the threads outputs a character, the second thread is already waiting for its turn to output a character. Thus, as soon as the first thread leaves the critical section, the second thread immediately outputs the next character. After that, both threads are delayed (the Sleep function).

To complete the topic on critical sections, it is necessary to mention that this method of synchronization is the fastest . Drawbacks of this approach include the impossibility of several threads accessing the section simultaneously and the lack of special tools that allow you to count the number of attempts at accessing the resource.



The Assembly Programming Master Book
The Assembly Programming Master Book
ISBN: 8170088178
EAN: 2147483647
Year: 2004
Pages: 140
Authors: Vlad Pirogov

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net