From: Wu Y. <ad...@sh...> - 2004-03-14 16:09:18
|
At last I cannot bear with it any more. Here is the patch based on Thomas's mutex implementation. And the test files and a test log. I think the speed test really shows (3605:70 or 3605:50) that the change is worth while. Best regards, Wu Yongwei On Thu, 2003-11-20 at 20:21, Thomas Pfaff wrote: > Your version of TryEnterCriticalSection : > > /* Our own version of TryEnterCriticalSection since it is not available > * on Windows 9x. */ > static inline BOOL > __TryEnterCriticalSection (LPCRITICAL_SECTION lpCriticalSection) > { > HANDLE hThreadId = (HANDLE) GetCurrentThreadId(); > if (InterlockedIncrement(&lpCriticalSection->LockCount) == 0) > { > lpCriticalSection->OwningThread = hThreadId; > lpCriticalSection->RecursionCount = 1; > } > else > { > if (lpCriticalSection->OwningThread == hThreadId) > lpCriticalSection->RecursionCount++; > { > InterlockedDecrement(&lpCriticalSection->LockCount); > return FALSE; > } > return TRUE; > } > > has a race condition. > > If the mutex is locked and a task switch occurs between > InterlockedIncrement and InterlockedDecrement and the mutex is unlocked > during that time then the counter contains an invalid (still > incremented) value and the unlock function assumes that another thread > is waiting on that mutex. > And i do not think that critical section internals should be used here. > > The mutex logic which is used by pthreads-win32 and cygwin is similar to > a critical section: > > struct mutex > { > LONG counter; > HANDLE sema; > }; > > mx_init (struct mutex *mx) > { > mx->counter = 0; > mx->sema = CreateSemaphore (NULL, 0, LONG_MAX, NULL); > } > > int mx_lock (struct mutex *mx) > { > if (InterlockedIncrement (&mx->counter) != 1) > WaitForSingleObject (mx->sema, INFINITE); > > return 0; > } > > int mx_trylock (struct mutex *mx) > { > if (InterlockedCompareExchange (&mx->counter, 1, 0 ) != 0) > return 1; > > return 0; > } > > int mx_unlock (struct mutex *mx) > { > if (InterlockedDecrement (&mx->counter)) > ReleaseSemaphore (mx->sema, 1, NULL); > > return 0; > } > > A return value of 0 signals success. > > This code will run on Win98 and NT4 or above. > > Win95 and NT3 are designed to run on a i386 and does not contain an > InterlockedCompareExchange and the Interlocked[Increment|Decrement] are > not thread safe. > > Cygwin avoids this by using inline assembler replacements for > Interlocked[Increment|Decrement|CompareExchange] that are based on xadd > and cmpxchg which requires at least on i486. > > The above implements a fast (deadlocking and not errorchecking) mutex. I > think that this is enough for gcc since this is also the default on Linux. > > Regards, > > Thomas |