[pypy-svn] r16217 - in pypy/dist/pypy/translator/c: . src test

arigo at codespeak.net arigo at codespeak.net
Mon Aug 22 17:44:42 CEST 2005


Author: arigo
Date: Mon Aug 22 17:44:40 2005
New Revision: 16217

Modified:
   pypy/dist/pypy/translator/c/extfunc.py
   pypy/dist/pypy/translator/c/src/ll_thread.h
   pypy/dist/pypy/translator/c/src/thread_nt.h
   pypy/dist/pypy/translator/c/src/thread_pthread.h
   pypy/dist/pypy/translator/c/test/test_extfunc.py
Log:
(rxe, arigo)

genc: acquire() and release() methods of locks.

(thread_nt is still untested)



Modified: pypy/dist/pypy/translator/c/extfunc.py
==============================================================================
--- pypy/dist/pypy/translator/c/extfunc.py	(original)
+++ pypy/dist/pypy/translator/c/extfunc.py	Mon Aug 22 17:44:40 2005
@@ -36,7 +36,9 @@
         'LL_strtod_parts_to_float',
     ll_strtod.ll_strtod_formatd:
         'LL_strtod_formatd',
-    ll_thread.ll_newlock:  'LL_thread_newlock',
+    ll_thread.ll_newlock:     'LL_thread_newlock',
+    ll_thread.ll_acquirelock: 'LL_thread_acquirelock',
+    ll_thread.ll_releaselock: 'LL_thread_releaselock',
     }
 
 #______________________________________________________

Modified: pypy/dist/pypy/translator/c/src/ll_thread.h
==============================================================================
--- pypy/dist/pypy/translator/c/src/ll_thread.h	(original)
+++ pypy/dist/pypy/translator/c/src/ll_thread.h	Mon Aug 22 17:44:40 2005
@@ -15,3 +15,23 @@
 	if (!RPyThreadLockInit(lock))
 		RPyRaiseSimpleException(PyExc_thread_error, "out of resources");
 }
+
+int LL_thread_acquirelock(struct RPyOpaque_ThreadLock *lock, int waitflag)
+{
+	return RPyThreadAcquireLock(lock, waitflag);
+}
+
+void LL_thread_releaselock(struct RPyOpaque_ThreadLock *lock)
+{
+	/* XXX this code is only quasi-thread-safe because the GIL is held
+	       across its whole execution! */
+
+	/* Sanity check: the lock must be locked */
+	if (RPyThreadAcquireLock(lock, 0)) {
+		RPyThreadReleaseLock(lock);
+		RPyRaiseSimpleException(PyExc_thread_error, "bad lock");
+	}
+	else {
+		RPyThreadReleaseLock(lock);
+	}
+}

Modified: pypy/dist/pypy/translator/c/src/thread_nt.h
==============================================================================
--- pypy/dist/pypy/translator/c/src/thread_nt.h	(original)
+++ pypy/dist/pypy/translator/c/src/thread_nt.h	Mon Aug 22 17:44:40 2005
@@ -123,3 +123,20 @@
 	if (lock->hevent != NULL)
 		DeleteNonRecursiveMutex(lock);
 }
+
+/*
+ * 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!
+ */
+int RPyThreadAcquireLock(struct RPyOpaque_ThreadLock *lock, int waitflag)
+{
+	return EnterNonRecursiveMutex(lock, (waitflag != 0 ? INFINITE : 0)) == WAIT_OBJECT_0;
+}
+
+void RPyThreadReleaseLock(struct RPyOpaque_ThreadLock *lock)
+{
+	if (!LeaveNonRecursiveMutex(lock))
+		/* XXX complain? */;
+}

Modified: pypy/dist/pypy/translator/c/src/thread_pthread.h
==============================================================================
--- pypy/dist/pypy/translator/c/src/thread_pthread.h	(original)
+++ pypy/dist/pypy/translator/c/src/thread_pthread.h	Mon Aug 22 17:44:40 2005
@@ -74,6 +74,50 @@
 	}
 }
 
