Skip to content

Commit a6ca4f4

Browse files
committed
SF patch #474500: Make OS/2 locks work like posix locks, from Michael
Muller.
1 parent 7e0f81e commit a6ca4f4

2 files changed

Lines changed: 62 additions & 30 deletions

File tree

Misc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@ The Dragon De Monsyne
297297
Skip Montanaro
298298
Sape Mullender
299299
Sjoerd Mullender
300+
Michael Muller
300301
Takahiro Nakayama
301302
Travers Naran
302303
Fredrik Nehr

Python/thread_os2.h

Lines changed: 61 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
108114
PyThread_type_lock
109115
PyThread_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

128135
void
129136
PyThread_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
*/
142150
int
143151
PyThread_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

Comments
 (0)