- Timestamp:
- Apr 14, 2004, 10:45:45 AM (21 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/odincrt/critsect.cpp
r10533 r10580 1 /* $Id: critsect.cpp,v 1.1 1 2004-03-16 17:24:53sandervl Exp $ */1 /* $Id: critsect.cpp,v 1.12 2004-04-14 08:45:45 sandervl Exp $ */ 2 2 /* 3 3 * Critical sections in the Win32 sense … … 6 6 * 7 7 */ 8 #define INCL_DOS9 8 #define INCL_DOSPROCESS 10 9 #define INCL_DOSERRORS 11 10 #define INCL_DOSSEMAPHORES 12 #include <os2.h> 13 14 #include "dbglog.h" 11 #include <os2wrap.h> 12 #include <win32type.h> 13 #include <win32api.h> 14 #include <FastInfoBlocks.h> 15 16 #include <assert.h> 17 #include <stdio.h> 15 18 16 19 #include <odincrt.h> 17 #include <FastInfoBlocks.h> 20 18 21 19 22 #undef fibGetPid … … 24 27 #define dprintf(a) 25 28 #define DebugInt3() 29 30 31 ULONG WIN32API DosValidateCriticalSection (CRITICAL_SECTION_OS2 *crit) 32 { 33 if (crit->hevLock != NULLHANDLE) 34 { 35 return NO_ERROR; 36 } 37 38 return ERROR_INVALID_PARAMETER; 39 } 26 40 27 41 //****************************************************************************** … … 65 79 //****************************************************************************** 66 80 //****************************************************************************** 67 ULONG WIN32API DosInitializeCriticalSection(CRITICAL_SECTION_OS2 *crit, char *pszSemName, BOOL fShared) 68 { 81 inline ULONG GetCurrentProcessId() 82 { 83 #ifdef fibGetPid 84 return fibGetPid(); 85 #else 86 PTIB ptib; 87 PPIB ppib; 69 88 APIRET rc; 70 89 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 90 rc = DosGetInfoBlocks(&ptib, &ppib); 91 if(rc == NO_ERROR) { 92 return ppib->pib_ulpid; 93 } 94 DebugInt3(); 95 return 0; 96 #endif 97 } 98 99 /*********************************************************************** 100 * DosInitializeCriticalSection 101 */ 102 ULONG WIN32API DosInitializeCriticalSection(CRITICAL_SECTION_OS2 *crit, 103 PSZ pszSemName, BOOL fShared) 104 { 105 APIRET rc; 106 79 107 // initialize lock count with special value -1, meaning noone posesses it 80 108 crit->LockCount = -1; … … 82 110 crit->OwningThread = 0; 83 111 112 rc = DosCreateEventSem(pszSemName, &crit->hevLock, (pszSemName || fShared) ? DC_SEM_SHARED : 0, 0); 113 if(rc != NO_ERROR) { 114 DebugInt3(); 115 crit->hevLock = 0; 116 return rc; 117 } 84 118 crit->CreationCount = 1; 85 crit->Reserved = 0; 86 87 return NO_ERROR; 88 } 89 90 ULONG 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 101 ULONG WIN32API DosAccessCriticalSection(CRITICAL_SECTION_OS2 *crit, char *pszSemName) 119 crit->Reserved = GetCurrentProcessId(); 120 return NO_ERROR; 121 } 122 123 124 /*********************************************************************** 125 * DosAccessCriticalSection 126 */ 127 ULONG WIN32API DosAccessCriticalSection(CRITICAL_SECTION_OS2 *crit, PSZ pszSemName) 102 128 { 103 129 APIRET rc = NO_ERROR; … … 132 158 return NO_ERROR; 133 159 } 134 160 /*********************************************************************** 161 * DosDeleteCriticalSection 162 */ 135 163 ULONG WIN32API DosDeleteCriticalSection( CRITICAL_SECTION_OS2 *crit ) 136 164 { 137 if (DosValidateCriticalSection (crit)) 138 { 139 DosCloseEventSem (crit->hevLock); 140 165 if (crit->hevLock) 166 { 167 #ifdef DEBUG 168 if ( (crit->LockCount != -1 && crit->CreationCount == 1) 169 || crit->OwningThread 170 || crit->RecursionCount) /* Should not happen */ 171 { 172 DebugInt3(); 173 } 174 #endif 175 DosCloseEventSem(crit->hevLock); 141 176 if(DosInterlockedDecrement(&crit->CreationCount) == 0) 142 177 { … … 144 179 crit->RecursionCount = 0; 145 180 crit->OwningThread = 0; 146 crit->hevLock = 0; 147 crit->Reserved = 0; 148 } 149 } 150 return NO_ERROR; 151 } 152 153 181 crit->hevLock = 0; 182 crit->Reserved = (DWORD)-1; 183 } 184 } 185 return NO_ERROR; 186 } 187 188 189 /*********************************************************************** 190 * DosEnterCriticalSection 191 */ 154 192 ULONG WIN32API DosEnterCriticalSection( CRITICAL_SECTION_OS2 *crit, ULONG ulTimeout ) 155 193 { 156 APIRET rc = NO_ERROR;157 158 ULONG threadid = GetCurrentThreadId(); 159 194 DWORD res; 195 DWORD threadid = GetCurrentThreadId(); 196 197 // create crit sect just in time... 160 198 if (!crit->hevLock) 161 199 { 162 rc = DosInitializeCriticalSection (crit, NULL, FALSE); 163 if (rc != NO_ERROR) 164 { 200 DosInitializeCriticalSection(crit, NULL); 201 } 202 // if the same thread is requesting it again, memorize it 203 if (crit->OwningThread == threadid) 204 { 205 crit->RecursionCount++; 206 return NO_ERROR; 207 } 208 209 // do an atomic increase of the lockcounter 210 DosInterlockedIncrement(&crit->LockCount); 211 212 // do an atomic operation where we compare the owning thread id with 0 213 // and if this is true, exchange it with the id of the current thread. 214 testenter: 215 if(DosInterlockedCompareExchange((PLONG)&crit->OwningThread, threadid, 0)) 216 { 217 // the crit sect is in use 218 ULONG ulnrposts; 219 220 // now wait for it 221 APIRET rc = DosWaitEventSem(crit->hevLock, ulTimeout); 222 if(rc != NO_ERROR) { 223 DebugInt3(); 165 224 return rc; 166 225 } 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 226 DosResetEventSem(crit->hevLock, &ulnrposts); 227 // multiple waiters could be running now. Repeat the logic so that 228 // only one actually can get the critical section 229 goto testenter; 230 } 212 231 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 232 return NO_ERROR; 233 } 234 235 236 /*********************************************************************** 237 * DosLeaveCriticalSection 238 */ 226 239 ULONG WIN32API DosLeaveCriticalSection( CRITICAL_SECTION_OS2 *crit ) 227 240 { 228 dprintf(("Leaving the section\n"));229 241 if (crit->OwningThread != GetCurrentThreadId()) { 230 dprintf(("WRONG THREAD ID!!! owner is %8.8X\n", crit->OwningThread));242 DebugInt3(); 231 243 return ERROR_INVALID_PARAMETER; 232 244 } … … 234 246 if (--crit->RecursionCount) 235 247 { 236 dprintf(("Recursion exit: %d\n", crit->RecursionCount)); 237 DosInterlockedDecrement( &crit->LockCount ); 248 //just return 238 249 return NO_ERROR; 239 250 } 240 241 crit->Reserved = 0;242 251 crit->OwningThread = 0; 243 244 dprintf(("Released the section\n"));245 246 252 if (DosInterlockedDecrement( &crit->LockCount ) >= 0) 247 253 { 248 dprintf(("Posted the semaphore\n"));254 /* Someone is waiting */ 249 255 DosPostEventSem(crit->hevLock); 250 256 } 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. 262 */ 263 ULONG WIN32API DosIsInCriticalSection( CRITICAL_SECTION_OS2 *pCrit ) 264 { 265 return (pCrit->hevLock && pCrit->OwningThread == GetCurrentThreadId() ? NO_ERROR : ERROR_NOT_OWNER); 266 } 267 257 return NO_ERROR; 258 }
Note:
See TracChangeset
for help on using the changeset viewer.