@@ -101,82 +101,113 @@ PyThread__exit_prog(int status)
101101#endif /* NO_EXIT_PROG */
102102
103103/*
104- * Lock support. It has too be implemented as semaphores.
105- * I [Dag] tried to implement it with mutex but I could find a way to
106- * tell whether a thread already own the lock or not .
104+ * Lock support. This is implemented with an event semaphore and critical
105+ * sections to make it behave more like a posix mutex than its OS/2
106+ # counterparts .
107107 */
108+
109+ typedef struct os2_lock_t {
110+ int is_set ;
111+ HEV changed ;
112+ } * type_os2_lock ;
113+
108114PyThread_type_lock
109115PyThread_allocate_lock (void )
110116{
111- HMTX aLock ;
112117 APIRET rc ;
118+ type_os2_lock lock = (type_os2_lock )malloc (sizeof (struct os2_lock_t ));
113119
114120 dprintf (("PyThread_allocate_lock called\n" ));
115121 if (!initialized )
116122 PyThread_init_thread ();
117123
118- DosCreateMutexSem (NULL , /* Sem name */
119- & aLock , /* the semaphore */
120- 0 , /* shared ? */
121- 0 ); /* initial state */
124+ lock -> is_set = 0 ;
122125
123- dprintf (( "%ld: PyThread_allocate_lock() -> %p\n" , PyThread_get_thread_ident (), aLock ) );
126+ DosCreateEventSem ( NULL , & lock -> changed , 0 , 0 );
124127
125- return (PyThread_type_lock ) aLock ;
128+ dprintf (("%ld: PyThread_allocate_lock() -> %p\n" ,
129+ PyThread_get_thread_ident (),
130+ lock -> changed ));
131+
132+ return (PyThread_type_lock ) lock ;
126133}
127134
128135void
129136PyThread_free_lock (PyThread_type_lock aLock )
130137{
138+ type_os2_lock lock = (type_os2_lock )aLock ;
131139 dprintf (("%ld: PyThread_free_lock(%p) called\n" , PyThread_get_thread_ident (),aLock ));
132140
133- DosCloseMutexSem ((HMTX )aLock );
141+ DosCloseEventSem (lock -> changed );
142+ free (aLock );
134143}
135144
136145/*
137146 * Return 1 on success if the lock was acquired
138147 *
139- * and 0 if the lock was not acquired. This means a 0 is returned
140- * if the lock has already been acquired by this thread!
148+ * and 0 if the lock was not acquired.
141149 */
142150int
143151PyThread_acquire_lock (PyThread_type_lock aLock , int waitflag )
144152{
145- int success = 1 ;
146- ULONG rc , count ;
153+ int done = 0 ;
154+ ULONG count ;
147155 PID pid = 0 ;
148156 TID tid = 0 ;
157+ type_os2_lock lock = (type_os2_lock )aLock ;
149158
150159 dprintf (("%ld: PyThread_acquire_lock(%p, %d) called\n" , PyThread_get_thread_ident (),
151160 aLock , waitflag ));
152161
153- DosQueryMutexSem ((HMTX )aLock ,& pid ,& tid ,& count );
154- if ( tid == PyThread_get_thread_ident () ) { /* if we own this lock */
155- success = 0 ;
156- } else {
157- rc = DosRequestMutexSem ((HMTX ) aLock ,
158- (waitflag == 1 ? SEM_INDEFINITE_WAIT : 0 ));
162+ while (!done ) {
163+ /* if the lock is currently set, we have to wait for the state to change */
164+ if (lock -> is_set ) {
165+ if (!waitflag )
166+ return 0 ;
167+ DosWaitEventSem (lock -> changed , SEM_INDEFINITE_WAIT );
168+ }
159169
160- if ( rc != 0 ) {
161- success = 0 ; /* We failed */
170+ /*
171+ * enter a critical section and try to get the semaphore. If
172+ * it is still locked, we will try again.
173+ */
174+ if (DosEnterCritSec ())
175+ return 0 ;
176+
177+ if (!lock -> is_set ) {
178+ lock -> is_set = 1 ;
179+ DosResetEventSem (lock -> changed , & count );
180+ done = 1 ;
162181 }
163- }
164182
165- dprintf (( "%ld: PyThread_acquire_lock(%p, %d) -> %d\n" ,
166- PyThread_get_thread_ident (), aLock , waitflag , success ));
183+ DosExitCritSec ();
184+ }
167185
168- return success ;
186+ return 1 ;
169187}
170188
171- void
172- PyThread_release_lock (PyThread_type_lock aLock )
189+ void PyThread_release_lock (PyThread_type_lock aLock )
173190{
191+ type_os2_lock lock = (type_os2_lock )aLock ;
174192 dprintf (("%ld: PyThread_release_lock(%p) called\n" , PyThread_get_thread_ident (),aLock ));
175193
176- if ( DosReleaseMutexSem ( (HMTX ) aLock ) != 0 ) {
194+ if (!lock -> is_set ) {
195+ dprintf (("%ld: Could not PyThread_release_lock(%p) error: %l\n" ,
196+ PyThread_get_thread_ident (), aLock , GetLastError ()));
197+ return ;
198+ }
199+
200+
201+ if (DosEnterCritSec ()) {
177202 dprintf (("%ld: Could not PyThread_release_lock(%p) error: %l\n" ,
178203 PyThread_get_thread_ident (), aLock , GetLastError ()));
204+ return ;
179205 }
206+
207+ lock -> is_set = 0 ;
208+ DosPostEventSem (lock -> changed );
209+
210+ DosExitCritSec ();
180211}
181212
182213/*
0 commit comments