summaryrefslogtreecommitdiffstats
path: root/lib/librthread/rthread.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/librthread/rthread.c')
-rw-r--r--lib/librthread/rthread.c59
1 files changed, 44 insertions, 15 deletions
diff --git a/lib/librthread/rthread.c b/lib/librthread/rthread.c
index 49b4f1ddd14..3a2e6bf55b2 100644
--- a/lib/librthread/rthread.c
+++ b/lib/librthread/rthread.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rthread.c,v 1.69 2013/04/06 04:25:01 tedu Exp $ */
+/* $OpenBSD: rthread.c,v 1.70 2013/06/01 20:47:40 tedu Exp $ */
/*
* Copyright (c) 2004,2005 Ted Unangst <tedu@openbsd.org>
* All Rights Reserved.
@@ -49,13 +49,15 @@
static int concurrency_level; /* not used */
+struct _spinlock _SPINLOCK_UNLOCKED_ASSIGN = _SPINLOCK_UNLOCKED;
+
int _threads_ready;
size_t _thread_pagesize;
struct listhead _thread_list = LIST_HEAD_INITIALIZER(_thread_list);
-_spinlock_lock_t _thread_lock = _SPINLOCK_UNLOCKED;
+struct _spinlock _thread_lock = _SPINLOCK_UNLOCKED;
static struct pthread_queue _thread_gc_list
= TAILQ_HEAD_INITIALIZER(_thread_gc_list);
-static _spinlock_lock_t _thread_gc_lock = _SPINLOCK_UNLOCKED;
+static struct _spinlock _thread_gc_lock = _SPINLOCK_UNLOCKED;
struct pthread _initial_thread;
struct thread_control_block _initial_thread_tcb;
@@ -78,18 +80,45 @@ struct pthread_attr _rthread_attr_default = {
* internal support functions
*/
void
-_spinlock(_spinlock_lock_t *lock)
+_spinlock(volatile struct _spinlock *lock)
{
+ uint32_t me;
- while (_atomic_lock(lock))
+ while (_atomic_lock(&lock->atomiclock))
sched_yield();
+ me = lock->waiter++;
+ lock->atomiclock = _ATOMIC_LOCK_UNLOCKED;
+ while (me != lock->ready) {
+ if (me < lock->ready) {
+ _rthread_debug(0, "SPINLOCK FAIL: %d %d\n",
+ me, lock->ready);
+ _exit(1);
+ }
+ if (me > lock->ready + 1)
+ sched_yield();
+ }
}
-void
-_spinunlock(_spinlock_lock_t *lock)
+int
+_spinlocktry(volatile struct _spinlock *lock)
{
+ int gotit = 0;
+
+ while (_atomic_lock(&lock->atomiclock))
+ sched_yield();
+ if (lock->waiter == lock->ready) {
+ lock->waiter++;
+ gotit = 1;
+ }
+ lock->atomiclock = _ATOMIC_LOCK_UNLOCKED;
+
+ return gotit;
+}
- *lock = _SPINLOCK_UNLOCKED;
+void
+_spinunlock(volatile struct _spinlock *lock)
+{
+ lock->ready++;
}
/*
@@ -164,9 +193,9 @@ _rthread_init(void)
struct sigaction sa;
thread->tid = getthrid();
- thread->donesem.lock = _SPINLOCK_UNLOCKED;
+ thread->donesem.lock = _SPINLOCK_UNLOCKED_ASSIGN;
thread->flags |= THREAD_CANCEL_ENABLE|THREAD_CANCEL_DEFERRED;
- thread->flags_lock = _SPINLOCK_UNLOCKED;
+ thread->flags_lock = _SPINLOCK_UNLOCKED_ASSIGN;
strlcpy(thread->name, "Main process", sizeof(thread->name));
LIST_INSERT_HEAD(&_thread_list, thread, threads);
_rthread_debug_init();
@@ -403,8 +432,8 @@ pthread_create(pthread_t *threadp, const pthread_attr_t *attr,
thread = calloc(1, sizeof(*thread));
if (!thread)
return (errno);
- thread->donesem.lock = _SPINLOCK_UNLOCKED;
- thread->flags_lock = _SPINLOCK_UNLOCKED;
+ thread->donesem.lock = _SPINLOCK_UNLOCKED_ASSIGN;
+ thread->flags_lock = _SPINLOCK_UNLOCKED_ASSIGN;
thread->fn = start_routine;
thread->arg = arg;
thread->tid = -1;
@@ -603,7 +632,7 @@ _thread_dump_info(void)
void
_rthread_dl_lock(int what)
{
- static _spinlock_lock_t lock = _SPINLOCK_UNLOCKED;
+ static struct _spinlock lock = _SPINLOCK_UNLOCKED;
static pthread_t owner = NULL;
static struct pthread_queue lockers = TAILQ_HEAD_INITIALIZER(lockers);
static int count = 0;
@@ -619,7 +648,7 @@ _rthread_dl_lock(int what)
} else if (owner != self) {
TAILQ_INSERT_TAIL(&lockers, self, waiting);
while (owner != self) {
- __thrsleep(self, 0, NULL, &lock, NULL);
+ __thrsleep(self, 0 | 0x8, NULL, &lock.ready, NULL);
_spinlock(&lock);
}
}
@@ -646,7 +675,7 @@ _rthread_dl_lock(int what)
void
_rthread_bind_lock(int what)
{
- static _spinlock_lock_t lock = _SPINLOCK_UNLOCKED;
+ static struct _spinlock lock = _SPINLOCK_UNLOCKED;
if (what == 0)
_spinlock(&lock);