Patch #525532: Add support for POSIX semaphores.
diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h
index 6e92128..56aec44 100644
--- a/Python/thread_pthread.h
+++ b/Python/thread_pthread.h
@@ -11,6 +11,10 @@
 #undef destructor
 #endif
 #include <signal.h>
+#ifdef _POSIX_SEMAPHORES
+#include <semaphore.h>
+#include <errno.h>
+#endif
 
 
 /* try to determine what version of the Pthread Standard is installed.
@@ -76,6 +80,16 @@
 #endif
 
 
+/* Whether or not to use semaphores directly rather than emulating them with
+ * mutexes and condition variables:
+ */
+#ifdef _POSIX_SEMAPHORES
+#  define USE_SEMAPHORES
+#else
+#  undef USE_SEMAPHORES
+#endif
+
+
 /* On platforms that don't use standard POSIX threads pthread_sigmask()
  * isn't present.  DEC threads uses sigprocmask() instead as do most
  * other UNIX International compliant systems that don't have the full
@@ -294,6 +308,109 @@
 }
 #endif /* NO_EXIT_PROG */
 
+#ifdef USE_SEMAPHORES
+
+/*
+ * Lock support.
+ */
+
+PyThread_type_lock 
+PyThread_allocate_lock(void)
+{
+	sem_t *lock;
+	int status, error = 0;
+
+	dprintf(("PyThread_allocate_lock called\n"));
+	if (!initialized)
+		PyThread_init_thread();
+
+	lock = (sem_t *)malloc(sizeof(sem_t));
+
+	if (lock) {
+		status = sem_init(lock,0,1);
+		CHECK_STATUS("sem_init");
+
+		if (error) {
+			free((void *)lock);
+			lock = NULL;
+		}
+	}
+
+	dprintf(("PyThread_allocate_lock() -> %p\n", lock));
+	return (PyThread_type_lock)lock;
+}
+
+void 
+PyThread_free_lock(PyThread_type_lock lock)
+{
+	sem_t *thelock = (sem_t *)lock;
+	int status, error = 0;
+
+	dprintf(("PyThread_free_lock(%p) called\n", lock));
+
+	if (!thelock)
+		return;
+
+	status = sem_destroy(thelock);
+	CHECK_STATUS("sem_destroy");
+
+	free((void *)thelock);
+}
+
+/*
+ * 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
+fix_status(int status)
+{
+	return (status == -1) ? errno : status;
+}
+
+int 
+PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
+{
+	int success;
+	sem_t *thelock = (sem_t *)lock;
+	int status, error = 0;
+
+	dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
+
+	do {
+		if (waitflag)
+			status = fix_status(sem_wait(thelock));
+		else
+			status = 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;
+
+	dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
+	return success;
+}
+
+void 
+PyThread_release_lock(PyThread_type_lock lock)
+{
+	sem_t *thelock = (sem_t *)lock;
+	int status, error = 0;
+
+	dprintf(("PyThread_release_lock(%p) called\n", lock));
+
+	status = sem_post(thelock);
+	CHECK_STATUS("sem_post");
+}
+
+#else /* USE_SEMAPHORES */
+
 /*
  * Lock support.
  */
@@ -405,3 +522,5 @@
 	status = pthread_cond_signal( &thelock->lock_released );
 	CHECK_STATUS("pthread_cond_signal");
 }
+
+#endif /* USE_SEMAPHORES */