Changeset 9756 for trunk/src


Ignore:
Timestamp:
Feb 6, 2003, 11:30:02 AM (23 years ago)
Author:
sandervl
Message:

Rewrote critical sections to be safe on SMP systems

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/odincrt/critsect.cpp

    r9336 r9756  
    1 /* $Id: critsect.cpp,v 1.7 2002-10-08 09:49:06 sandervl Exp $ */
     1/* $Id: critsect.cpp,v 1.8 2003-02-06 10:30:02 sandervl Exp $ */
    22/*
    33 * Critical sections in the Win32 sense
     
    3131// serialization and not lose any performance when concurrent access is unlikely.
    3232//
    33 // In case there is multiple access, we use the OS/2 kernel even semaphores.
     33// In case there is multiple access, we use the OS/2 kernel event semaphores.
    3434//******************************************************************************
    3535
     
    4848    rc = DosGetInfoBlocks(&ptib, &ppib);
    4949    if(rc == NO_ERROR) {
     50#ifdef DEBUG
     51        if(MAKE_THREADID(ppib->pib_ulpid, ptib->tib_ptib2->tib2_ultid) == 0) {
     52            DebugInt3();
     53        }
     54#endif
    5055        return MAKE_THREADID(ppib->pib_ulpid, ptib->tib_ptib2->tib2_ultid);
    5156    }
     
    125130    if (crit->hmtxLock)
    126131    {
    127         if (crit->RecursionCount)  /* Should not happen */
     132#ifdef DEBUG
     133        if (crit->LockCount != -1 || crit->OwningThread || crit->RecursionCount)  /* Should not happen */
    128134        {
    129135           DebugInt3();
    130136        }
     137#endif
    131138        DosCloseEventSem(crit->hmtxLock);
    132139        if(DosInterlockedDecrement(&crit->CreationCount) == 0)
     
    156163        DosInitializeCriticalSection(crit, NULL);
    157164    }
    158     // do an atomic increase of the lockcounter and see if it is > 0
    159     // (i.e. it is already posessed)
    160     if (DosInterlockedIncrement(&crit->LockCount))
    161     {
     165    // if the same thread is requesting it again, memorize it
     166    if (crit->OwningThread == threadid)
     167    {
     168        crit->RecursionCount++;
     169        return NO_ERROR;
     170    }
     171
     172    // do an atomic increase of the lockcounter
     173    DosInterlockedIncrement(&crit->LockCount);
     174
     175    // do an atomic operation where we compare the owning thread id with 0
     176    // and if this is true, exchange it with the id of the current thread.
    162177testenter:
    163         // if the same thread is requesting it again, memorize it
    164         if (crit->OwningThread == threadid)
    165         {
    166             crit->RecursionCount++;
    167             return NO_ERROR;
    168         }
    169         // do an atomic operation where we compare the owning thread id with 0
    170         // and if this is true, exchange it with the id of the current thread.
    171         if(DosInterlockedCompareExchange((PLONG)&crit->OwningThread, threadid, 0))
    172         {
    173             // the compare did not return equal, i.e. the crit sect is in use
    174 
    175             ULONG ulnrposts;
    176 
    177             /* Now wait for it */
    178             APIRET rc = DosWaitEventSem(crit->hmtxLock, ulTimeout);
    179             if(rc != NO_ERROR) {
    180                 DebugInt3();
    181                 return rc;
    182             }
    183             DosResetEventSem(crit->hmtxLock, &ulnrposts);
    184             // multiple waiters could be running now. Repeat the logic so that
    185             // only one actually can get the critical section
    186             goto testenter;
    187         }
    188     }
    189     crit->OwningThread   = GetCurrentThreadId();
     178    if(DosInterlockedCompareExchange((PLONG)&crit->OwningThread, threadid, 0))
     179    {
     180        // the crit sect is in use
     181        ULONG ulnrposts;
     182
     183        // now wait for it
     184        APIRET rc = DosWaitEventSem(crit->hmtxLock, ulTimeout);
     185        if(rc != NO_ERROR) {
     186            DebugInt3();
     187            return rc;
     188        }
     189        DosResetEventSem(crit->hmtxLock, &ulnrposts);
     190        // multiple waiters could be running now. Repeat the logic so that
     191        // only one actually can get the critical section
     192        goto testenter;
     193    }
    190194    crit->RecursionCount = 1;
    191195    return NO_ERROR;
    192 }
    193 
    194 
    195 /***********************************************************************
    196  *           DosTryEnterCriticalSection
    197  */
    198 BOOL WIN32API DosTryEnterCriticalSection( CRITICAL_SECTION_OS2 *crit )
    199 {
    200     if (DosInterlockedIncrement( &crit->LockCount ))
    201     {
    202         if (crit->OwningThread == GetCurrentThreadId())
    203         {
    204             crit->RecursionCount++;
    205             return TRUE;
    206         }
    207         DosInterlockedDecrement( &crit->LockCount );
    208         return FALSE;
    209     }
    210     crit->OwningThread   = GetCurrentThreadId();
    211     crit->RecursionCount = 1;
    212     return TRUE;
    213196}
    214197
     
    226209    if (--crit->RecursionCount)
    227210    {
    228         DosInterlockedDecrement( &crit->LockCount );
     211        //just return
    229212        return NO_ERROR;
    230213    }
Note: See TracChangeset for help on using the changeset viewer.