@@ -30,11 +30,113 @@ PERFORMANCE OF THIS SOFTWARE.
3030******************************************************************/
3131
3232/* This code implemented by Dag.Gruneau@elsa.preseco.comm.se */
33+ /* Fast NonRecursiveMutex support by Yakov Markovitch, markovitch@iso.ru */
3334
3435#include <windows.h>
3536#include <limits.h>
3637#include <process.h>
3738
39+ typedef struct NRMUTEX {
40+ LONG owned ;
41+ DWORD thread_id ;
42+ HANDLE hevent ;
43+ } NRMUTEX , * PNRMUTEX ;
44+
45+
46+ typedef PVOID WINAPI interlocked_cmp_xchg_t (PVOID * dest , PVOID exc , PVOID comperand ) ;
47+
48+ /* Sorry mate, but we haven't got InterlockedCompareExchange in Win95! */
49+ static PVOID WINAPI interlocked_cmp_xchg (PVOID * dest , PVOID exc , PVOID comperand )
50+ {
51+ static LONG spinlock = 0 ;
52+ PVOID result ;
53+
54+ /* Acqire spinlock (yielding control to other threads if cant aquire for the moment) */
55+ while (InterlockedExchange (& spinlock , 1 )) Sleep (0 ) ;
56+ result = * dest ;
57+ if (result == comperand )
58+ * dest = exc ;
59+ /* Release spinlock */
60+ spinlock = 0 ;
61+ return result ;
62+ } ;
63+
64+ static interlocked_cmp_xchg_t * ixchg ;
65+ BOOL InitializeNonRecursiveMutex (PNRMUTEX mutex )
66+ {
67+ if (!ixchg )
68+ {
69+ /* Sorely, Win95 has no InterlockedCompareExchange API (Win98 has), so we have to use emulation */
70+ HANDLE kernel = GetModuleHandle ("kernel32.dll" ) ;
71+ if (!kernel || (ixchg = (interlocked_cmp_xchg_t * )GetProcAddress (kernel , "InterlockedCompareExchange" )) == NULL )
72+ ixchg = interlocked_cmp_xchg ;
73+ }
74+
75+ mutex -> owned = -1 ; /* No threads have entered NonRecursiveMutex */
76+ mutex -> thread_id = 0 ;
77+ mutex -> hevent = CreateEvent (NULL , FALSE, FALSE, NULL ) ;
78+ return mutex -> hevent != NULL ; /* TRUE if the mutex is created */
79+ }
80+
81+ #define InterlockedCompareExchange (dest ,exchange ,comperand ) (ixchg((dest), (exchange), (comperand)))
82+
83+ VOID DeleteNonRecursiveMutex (PNRMUTEX mutex )
84+ {
85+ /* No in-use check */
86+ CloseHandle (mutex -> hevent ) ;
87+ mutex -> hevent = NULL ; /* Just in case */
88+ }
89+
90+ DWORD EnterNonRecursiveMutex (PNRMUTEX mutex , BOOL wait )
91+ {
92+ /* Assume that the thread waits successfully */
93+ DWORD ret ;
94+
95+ /* InterlockedIncrement(&mutex->owned) == 0 means that no thread currently owns the mutex */
96+ if (!wait )
97+ {
98+ if (InterlockedCompareExchange ((PVOID * )& mutex -> owned , (PVOID )0 , (PVOID )- 1 ) != (PVOID )- 1 )
99+ return WAIT_TIMEOUT ;
100+ ret = WAIT_OBJECT_0 ;
101+ }
102+ else
103+ ret = InterlockedIncrement (& mutex -> owned ) ?
104+ /* Some thread owns the mutex, let's wait... */
105+ WaitForSingleObject (mutex -> hevent , INFINITE ) : WAIT_OBJECT_0 ;
106+
107+ mutex -> thread_id = GetCurrentThreadId () ; /* We own it */
108+ return ret ;
109+ }
110+
111+ BOOL LeaveNonRecursiveMutex (PNRMUTEX mutex )
112+ {
113+ /* We don't own the mutex */
114+ mutex -> thread_id = 0 ;
115+ return
116+ InterlockedDecrement (& mutex -> owned ) < 0 ||
117+ SetEvent (mutex -> hevent ) ; /* Other threads are waiting, wake one on them up */
118+ }
119+
120+ PNRMUTEX AllocNonRecursiveMutex ()
121+ {
122+ PNRMUTEX mutex = (PNRMUTEX )malloc (sizeof (NRMUTEX )) ;
123+ if (mutex && !InitializeNonRecursiveMutex (mutex ))
124+ {
125+ free (mutex ) ;
126+ mutex = NULL ;
127+ }
128+ return mutex ;
129+ }
130+
131+ void FreeNonRecursiveMutex (PNRMUTEX mutex )
132+ {
133+ if (mutex )
134+ {
135+ DeleteNonRecursiveMutex (mutex ) ;
136+ free (mutex ) ;
137+ }
138+ }
139+
38140long PyThread_get_thread_ident (void );
39141
40142/*
@@ -65,7 +167,7 @@ int PyThread_start_new_thread(void (*func)(void *), void *arg)
65167
66168 if (rv != -1 ) {
67169 success = 1 ;
68- dprintf (("%ld: PyThread_start_new_thread succeeded: %ld\n" , PyThread_get_thread_ident (), rv ));
170+ dprintf (("%ld: PyThread_start_new_thread succeeded: %ld\n" , PyThread_get_thread_ident (), aThreadId ));
69171 }
70172
71173 return success ;
@@ -79,7 +181,7 @@ long PyThread_get_thread_ident(void)
79181{
80182 if (!initialized )
81183 PyThread_init_thread ();
82-
184+
83185 return GetCurrentThreadId ();
84186}
85187
@@ -133,17 +235,13 @@ void PyThread__exit_prog _P1(int status)
133235 */
134236PyThread_type_lock PyThread_allocate_lock (void )
135237{
136- HANDLE aLock ;
238+ PNRMUTEX aLock ;
137239
138240 dprintf (("PyThread_allocate_lock called\n" ));
139241 if (!initialized )
140242 PyThread_init_thread ();
141243
142- aLock = CreateSemaphore (NULL , /* Security attributes */
143- 1 , /* Initial value */
144- 1 , /* Maximum value */
145- NULL );
146- /* Name of semaphore */
244+ aLock = AllocNonRecursiveMutex () ;
147245
148246 dprintf (("%ld: PyThread_allocate_lock() -> %lx\n" , PyThread_get_thread_ident (), (long )aLock ));
149247
@@ -154,7 +252,7 @@ void PyThread_free_lock(PyThread_type_lock aLock)
154252{
155253 dprintf (("%ld: PyThread_free_lock(%lx) called\n" , PyThread_get_thread_ident (),(long )aLock ));
156254
157- CloseHandle (( HANDLE ) aLock );
255+ FreeNonRecursiveMutex ( aLock ) ;
158256}
159257
160258/*
@@ -165,16 +263,11 @@ void PyThread_free_lock(PyThread_type_lock aLock)
165263 */
166264int PyThread_acquire_lock (PyThread_type_lock aLock , int waitflag )
167265{
168- int success = 1 ;
169- DWORD waitResult ;
266+ int success ;
170267
171268 dprintf (("%ld: PyThread_acquire_lock(%lx, %d) called\n" , PyThread_get_thread_ident (),(long )aLock , waitflag ));
172269
173- waitResult = WaitForSingleObject ((HANDLE ) aLock , (waitflag == 1 ? INFINITE : 0 ));
174-
175- if (waitResult != WAIT_OBJECT_0 ) {
176- success = 0 ; /* We failed */
177- }
270+ success = aLock && EnterNonRecursiveMutex ((PNRMUTEX ) aLock , (waitflag == 1 ? INFINITE : 0 )) == WAIT_OBJECT_0 ;
178271
179272 dprintf (("%ld: PyThread_acquire_lock(%lx, %d) -> %d\n" , PyThread_get_thread_ident (),(long )aLock , waitflag , success ));
180273
@@ -185,13 +278,8 @@ void PyThread_release_lock(PyThread_type_lock aLock)
185278{
186279 dprintf (("%ld: PyThread_release_lock(%lx) called\n" , PyThread_get_thread_ident (),(long )aLock ));
187280
188- if (!ReleaseSemaphore (
189- (HANDLE ) aLock , /* Handle of semaphore */
190- 1 , /* increment count by one */
191- NULL )) /* not interested in previous count */
192- {
281+ if (!(aLock && LeaveNonRecursiveMutex ((PNRMUTEX ) aLock )))
193282 dprintf (("%ld: Could not PyThread_release_lock(%lx) error: %l\n" , PyThread_get_thread_ident (), (long )aLock , GetLastError ()));
194- }
195283}
196284
197285/*
@@ -206,9 +294,9 @@ PyThread_type_sema PyThread_allocate_sema(int value)
206294 PyThread_init_thread ();
207295
208296 aSemaphore = CreateSemaphore ( NULL , /* Security attributes */
209- value , /* Initial value */
210- INT_MAX , /* Maximum value */
211- NULL ); /* Name of semaphore */
297+ value , /* Initial value */
298+ INT_MAX , /* Maximum value */
299+ NULL ); /* Name of semaphore */
212300
213301 dprintf (("%ld: PyThread_allocate_sema() -> %lx\n" , PyThread_get_thread_ident (), (long )aSemaphore ));
214302
0 commit comments