--- Modules/_multiprocessing/semaphore.c.orig	Thu Oct 24 19:35:50 2013
+++ Modules/_multiprocessing/semaphore.c	Thu Oct 24 19:38:35 2013
@@ -186,7 +186,107 @@
 
 #else /* !MS_WINDOWS */
 
+#ifdef __OpenBSD__
+
 /*
+ * OpenBSD definitions
+ */
+
+#define SEM_CLEAR_ERROR()
+#define SEM_GET_LAST_ERROR() 0
+#define SEM_CREATE(name, val, max) openbsd_sem_create(val)
+#define SEM_CLOSE(sem) openbsd_sem_close(sem)
+#define SEM_GETVALUE(sem, pval) openbsd_sem_getvalue(sem, pval)
+#define SEM_WAIT(sem) openbsd_sem_wait(sem)
+#define SEM_TRYLOCK(sem) openbsd_sem_trywait(sem)
+#define SEM_TRYWAIT(sem) openbsd_sem_trywait(sem)
+#define SEM_POST(sem) openbsd_sem_post(sem)
+#undef SEM_FAILED
+#define SEM_FAILED (-1)
+#undef HAVE_SEM_UNLINK
+#define SEM_UNLINK(sem) 0
+#undef HAVE_SEM_TIMEDWAIT
+#define SEM_FLAGS (S_IRWXU|S_IRWXG|S_IRWXO)
+
+int
+openbsd_sem_create(int val) {
+	int s, fd;
+	key_t key;
+	char *name = NULL;
+	union semun arg = {
+		.val = val
+	};
+
+	asprintf(&name, "/tmp/tmp.XXXXXXXXXX");
+
+	fd = mkstemp(name);
+	if (fd < 0)
+		goto error;
+	if (chmod(name, SEM_FLAGS) < 0)
+		goto error;
+
+	key = ftok(name, 0);
+	s = semget(key, 1, SEM_FLAGS | IPC_CREAT);
+	if (s < 0)
+		goto error;
+
+	if (semctl(s, 0, SETVAL, arg) < 0)
+		goto error;
+
+	unlink(name);
+	free(name);
+	return s;
+error:
+	unlink(name);
+	free(name);
+	return SEM_FAILED;
+}
+
+void
+openbsd_sem_close(int sem) {
+	union semun arg;
+	semctl(sem, 0, IPC_RMID, arg);
+}
+
+int
+openbsd_sem_trywait(int sem) {
+	struct sembuf buf = {
+		.sem_num = 0,
+		.sem_op  = -1, /* Block until semaphore is 1, then lock */
+		.sem_flg = IPC_NOWAIT
+	};
+	return semop(sem, &buf, 1);
+}
+
+int
+openbsd_sem_wait(int sem) {
+	struct sembuf buf = {
+		.sem_num = 0,
+		.sem_op = -1, /* Block until semaphore is 1, then lock */
+		.sem_flg = 0
+	};
+	return semop(sem, &buf, 1);
+}
+
+int
+openbsd_sem_post(int sem) {
+	struct sembuf buf = {
+		.sem_num = 0,
+		.sem_op = 1, /* Release the semaphore */
+		.sem_flg = 0
+	};
+	return semop(sem, &buf, 1);
+}
+
+void
+openbsd_sem_getvalue(int sem, int *val) {
+	union semun arg;
+	*val = semctl(sem, 0, GETVAL, arg);
+}
+
+#else /* !__OpenBSD__ */
+
+/*
  * Unix definitions
  */
 
@@ -195,8 +295,14 @@
 #define SEM_CREATE(name, val, max) sem_open(name, O_CREAT | O_EXCL, 0600, val)
 #define SEM_CLOSE(sem) sem_close(sem)
 #define SEM_GETVALUE(sem, pval) sem_getvalue(sem, pval)
-#define SEM_UNLINK(name) sem_unlink(name)
+#define SEM_WAIT(sem) sem_wait(sem)
+#define SEM_TRYWAIT(sem) sem_trywait(sem)
+#define SEM_POST(sem) sem_post(sem)
 
+#ifndef SEM_UNLINK
+#	define SEM_UNLINK(name) sem_unlink(name)
+#endif
+
 /* OS X 10.4 defines SEM_FAILED as -1 instead of (sem_t *)-1;  this gives
    compiler warnings, and (potentially) undefined behaviour. */
 #ifdef __APPLE__