+/*
+ * As of February 2002, Cygwin thread implementations mistakenly report error
+ * codes in the return value of the sem_ calls (like the pthread_ functions).
+ * Correct implementations return -1 and put the code in errno. This supports
+ * either.
+ */
+static int
+rpythread_fix_status(int status)
+{
+	return (status == -1) ? errno : status;
+}
+
+int RPyThreadAcquireLock(struct RPyOpaque_ThreadLock *lock, int waitflag)
+{
+	int success;
+	sem_t *thelock = &lock->sem;
+	int status, error = 0;
+
+	do {
+		if (waitflag)
+			status = rpythread_fix_status(sem_wait(thelock));
+		else
+			status = rpythread_fix_status(sem_trywait(thelock));
+	} while (status == EINTR); /* Retry if interrupted by a signal */
+
+	if (waitflag) {
+		CHECK_STATUS("sem_wait");
+	} else if (status != EAGAIN) {
+		CHECK_STATUS("sem_trywait");
+	}
+	
+	success = (status == 0) ? 1 : 0;
+	return success;
+}
+
+void RPyThreadReleaseLock(struct RPyOpaque_ThreadLock *lock)
+{
+	sem_t *thelock = &lock->sem;
+	int status, error = 0;
+
+	status = sem_post(thelock);
+	CHECK_STATUS("sem_post");
+}
+
 /************************************************************/
 #else                                      /* no semaphores */
 /************************************************************/
@@ -124,6 +168,52 @@
 	}
 }
 
+int RPyThreadAcquireLock(struct RPyOpaque_ThreadLock *lock, int waitflag)
+{
+	int success;
+	int status, error = 0;
+
+	status = pthread_mutex_lock( &lock->mut );
+	CHECK_STATUS("pthread_mutex_lock[1]");
+	success = lock->locked == 0;
+
+	if ( !success && waitflag ) {
+		/* continue trying until we get the lock */
+
+		/* mut must be locked by me -- part of the condition
+		 * protocol */
+		while ( lock->locked ) {
+			status = pthread_cond_wait(&lock->lock_released,
+						   &lock->mut);
+			CHECK_STATUS("pthread_cond_wait");
+		}
+		success = 1;
+	}
+	if (success) lock->locked = 1;
+	status = pthread_mutex_unlock( &lock->mut );
+	CHECK_STATUS("pthread_mutex_unlock[1]");
+
+	if (error) success = 0;
+	return success;
+}
+
+void RPyThreadReleaseLock(struct RPyOpaque_ThreadLock *lock)
+{
+	int status, error = 0;
+
+	status = pthread_mutex_lock( &lock->mut );
+	CHECK_STATUS("pthread_mutex_lock[3]");
+
+	lock->locked = 0;
+
+	status = pthread_mutex_unlock( &lock->mut );
+	CHECK_STATUS("pthread_mutex_unlock[3]");
+
+	/* wake up someone (anyone, if any) waiting on the lock */
+	status = pthread_cond_signal( &lock->lock_released );
+	CHECK_STATUS("pthread_cond_signal");
+}
+
 /************************************************************/
 #endif                                     /* no semaphores */
 /************************************************************/

Modified: pypy/dist/pypy/translator/c/test/test_extfunc.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_extfunc.py	(original)
+++ pypy/dist/pypy/translator/c/test/test_extfunc.py	Mon Aug 22 17:44:40 2005
@@ -308,12 +308,16 @@
     import pypy.module.thread.rpython.exttable   # for declare()/declaretype()
     def fn():
         l = thread.allocate_lock()
-        #ok1 = l.acquire(True)
-        #ok2 = l.acquire(False)
-        #l.release()
-        #ok3 = l.acquire(False)
-        #return ok1 and not ok2 and ok3
-        return True
+        ok1 = l.acquire(True)
+        ok2 = l.acquire(False)
+        l.release()
+        ok2_and_a_half = False
+        try:
+            l.release()
+        except thread.error:
+            ok2_and_a_half = True
+        ok3 = l.acquire(False)
+        return ok1 and not ok2 and ok2_and_a_half and ok3
     f = compile(fn, [])
     res = f()
     assert res is True



More information about the Pypy-commit mailing list