diff Python/thread_os2.h @ 20782:b1d9029e09d1 legacy-trunk

SF patch #474500: Make OS/2 locks work like posix locks, from Michael Muller.
author Tim Peters <tim.peters@gmail.com>
date Wed, 31 Oct 2001 03:50:45 +0000
parents ebfd87e87884
children 8b116a8449bd
line wrap: on
line diff
--- a/Python/thread_os2.h	Wed Oct 31 03:46:14 2001 +0000
+++ b/Python/thread_os2.h	Wed Oct 31 03:50:45 2001 +0000
@@ -101,82 +101,113 @@
 #endif /* NO_EXIT_PROG */
 
 /*
- * Lock support. It has too be implemented as semaphores.
- * I [Dag] tried to implement it with mutex but I could find a way to
- * tell whether a thread already own the lock or not.
+ * Lock support.  This is implemented with an event semaphore and critical
+ * sections to make it behave more like a posix mutex than its OS/2 
+ # counterparts.
  */
+
+typedef struct os2_lock_t {
+  int is_set;
+  HEV changed;
+} *type_os2_lock;
+
 PyThread_type_lock 
 PyThread_allocate_lock(void)
 {
-  HMTX   aLock;
   APIRET rc;
+  type_os2_lock lock = (type_os2_lock)malloc(sizeof(struct os2_lock_t));
 
   dprintf(("PyThread_allocate_lock called\n"));
   if (!initialized)
     PyThread_init_thread();
 
-  DosCreateMutexSem(NULL,  /* Sem name      */
-                    &aLock, /* the semaphore */
-                    0,     /* shared ?      */
-                    0);    /* initial state */  
+  lock->is_set = 0;
+
+  DosCreateEventSem(NULL, &lock->changed, 0, 0);
 
-  dprintf(("%ld: PyThread_allocate_lock() -> %p\n", PyThread_get_thread_ident(), aLock));
+  dprintf(("%ld: PyThread_allocate_lock() -> %p\n", 
+           PyThread_get_thread_ident(), 
+           lock->changed));
 
-  return (PyThread_type_lock) aLock;
+  return (PyThread_type_lock) lock;
 }
 
 void 
 PyThread_free_lock(PyThread_type_lock aLock)
 {
+  type_os2_lock lock = (type_os2_lock)aLock;
   dprintf(("%ld: PyThread_free_lock(%p) called\n", PyThread_get_thread_ident(),aLock));
 
-  DosCloseMutexSem((HMTX)aLock);
+  DosCloseEventSem(lock->changed);
+  free(aLock);
 }
 
 /*
  * Return 1 on success if the lock was acquired
  *
- * and 0 if the lock was not acquired. This means a 0 is returned
- * if the lock has already been acquired by this thread!
+ * and 0 if the lock was not acquired.
  */
 int 
 PyThread_acquire_lock(PyThread_type_lock aLock, int waitflag)
 {
-  int   success = 1;
-  ULONG rc, count;
+  int   done = 0;
+  ULONG count;
   PID   pid = 0;
   TID   tid = 0;
+  type_os2_lock lock = (type_os2_lock)aLock;
 
   dprintf(("%ld: PyThread_acquire_lock(%p, %d) called\n", PyThread_get_thread_ident(),
            aLock, waitflag));
 
-  DosQueryMutexSem((HMTX)aLock,&pid,&tid,&count);
-  if( tid == PyThread_get_thread_ident() ) { /* if we own this lock */
-    success = 0;
-  } else {
-    rc = DosRequestMutexSem((HMTX) aLock,
-                            (waitflag == 1 ? SEM_INDEFINITE_WAIT : 0));
+  while (!done) {
+    /* if the lock is currently set, we have to wait for the state to change */
+    if (lock->is_set) {
+      if (!waitflag)
+        return 0;
+      DosWaitEventSem(lock->changed, SEM_INDEFINITE_WAIT);
+    }
     
-    if( rc != 0) {
-      success = 0;                /* We failed */
+    /* 
+     * enter a critical section and try to get the semaphore.  If
+     * it is still locked, we will try again.
+     */
+    if (DosEnterCritSec())
+      return 0;
+
+    if (!lock->is_set) {
+      lock->is_set = 1;
+      DosResetEventSem(lock->changed, &count);
+      done = 1;
     }
+
+    DosExitCritSec();
   }
 
-  dprintf(("%ld: PyThread_acquire_lock(%p, %d) -> %d\n",
-           PyThread_get_thread_ident(),aLock, waitflag, success));
-
-  return success;
+  return 1;
 }
 
-void 
-PyThread_release_lock(PyThread_type_lock aLock)
+void PyThread_release_lock(PyThread_type_lock aLock)
 {
+  type_os2_lock lock = (type_os2_lock)aLock;
   dprintf(("%ld: PyThread_release_lock(%p) called\n", PyThread_get_thread_ident(),aLock));
 
-  if ( DosReleaseMutexSem( (HMTX) aLock ) != 0 ) {
+  if (!lock->is_set) {
     dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n",
              PyThread_get_thread_ident(), aLock, GetLastError()));
+    return;
   }
+
+
+  if (DosEnterCritSec()) {
+    dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n",
+             PyThread_get_thread_ident(), aLock, GetLastError()));
+    return;
+  }
+  
+  lock->is_set = 0;
+  DosPostEventSem(lock->changed);
+  
+  DosExitCritSec();
 }
 
 /*