Changeset 10533 for trunk/src


Ignore:
Timestamp:
Mar 16, 2004, 6:24:54 PM (21 years ago)
Author:
sandervl
Message:

VP: Critical section update

Location:
trunk/src/odincrt
Files:
6 edited

Legend:

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

    r10186 r10533  
    1 /* $Id: critsect.cpp,v 1.10 2003-07-28 17:32:58 sandervl Exp $ */
     1/* $Id: critsect.cpp,v 1.11 2004-03-16 17:24:53 sandervl Exp $ */
    22/*
    33 * Critical sections in the Win32 sense
     
    66 *
    77 */
     8#define INCL_DOS
    89#define INCL_DOSPROCESS
    910#define INCL_DOSERRORS
    1011#define INCL_DOSSEMAPHORES
    11 #include <os2wrap.h>
    12 #include <win32type.h>
    13 #include <win32api.h>
     12#include <os2.h>
     13
     14#include "dbglog.h"
     15
     16#include <odincrt.h>
    1417#include <FastInfoBlocks.h>
    1518
    1619#undef fibGetPid
    1720
    18 #include <assert.h>
    19 #include <stdio.h>
    20 
    21 #include <odincrt.h>
    22 
    23 #ifdef DEBUG
    24 #define DebugInt3()     _interrupt(3)
    25 #else
     21#undef dprintf
     22#undef DebugInt3
     23
     24#define dprintf(a)
    2625#define DebugInt3()
    27 #endif
    28 
    2926
    3027//******************************************************************************
     
    6865//******************************************************************************
    6966//******************************************************************************
    70 inline ULONG GetCurrentProcessId()
    71 {
    72 #ifdef fibGetPid
    73     return fibGetPid();
    74 #else
    75     PTIB   ptib;
    76     PPIB   ppib;
     67ULONG WIN32API DosInitializeCriticalSection(CRITICAL_SECTION_OS2 *crit, char *pszSemName, BOOL fShared)
     68{
    7769    APIRET rc;
    7870
    79     rc = DosGetInfoBlocks(&ptib, &ppib);
    80     if(rc == NO_ERROR) {
    81         return ppib->pib_ulpid;
    82     }
    83     DebugInt3();
    84     return 0;
    85 #endif
    86 }
    87 
    88 /***********************************************************************
    89  *           DosInitializeCriticalSection
    90  */
    91 ULONG WIN32API DosInitializeCriticalSection(CRITICAL_SECTION_OS2 *crit,
    92                                             PSZ pszSemName, BOOL fShared)
    93 {
    94     APIRET rc;
    95 
     71    rc = DosCreateEventSem(pszSemName, &crit->hevLock, (pszSemName || fShared)? DC_SEM_SHARED: 0, 0);
     72   
     73    if(rc != NO_ERROR)
     74    {
     75        crit->hevLock = 0;
     76        return rc;
     77    }
     78   
    9679    // initialize lock count with special value -1, meaning noone posesses it
    9780    crit->LockCount      = -1;
     
    9982    crit->OwningThread   = 0;
    10083
    101     rc = DosCreateEventSem(pszSemName, &crit->hmtxLock, (pszSemName || fShared) ? DC_SEM_SHARED : 0, 0);
    102     if(rc != NO_ERROR) {
    103         DebugInt3();
    104         crit->hmtxLock = 0;
    105         return rc;
    106     }
    10784    crit->CreationCount  = 1;
    108     crit->Reserved       = GetCurrentProcessId();
    109     return NO_ERROR;
    110 }
    111 
    112 
    113 /***********************************************************************
    114  *           DosAccessCriticalSection
    115  */
    116 ULONG WIN32API DosAccessCriticalSection(CRITICAL_SECTION_OS2 *crit, PSZ pszSemName)
    117 {
    118     HMTX   hmtxLock = 0;
    119     APIRET rc;
    120 
    121     if(pszSemName == NULL && crit->hmtxLock == 0) {
    122         DebugInt3();
    123         return ERROR_INVALID_PARAMETER;
    124     }
    125     if(pszSemName == NULL) {
    126         hmtxLock = crit->hmtxLock;
    127     }
    128 
    129     rc = DosOpenEventSem(pszSemName, &hmtxLock);
    130     if(rc != NO_ERROR) {
    131         DebugInt3();
    132         return rc;
    133     }
     85    crit->Reserved       = 0;
     86   
     87    return NO_ERROR;
     88}
     89
     90ULONG WIN32API DosValidateCriticalSection (CRITICAL_SECTION_OS2 *crit)
     91{
     92    if (crit->hevLock != NULLHANDLE)
     93    {
     94        return NO_ERROR;
     95    }
     96   
     97    return ERROR_INVALID_PARAMETER;
     98}
     99
     100// Initializes or opens a critical section
     101ULONG WIN32API DosAccessCriticalSection(CRITICAL_SECTION_OS2 *crit, char *pszSemName)
     102{
     103    APIRET rc = NO_ERROR;
     104   
     105    // Increment creation counter to prevent the section to be destroyed while
     106    // we are checking it. Assume that an unitialized section has the counter == 0
    134107    DosInterlockedIncrement(&crit->CreationCount);
    135     return NO_ERROR;
    136 }
    137 /***********************************************************************
    138  *           DosDeleteCriticalSection
    139  */
     108   
     109    if (DosValidateCriticalSection (crit) == NO_ERROR)
     110    {
     111        // the section already initialized, use it
     112        HEV hevLock = NULLHANDLE;
     113       
     114        if (pszSemName == NULL)
     115        {
     116            hevLock = crit->hevLock;
     117        }
     118
     119        rc = DosOpenEventSem(pszSemName, &hevLock);
     120
     121        if (rc != NO_ERROR)
     122        {
     123            DosInterlockedDecrement(&crit->CreationCount);
     124            DebugInt3();
     125        }
     126    }
     127    else
     128    {
     129        rc = DosInitializeCriticalSection (crit, pszSemName, TRUE);
     130    }
     131     
     132    return NO_ERROR;
     133}
     134
    140135ULONG WIN32API DosDeleteCriticalSection( CRITICAL_SECTION_OS2 *crit )
    141136{
    142     if (crit->hmtxLock)
    143     {
    144 #ifdef DEBUG
    145         if (  (crit->LockCount != -1 && crit->CreationCount == 1)
    146             || crit->OwningThread
    147             || crit->RecursionCount)  /* Should not happen */
    148         {
    149            DebugInt3();
    150         }
    151 #endif
    152         DosCloseEventSem(crit->hmtxLock);
     137    if (DosValidateCriticalSection (crit))
     138    {
     139        DosCloseEventSem (crit->hevLock);
     140       
    153141        if(DosInterlockedDecrement(&crit->CreationCount) == 0)
    154142        {
     
    156144            crit->RecursionCount = 0;
    157145            crit->OwningThread   = 0;
    158             crit->hmtxLock       = 0;
    159             crit->Reserved       = (DWORD)-1;
    160         }
    161     }
    162     return NO_ERROR;
    163 }
    164 
    165 
    166 /***********************************************************************
    167  *           DosEnterCriticalSection
     146            crit->hevLock        = 0;
     147            crit->Reserved       = 0;
     148        }
     149    }
     150    return NO_ERROR;
     151}
     152
     153
     154ULONG WIN32API DosEnterCriticalSection( CRITICAL_SECTION_OS2 *crit, ULONG ulTimeout )
     155{
     156    APIRET rc = NO_ERROR;
     157           
     158    ULONG threadid = GetCurrentThreadId();
     159           
     160    if (!crit->hevLock)
     161    {
     162        rc = DosInitializeCriticalSection (crit, NULL, FALSE);
     163        if (rc != NO_ERROR)
     164        {
     165            return rc;
     166        }
     167    }
     168
     169    dprintf(("Entering the section: owner = %8.8X\n", crit->OwningThread));
     170
     171    // We want to acquire the section, count the entering
     172    DosInterlockedIncrement (&crit->LockCount);
     173   
     174    // try to acquire the section
     175    for (;;)
     176    {
     177        // try to assign owning thread id atomically
     178        if (DosInterlockedCompareExchange((PLONG)&crit->OwningThread, threadid, 0) == 0)
     179        {
     180            ULONG ulnrposts = 0;
     181
     182            dprintf(("Acquired the section: owner = %8.8X\n", crit->OwningThread));
     183            DosResetEventSem (crit->hevLock, &ulnrposts);
     184            break;
     185        }
     186       
     187        if (crit->OwningThread == threadid)
     188        {
     189            // This thread already owns the section
     190            crit->RecursionCount++;
     191            dprintf(("Recursion: %d\n", crit->RecursionCount));
     192            return NO_ERROR;
     193        }
     194
     195        // Arise any timing problems and let others to run
     196        DosSleep (0);
     197
     198        dprintf(("Waiting on sem: owner = %8.8X\n", crit->OwningThread));
     199        rc = DosWaitEventSem (crit->hevLock, ulTimeout);
     200        dprintf(("Returned from wait: owner = %8.8X, rc = %d\n", crit->OwningThread, rc));
     201       
     202        if (rc != NO_ERROR)
     203        {
     204            dprintf(("Returned from wait: FAILED!!!\n"));
     205            // We fail, deregister itself
     206            DosInterlockedDecrement (&crit->LockCount);
     207            return rc;
     208        }
     209    }
     210   
     211    // the section was successfully aquired
     212    crit->RecursionCount = 1;
     213   
     214    if (crit->Reserved != 0)
     215    {
     216        // the section already entered!!!!
     217        DosBeep (2000, 200);
     218    }
     219   
     220    crit->Reserved = 1;
     221   
     222    return NO_ERROR;
     223}
     224
     225
     226ULONG WIN32API DosLeaveCriticalSection( CRITICAL_SECTION_OS2 *crit )
     227{
     228    dprintf(("Leaving the section\n"));
     229    if (crit->OwningThread != GetCurrentThreadId()) {
     230        dprintf(("WRONG THREAD ID!!! owner is %8.8X\n", crit->OwningThread));
     231        return ERROR_INVALID_PARAMETER;
     232    }
     233
     234    if (--crit->RecursionCount)
     235    {
     236        dprintf(("Recursion exit: %d\n", crit->RecursionCount));
     237        DosInterlockedDecrement( &crit->LockCount );
     238        return NO_ERROR;
     239    }
     240   
     241    crit->Reserved = 0;
     242    crit->OwningThread = 0;
     243
     244    dprintf(("Released the section\n"));
     245
     246    if (DosInterlockedDecrement( &crit->LockCount ) >= 0)
     247    {
     248        dprintf(("Posted the semaphore\n"));
     249        DosPostEventSem(crit->hevLock);
     250    }
     251   
     252    return NO_ERROR;
     253}
     254
     255
     256/**
     257 * Checks if the current thread is in the critical section or now.
     258 *
     259 * @returns NO_ERROR if in the critical section.
     260 * @returns ERROR_NOT_OWNER if not in the critical section.
     261 * @param   pCrit   Pointer to the critical section.
    168262 */
    169 ULONG WIN32API DosEnterCriticalSection( CRITICAL_SECTION_OS2 *crit, ULONG ulTimeout )
    170 {
    171     DWORD res;
    172     DWORD threadid = GetCurrentThreadId();
    173 
    174     // create crit sect just in time...
    175     if (!crit->hmtxLock)
    176     {
    177         DosInitializeCriticalSection(crit, NULL);
    178     }
    179     // if the same thread is requesting it again, memorize it
    180     if (crit->OwningThread == threadid)
    181     {
    182         crit->RecursionCount++;
    183         return NO_ERROR;
    184     }
    185 
    186     // do an atomic increase of the lockcounter
    187     DosInterlockedIncrement(&crit->LockCount);
    188 
    189     // do an atomic operation where we compare the owning thread id with 0
    190     // and if this is true, exchange it with the id of the current thread.
    191 testenter:
    192     if(DosInterlockedCompareExchange((PLONG)&crit->OwningThread, threadid, 0))
    193     {
    194         // the crit sect is in use
    195         ULONG ulnrposts;
    196 
    197         // now wait for it
    198         APIRET rc = DosWaitEventSem(crit->hmtxLock, ulTimeout);
    199         if(rc != NO_ERROR) {
    200             DebugInt3();
    201             return rc;
    202         }
    203         DosResetEventSem(crit->hmtxLock, &ulnrposts);
    204         // multiple waiters could be running now. Repeat the logic so that
    205         // only one actually can get the critical section
    206         goto testenter;
    207     }
    208     crit->RecursionCount = 1;
    209     return NO_ERROR;
    210 }
    211 
    212 
    213 /***********************************************************************
    214  *           DosLeaveCriticalSection
    215  */
    216 ULONG WIN32API DosLeaveCriticalSection( CRITICAL_SECTION_OS2 *crit )
    217 {
    218     if (crit->OwningThread != GetCurrentThreadId()) {
    219         DebugInt3();
    220         return ERROR_INVALID_PARAMETER;
    221     }
    222 
    223     if (--crit->RecursionCount)
    224     {
    225         //just return
    226         return NO_ERROR;
    227     }
    228     crit->OwningThread = 0;
    229     if (DosInterlockedDecrement( &crit->LockCount ) >= 0)
    230     {
    231         /* Someone is waiting */
    232         DosPostEventSem(crit->hmtxLock);
    233     }
    234     return NO_ERROR;
    235 }
     263ULONG WIN32API DosIsInCriticalSection( CRITICAL_SECTION_OS2 *pCrit )
     264{
     265    return  (pCrit->hevLock && pCrit->OwningThread == GetCurrentThreadId() ? NO_ERROR : ERROR_NOT_OWNER);
     266}
     267
  • trunk/src/odincrt/odin36.def

    r10185 r10533  
    1 ; $Id: odin36.def,v 1.10 2003-07-28 11:30:17 sandervl Exp $
     1; $Id: odin36.def,v 1.11 2004-03-16 17:24:53 sandervl Exp $
    22; Odin VAC++ 3.6.5 shared multithreaded runtime
    33LIBRARY ODINCRT INITINSTANCE TERMINSTANCE
     
    986986    _DosInterlockedExchangeAdd@8                       @1208 NONAME
    987987    _DosInterlockedIncrement@4                         @1209 NONAME
     988    _DosValidateCriticalSection@4                      @1210 NONAME
  • trunk/src/odincrt/odin36d.def

    r10185 r10533  
    1 ; $Id: odin36d.def,v 1.10 2003-07-28 11:30:18 sandervl Exp $
     1; $Id: odin36d.def,v 1.11 2004-03-16 17:24:54 sandervl Exp $
    22; Odin VAC++ 3.6.5 shared multithreaded runtime
    33LIBRARY ODINCRTD INITINSTANCE TERMINSTANCE
     
    994994    _DosInterlockedExchangeAdd@8                       @1208 NONAME
    995995    _DosInterlockedIncrement@4                         @1209 NONAME
     996    _DosValidateCriticalSection@4                      @1210 NONAME
  • trunk/src/odincrt/odincrt.def

    r10185 r10533  
    1 ; $Id: odincrt.def,v 1.30 2003-07-28 11:30:19 sandervl Exp $
     1; $Id: odincrt.def,v 1.31 2004-03-16 17:24:54 sandervl Exp $
    22; Odin VAC++ 3.08 shared multithreaded runtime
    33LIBRARY ODINCRT INITINSTANCE TERMINSTANCE
     
    967967    _DosInterlockedExchangeAdd@8                       @1208 NONAME
    968968    _DosInterlockedIncrement@4                         @1209 NONAME
     969    _DosValidateCriticalSection@4                      @1210 NONAME
  • trunk/src/odincrt/odincrtd.def

    r10185 r10533  
    1 ; $Id: odincrtd.def,v 1.11 2003-07-28 11:30:19 sandervl Exp $
     1; $Id: odincrtd.def,v 1.12 2004-03-16 17:24:54 sandervl Exp $
    22; Odin VAC++ 3.08 shared multithreaded runtime
    33LIBRARY ODINCRTD INITINSTANCE TERMINSTANCE
     
    966966    _DosInterlockedExchangeAdd@8                       @1208 NONAME
    967967    _DosInterlockedIncrement@4                         @1209 NONAME
     968    _DosValidateCriticalSection@4                      @1210 NONAME
  • trunk/src/odincrt/odincrtp.def

    r10185 r10533  
    1 ; $Id: odincrtp.def,v 1.8 2003-07-28 11:30:20 sandervl Exp $
     1; $Id: odincrtp.def,v 1.9 2004-03-16 17:24:54 sandervl Exp $
    22; Odin VAC++ 3.08 shared multithreaded runtime
    33LIBRARY ODINCRTP INITINSTANCE TERMINSTANCE
     
    987987    _DosInterlockedExchangeAdd@8                       @1208 NONAME
    988988    _DosInterlockedIncrement@4                         @1209 NONAME
     989    _DosValidateCriticalSection@4                      @1210 NONAME
Note: See TracChangeset for help on using the changeset viewer.