aboutsummaryrefslogtreecommitdiff
path: root/compat
diff options
context:
space:
mode:
authorBenjamin Fleischer <fleiben@gmail.com>2013-01-08 14:53:09 +0100
committerBenjamin Fleischer <fleiben@gmail.com>2013-01-08 15:32:57 +0100
commit14581937282486ab7ce057ec79f226181ef1d45d (patch)
tree74dc8d75bcc78d1aae3f17d9975ebd9f0c60767c /compat
parent66458931ddd09fc15244c5ddf3c1ec73e2fd08b9 (diff)
downloadsshfs-14581937282486ab7ce057ec79f226181ef1d45d.tar
sshfs-14581937282486ab7ce057ec79f226181ef1d45d.tar.gz
sshfs-14581937282486ab7ce057ec79f226181ef1d45d.tar.bz2
sshfs-14581937282486ab7ce057ec79f226181ef1d45d.zip
Add unnamed semaphore implementation for Mac OS X
In the past we relied on libosxfuse including a working unnamed semaphore implmentation for Mac OS X. This will not be the case in future releases of OSXFUSE, therefore we need to add our own implementation.
Diffstat (limited to 'compat')
-rw-r--r--compat/darwin_compat.c246
-rw-r--r--compat/darwin_compat.h51
2 files changed, 297 insertions, 0 deletions
diff --git a/compat/darwin_compat.c b/compat/darwin_compat.c
new file mode 100644
index 0000000..3883ec6
--- /dev/null
+++ b/compat/darwin_compat.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2006-2008 Amit Singh/Google Inc.
+ * Copyright (c) 2012 Anatol Pomozov
+ * Copyright (c) 2011-2012 Benjamin Fleischer
+ */
+
+#include "darwin_compat.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <sys/types.h>
+
+/*
+ * Semaphore implementation based on:
+ *
+ * Copyright (C) 2000,02 Free Software Foundation, Inc.
+ * This file is part of the GNU C Library.
+ * Written by Ga<EB>l Le Mignot <address@hidden>
+ *
+ * The GNU C Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * The GNU C Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with the GNU C Library; see the file COPYING.LIB. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* Semaphores */
+
+#define __SEM_ID_NONE ((int)0x0)
+#define __SEM_ID_LOCAL ((int)0xcafef00d)
+
+/* http://www.opengroup.org/onlinepubs/007908799/xsh/sem_init.html */
+int
+darwin_sem_init(darwin_sem_t *sem, int pshared, unsigned int value)
+{
+ if (pshared) {
+ errno = ENOSYS;
+ return -1;
+ }
+
+ sem->id = __SEM_ID_NONE;
+
+ if (pthread_cond_init(&sem->__data.local.count_cond, NULL)) {
+ goto cond_init_fail;
+ }
+
+ if (pthread_mutex_init(&sem->__data.local.count_lock, NULL)) {
+ goto mutex_init_fail;
+ }
+
+ sem->__data.local.count = value;
+ sem->id = __SEM_ID_LOCAL;
+
+ return 0;
+
+mutex_init_fail:
+
+ pthread_cond_destroy(&sem->__data.local.count_cond);
+
+cond_init_fail:
+
+ return -1;
+}
+
+/* http://www.opengroup.org/onlinepubs/007908799/xsh/sem_destroy.html */
+int
+darwin_sem_destroy(darwin_sem_t *sem)
+{
+ int res = 0;
+
+ pthread_mutex_lock(&sem->__data.local.count_lock);
+
+ sem->id = __SEM_ID_NONE;
+ pthread_cond_broadcast(&sem->__data.local.count_cond);
+
+ if (pthread_cond_destroy(&sem->__data.local.count_cond)) {
+ res = -1;
+ }
+
+ pthread_mutex_unlock(&sem->__data.local.count_lock);
+
+ if (pthread_mutex_destroy(&sem->__data.local.count_lock)) {
+ res = -1;
+ }
+
+ return res;
+}
+
+int
+darwin_sem_getvalue(darwin_sem_t *sem, unsigned int *sval)
+{
+ int res = 0;
+
+ pthread_mutex_lock(&sem->__data.local.count_lock);
+
+ if (sem->id != __SEM_ID_LOCAL) {
+ res = -1;
+ errno = EINVAL;
+ } else {
+ *sval = sem->__data.local.count;
+ }
+
+ pthread_mutex_unlock(&sem->__data.local.count_lock);
+
+ return res;
+}
+
+/* http://www.opengroup.org/onlinepubs/007908799/xsh/sem_post.html */
+int
+darwin_sem_post(darwin_sem_t *sem)
+{
+ int res = 0;
+
+ pthread_mutex_lock(&sem->__data.local.count_lock);
+
+ if (sem->id != __SEM_ID_LOCAL) {
+ res = -1;
+ errno = EINVAL;
+ } else if (sem->__data.local.count < DARWIN_SEM_VALUE_MAX) {
+ sem->__data.local.count++;
+ if (sem->__data.local.count == 1) {
+ pthread_cond_signal(&sem->__data.local.count_cond);
+ }
+ } else {
+ errno = ERANGE;
+ res = -1;
+ }
+
+ pthread_mutex_unlock(&sem->__data.local.count_lock);
+
+ return res;
+}
+
+/* http://www.opengroup.org/onlinepubs/009695399/functions/sem_timedwait.html */
+int
+darwin_sem_timedwait(darwin_sem_t *sem, const struct timespec *abs_timeout)
+{
+ int res = 0;
+
+ if (abs_timeout &&
+ (abs_timeout->tv_nsec < 0 || abs_timeout->tv_nsec >= 1000000000)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ pthread_cleanup_push((void(*)(void*))&pthread_mutex_unlock,
+ &sem->__data.local.count_lock);
+
+ pthread_mutex_lock(&sem->__data.local.count_lock);
+
+ if (sem->id != __SEM_ID_LOCAL) {
+ errno = EINVAL;
+ res = -1;
+ } else {
+ if (!sem->__data.local.count) {
+ res = pthread_cond_timedwait(&sem->__data.local.count_cond,
+ &sem->__data.local.count_lock,
+ abs_timeout);
+ }
+ if (res) {
+ assert(res == ETIMEDOUT);
+ res = -1;
+ errno = ETIMEDOUT;
+ } else if (sem->id != __SEM_ID_LOCAL) {
+ res = -1;
+ errno = EINVAL;
+ } else {
+ sem->__data.local.count--;
+ }
+ }
+
+ pthread_cleanup_pop(1);
+
+ return res;
+}
+
+/* http://www.opengroup.org/onlinepubs/007908799/xsh/sem_trywait.html */
+int
+darwin_sem_trywait(darwin_sem_t *sem)
+{
+ int res = 0;
+
+ pthread_mutex_lock(&sem->__data.local.count_lock);
+
+ if (sem->id != __SEM_ID_LOCAL) {
+ res = -1;
+ errno = EINVAL;
+ } else if (sem->__data.local.count) {
+ sem->__data.local.count--;
+ } else {
+ res = -1;
+ errno = EAGAIN;
+ }
+
+ pthread_mutex_unlock (&sem->__data.local.count_lock);
+
+ return res;
+}
+
+/* http://www.opengroup.org/onlinepubs/007908799/xsh/sem_wait.html */
+int
+darwin_sem_wait(darwin_sem_t *sem)
+{
+ int res = 0;
+
+ pthread_cleanup_push((void(*)(void*))&pthread_mutex_unlock,
+ &sem->__data.local.count_lock);
+
+ pthread_mutex_lock(&sem->__data.local.count_lock);
+
+ if (sem->id != __SEM_ID_LOCAL) {
+ errno = EINVAL;
+ res = -1;
+ } else {
+ if (!sem->__data.local.count) {
+ pthread_cond_wait(&sem->__data.local.count_cond,
+ &sem->__data.local.count_lock);
+ if (!sem->__data.local.count) {
+ /* spurious wakeup, assume it is an interruption */
+ res = -1;
+ errno = EINTR;
+ goto out;
+ }
+ }
+ if (sem->id != __SEM_ID_LOCAL) {
+ res = -1;
+ errno = EINVAL;
+ } else {
+ sem->__data.local.count--;
+ }
+ }
+
+out:
+ pthread_cleanup_pop(1);
+
+ return res;
+}
diff --git a/compat/darwin_compat.h b/compat/darwin_compat.h
new file mode 100644
index 0000000..1cdbcce
--- /dev/null
+++ b/compat/darwin_compat.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2006-2008 Amit Singh/Google Inc.
+ * Copyright (c) 2011-2012 Benjamin Fleischer
+ */
+
+#ifndef _DARWIN_COMPAT_
+#define _DARWIN_COMPAT_
+
+#include <pthread.h>
+
+/* Semaphores */
+
+struct __local_sem_t
+{
+ unsigned int count;
+ pthread_mutex_t count_lock;
+ pthread_cond_t count_cond;
+};
+
+typedef struct fuse_sem {
+ int id;
+ union {
+ struct __local_sem_t local;
+ } __data;
+} darwin_sem_t;
+
+#define DARWIN_SEM_VALUE_MAX ((int32_t)32767)
+
+int darwin_sem_init(darwin_sem_t *sem, int pshared, unsigned int value);
+int darwin_sem_destroy(darwin_sem_t *sem);
+int darwin_sem_getvalue(darwin_sem_t *sem, unsigned int *value);
+int darwin_sem_post(darwin_sem_t *sem);
+int darwin_sem_timedwait(darwin_sem_t *sem, const struct timespec *abs_timeout);
+int darwin_sem_trywait(darwin_sem_t *sem);
+int darwin_sem_wait(darwin_sem_t *sem);
+
+/* Caller must not include <semaphore.h> */
+
+typedef darwin_sem_t sem_t;
+
+#define sem_init(s, p, v) darwin_sem_init(s, p, v)
+#define sem_destroy(s) darwin_sem_destroy(s)
+#define sem_getvalue(s, v) darwin_sem_getvalue(s, v)
+#define sem_post(s) darwin_sem_post(s)
+#define sem_timedwait(s, t) darwin_sem_timedwait(s, t)
+#define sem_trywait(s) darwin_sem_trywait(s)
+#define sem_wait(s) darwin_sem_wait(s)
+
+#define SEM_VALUE_MAX DARWIN_SEM_VALUE_MAX
+
+#endif /* _DARWIN_COMPAT_ */