@@ -204,15 +310,15 @@
 #  define SEM_FAILED ((sem_t *)-1)
 #endif
 
-#ifndef HAVE_SEM_UNLINK
-#  define sem_unlink(name) 0
+#ifndef SEM_TRYWAIT
+#	define SEM_TRYWAIT(sem) sem_trywait(sem)
 #endif
+#endif
 
 #ifndef HAVE_SEM_TIMEDWAIT
-#  define sem_timedwait(sem,deadline) sem_timedwait_save(sem,deadline,_save)
-
+#define SEM_TIMEDWAIT(sem, deadline) sem_timedwait_save(sem, deadline, _save)
 int
-sem_timedwait_save(sem_t *sem, struct timespec *deadline, PyThreadState *_save)
+sem_timedwait_save(SEM_HANDLE sem, struct timespec *deadline, PyThreadState *_save)
 {
     int res;
     unsigned long delay, difference;
@@ -224,7 +330,7 @@
 
     for (delay = 0 ; ; delay += 1000) {
         /* poll */
-        if (sem_trywait(sem) == 0)
+        if (SEM_TRYWAIT(sem) == 0)
             return 0;
         else if (errno != EAGAIN)
             return MP_STANDARD_ERROR;
@@ -314,11 +420,11 @@
     do {
         Py_BEGIN_ALLOW_THREADS
         if (blocking && timeout_obj == Py_None)
-            res = sem_wait(self->handle);
+            res = SEM_WAIT(self->handle);
         else if (!blocking)
-            res = sem_trywait(self->handle);
+            res = SEM_TRYWAIT(self->handle);
         else
-            res = sem_timedwait(self->handle, &deadline);
+            res = SEM_TIMEDWAIT(self->handle, &deadline);
         Py_END_ALLOW_THREADS
         if (res == MP_EXCEPTION_HAS_BEEN_SET)
             break;
@@ -359,7 +465,7 @@
         /* We will only check properly the maxvalue == 1 case */
         if (self->maxvalue == 1) {
             /* make sure that already locked */
-            if (sem_trywait(self->handle) < 0) {
+            if (SEM_TRYWAIT(self->handle) < 0) {
                 if (errno != EAGAIN) {
                     PyErr_SetFromErrno(PyExc_OSError);
                     return NULL;
@@ -367,7 +473,7 @@
                 /* it is already locked as expected */
             } else {
                 /* it was not locked so undo wait and raise  */
-                if (sem_post(self->handle) < 0) {
+                if (SEM_POST(self->handle) < 0) {
                     PyErr_SetFromErrno(PyExc_OSError);
                     return NULL;
                 }
@@ -382,7 +488,7 @@
 
         /* This check is not an absolute guarantee that the semaphore
            does not rise above maxvalue. */
-        if (sem_getvalue(self->handle, &sval) < 0) {
+        if (SEM_GETVALUE(self->handle, &sval) < 0) {
             return PyErr_SetFromErrno(PyExc_OSError);
         } else if (sval >= self->maxvalue) {
             PyErr_SetString(PyExc_ValueError, "semaphore or lock "
@@ -392,14 +498,14 @@
 #endif
     }
 
-    if (sem_post(self->handle) < 0)
+    if (SEM_POST(self->handle) < 0)
         return PyErr_SetFromErrno(PyExc_OSError);
 
     --self->count;
     Py_RETURN_NONE;
 }
 
-#endif /* !MS_WINDOWS */
+#endif /* !Unix */
 
 /*
  * All platforms
@@ -520,12 +626,12 @@
 semlock_iszero(SemLockObject *self)
 {
 #ifdef HAVE_BROKEN_SEM_GETVALUE
-    if (sem_trywait(self->handle) < 0) {
+    if (SEM_TRYWAIT(self->handle) < 0) {
         if (errno == EAGAIN)
             Py_RETURN_TRUE;
         return mp_SetError(NULL, MP_STANDARD_ERROR);
     } else {
-        if (sem_post(self->handle) < 0)
+        if (SEM_POST(self->handle) < 0)
             return mp_SetError(NULL, MP_STANDARD_ERROR);
         Py_RETURN_FALSE;
     }
