Bladeren bron

(re)implement a spinlock in case pthread_spinlock_t is not available.

Cédric Augonnet 16 jaren geleden
bovenliggende
commit
5cdd7aec2f
3 gewijzigde bestanden met toevoegingen van 117 en 1 verwijderingen
  1. 5 1
      configure.ac
  2. 72 0
      src/common/starpu-spinlock.c
  3. 40 0
      src/common/starpu-spinlock.h

+ 5 - 1
configure.ac

@@ -48,10 +48,14 @@ AC_DEFINE_UNQUOTED(STARPUDIR, "$PWD", [location of StarPU sources])
 AC_SUBST(STARPUDIR, $PWD)
 
 AC_SEARCH_LIBS([pthread_create],[pthread],,AC_MSG_ERROR([pthread library unavailable]))
-AC_CHECK_FUNC([pthread_spin_lock], [], AC_MSG_ERROR([pthread_spin_lock is not available]))
 AC_SEARCH_LIBS([sqrt],[m],,AC_MSG_ERROR([math library unavailable]))
 AC_SEARCH_LIBS([sysconf],[c],,AC_MSG_ERROR([sysconf unavailable]))
 
+AC_CHECK_FUNC([pthread_spin_lock], have_pthread_spin_lock=yes, have_pthread_spin_lock=no)
+if test x$have_pthread_spin_lock = xyes; then
+	AC_DEFINE(HAVE_PTHREAD_SPIN_LOCK,[],[pthread_spin_lock is available])
+fi
+
 # yes, that's non portable, but it's still better than sched_setaffinity
 AC_CHECK_FUNC(pthread_setaffinity_np,
 	[], [AC_DEFINE(DONTBIND, [1], [Threads are not bound on a CPU])])

+ 72 - 0
src/common/starpu-spinlock.c

@@ -0,0 +1,72 @@
+/*
+ * StarPU
+ * Copyright (C) INRIA 2008-2009 (see AUTHORS file)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * This program 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 Lesser General Public License in COPYING.LGPL for more details.
+ */
+
+#include <common/starpu-spinlock.h>
+#include <common/config.h>
+
+int starpu_spin_init(starpu_spinlock_t *lock)
+{
+#ifdef HAVE_PTHREAD_SPIN_LOCK
+	return pthread_spin_init(&lock->lock, 0);
+#else
+	lock->taken = 0;
+	return 0;
+#endif
+}
+
+int starpu_spin_destroy(starpu_spinlock_t *lock)
+{
+#ifdef HAVE_PTHREAD_SPIN_LOCK
+	return pthread_spin_destroy(&lock->lock);
+#else
+	/* we don't do anything */
+	return 0;
+#endif
+}
+
+int starpu_spin_lock(starpu_spinlock_t *lock)
+{
+#ifdef HAVE_PTHREAD_SPIN_LOCK
+	return pthread_spin_lock(&lock->lock);
+#else
+	uint32_t prev;
+	do {
+		prev = __sync_lock_test_and_set(&lock->taken, 1);
+	} while (prev);
+	return 0;
+#endif
+}
+
+int starpu_spin_trylock(starpu_spinlock_t *lock)
+{
+#ifdef HAVE_PTHREAD_SPIN_LOCK
+	return pthread_spin_trylock(&lock->lock);
+#else
+	uint32_t prev;
+	prev = __sync_lock_test_and_set(&lock->taken, 1);
+	return (prev == 0)?0:EBUSY;
+#endif
+}
+
+int starpu_spin_unlock(starpu_spinlock_t *lock)
+{
+#ifdef HAVE_PTHREAD_SPIN_LOCK
+	return pthread_spin_unlock(&lock->lock);
+#else
+	lock->taken = 0;
+	return 0;
+#endif
+}

+ 40 - 0
src/common/starpu-spinlock.h

@@ -0,0 +1,40 @@
+/*
+ * StarPU
+ * Copyright (C) INRIA 2008-2009 (see AUTHORS file)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * This program 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 Lesser General Public License in COPYING.LGPL for more details.
+ */
+#ifndef __STARPU_SPINLOCK_H__
+#define __STARPU_SPINLOCK_H__
+
+#include <errno.h>
+#include <stdint.h>
+#include <pthread.h>
+#include <common/config.h>
+
+typedef struct starpu_spinlock_s {
+#ifdef HAVE_PTHREAD_SPIN_LOCK
+	pthread_spinlock_t lock;
+#else
+	/* we only have a trivial implementation yet ! */
+	volatile uint32_t taken __attribute__ ((aligned(16)));
+#endif
+} starpu_spinlock_t;
+
+int starpu_spin_init(starpu_spinlock_t *lock);
+int starpu_spin_destroy(starpu_spinlock_t *lock);
+
+int starpu_spin_lock(starpu_spinlock_t *lock);
+int starpu_spin_trylock(starpu_spinlock_t *lock);
+int starpu_spin_unlock(starpu_spinlock_t *lock);
+
+#endif // __STARPU_SPINLOCK_H__