summaryrefslogtreecommitdiff
path: root/lib/librthread/rthread_spin_lock.c
diff options
context:
space:
mode:
authorPaul Irofti <pirofti@cvs.openbsd.org>2012-05-03 09:07:18 +0000
committerPaul Irofti <pirofti@cvs.openbsd.org>2012-05-03 09:07:18 +0000
commite80bf7425576ea69b4d12d80cc8031bf730710f4 (patch)
treeb02022cfbc8a1d7b25b2235814ab4049039afe16 /lib/librthread/rthread_spin_lock.c
parentac991706e149d4917b8169f9cf03311896fb2f30 (diff)
Add pthread spinlock support.
Implementation, documentation and naive regression tests for: - pthread_spin_init() - pthread_spin_destroy() - pthread_spin_lock() - pthread_spin_trylock() - pthread_spin_unlock() Implementation okay guenther@, documentation okay jmc@.
Diffstat (limited to 'lib/librthread/rthread_spin_lock.c')
-rw-r--r--lib/librthread/rthread_spin_lock.c115
1 files changed, 115 insertions, 0 deletions
diff --git a/lib/librthread/rthread_spin_lock.c b/lib/librthread/rthread_spin_lock.c
new file mode 100644
index 00000000000..f89332205ba
--- /dev/null
+++ b/lib/librthread/rthread_spin_lock.c
@@ -0,0 +1,115 @@
+/* $OpenBSD: rthread_spin_lock.c,v 1.1 2012/05/03 09:07:17 pirofti Exp $ */
+/*
+ * Copyright (c) 2012 Paul Irofti <pirofti@openbsd.org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+
+#include <pthread.h>
+
+#include "rthread.h"
+
+int
+pthread_spin_init(pthread_spinlock_t *lock, int pshared)
+{
+ pthread_spinlock_t l = NULL;
+
+ if (lock == NULL) {
+ return (EINVAL);
+ }
+ if (pshared != PTHREAD_PROCESS_PRIVATE) {
+ return (ENOTSUP);
+ }
+
+ l = calloc(1, sizeof *l);
+ if (l == NULL) {
+ return (ENOMEM);
+ }
+ l->lock = _SPINLOCK_UNLOCKED;
+ *lock = l;
+ return (0);
+}
+
+int
+pthread_spin_destroy(pthread_spinlock_t *lock)
+{
+ if (lock == NULL || *lock == NULL) {
+ return (EINVAL);
+ }
+ if ((*lock)->owner != NULL) {
+ return (EBUSY);
+ }
+
+ free(*lock);
+ *lock = NULL;
+ return (0);
+}
+
+int
+pthread_spin_trylock(pthread_spinlock_t *lock)
+{
+ pthread_t self = pthread_self();
+ pthread_spinlock_t l;
+
+ if (lock == NULL || *lock == NULL) {
+ return (EINVAL);
+ }
+ l = *lock;
+ if (l->owner == self) {
+ return (EDEADLK);
+ }
+ if (_atomic_lock(&l->lock)) {
+ return (EBUSY);
+ }
+ l->owner = self;
+ return (0);
+}
+
+int
+pthread_spin_lock(pthread_spinlock_t *lock)
+{
+ pthread_t self = pthread_self();
+ pthread_spinlock_t l;
+
+ if (lock == NULL || *lock == NULL) {
+ return (EINVAL);
+ }
+ l = *lock;
+ if (l->owner == self) {
+ return (EDEADLK);
+ }
+ _spinlock(&l->lock);
+ l->owner = self;
+ return (0);
+}
+
+int
+pthread_spin_unlock(pthread_spinlock_t *lock)
+{
+ pthread_t self = pthread_self();
+ pthread_spinlock_t l;
+
+ if (lock == NULL || *lock == NULL) {
+ return (EINVAL);
+ }
+ l = *lock;
+ if (l->owner != self) {
+ return (EPERM);
+ }
+ l->owner = NULL;
+ _spinunlock(&l->lock);
+ return (0);
+}