thr_pspinlock.c revision 149691
1266733Speter/*- 2266733Speter * Copyright (c) 2003 David Xu <davidxu@freebsd.org> 3266733Speter * All rights reserved. 4266733Speter * 5266733Speter * Redistribution and use in source and binary forms, with or without 6266733Speter * modification, are permitted provided that the following conditions 7266733Speter * are met: 8266733Speter * 1. Redistributions of source code must retain the above copyright 9266733Speter * notice, this list of conditions and the following disclaimer. 10266733Speter * 2. Redistributions in binary form must reproduce the above copyright 11266733Speter * notice, this list of conditions and the following disclaimer in the 12266733Speter * documentation and/or other materials provided with the distribution. 13266733Speter * 14266733Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15266733Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16266733Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17266733Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18266733Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19266733Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20266733Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21266733Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22266733Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23266733Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24266733Speter * SUCH DAMAGE. 25266733Speter * 26266733Speter * $FreeBSD: head/lib/libkse/thread/thr_pspinlock.c 149691 2005-09-01 15:21:23Z stefanf $ 27266733Speter */ 28266733Speter 29266733Speter#include <sys/types.h> 30266733Speter#include <errno.h> 31266733Speter#include <pthread.h> 32266733Speter#include <stdint.h> 33266733Speter#include <stdlib.h> 34266733Speter 35266733Speter#include "atomic_ops.h" 36266733Speter#include "thr_private.h" 37266733Speter 38266733Speter#define SPIN_COUNT 10000 39266733Speter 40266733Speter__weak_reference(_pthread_spin_init, pthread_spin_init); 41266733Speter__weak_reference(_pthread_spin_destroy, pthread_spin_destroy); 42266733Speter__weak_reference(_pthread_spin_trylock, pthread_spin_trylock); 43266733Speter__weak_reference(_pthread_spin_lock, pthread_spin_lock); 44266733Speter__weak_reference(_pthread_spin_unlock, pthread_spin_unlock); 45266733Speter 46266733Speterint 47266733Speter_pthread_spin_init(pthread_spinlock_t *lock, int pshared) 48266733Speter{ 49266733Speter struct pthread_spinlock *lck; 50266733Speter int ret; 51266733Speter 52266733Speter if (lock == NULL || pshared != PTHREAD_PROCESS_PRIVATE) 53266733Speter ret = EINVAL; 54266733Speter else if ((lck = malloc(sizeof(struct pthread_spinlock))) == NULL) 55266733Speter ret = ENOMEM; 56266733Speter else { 57266733Speter lck->s_lock = 0; 58266733Speter lck->s_owner= NULL; 59266733Speter *lock = lck; 60266733Speter ret = 0; 61266733Speter } 62266733Speter 63266733Speter return (ret); 64266733Speter} 65266733Speter 66266733Speterint 67266733Speter_pthread_spin_destroy(pthread_spinlock_t *lock) 68266733Speter{ 69266733Speter int ret; 70266733Speter 71266733Speter if (lock == NULL || *lock == NULL) 72266733Speter ret = EINVAL; 73266733Speter else if ((*lock)->s_owner != NULL) 74266733Speter ret = EBUSY; 75266733Speter else { 76266733Speter free(*lock); 77266733Speter *lock = NULL; 78266733Speter ret = 0; 79266733Speter } 80266733Speter 81266733Speter return (ret); 82266733Speter} 83266733Speter 84266733Speterint 85266733Speter_pthread_spin_trylock(pthread_spinlock_t *lock) 86266733Speter{ 87266733Speter struct pthread_spinlock *lck; 88266733Speter struct pthread *self = _pthread_self(); 89266733Speter int oldval, ret; 90266733Speter 91266733Speter if (lock == NULL || (lck = *lock) == NULL) 92266733Speter ret = EINVAL; 93266733Speter else if (lck->s_owner == self) 94266733Speter ret = EDEADLK; 95266733Speter else if (lck->s_lock != 0) 96266733Speter ret = EBUSY; 97266733Speter else { 98266733Speter atomic_swap_int((int *)&(lck)->s_lock, 1, &oldval); 99266733Speter if (oldval) 100266733Speter ret = EBUSY; 101266733Speter else { 102266733Speter lck->s_owner = _pthread_self(); 103266733Speter ret = 0; 104266733Speter } 105266733Speter } 106266733Speter return (ret); 107266733Speter} 108266733Speter 109266733Speterint 110266733Speter_pthread_spin_lock(pthread_spinlock_t *lock) 111266733Speter{ 112266733Speter struct pthread_spinlock *lck; 113266733Speter struct pthread *self = _pthread_self(); 114266733Speter int count, oldval, ret; 115266733Speter 116266733Speter if (lock == NULL || (lck = *lock) == NULL) 117266733Speter ret = EINVAL; 118266733Speter else if (lck->s_owner == self) 119266733Speter ret = EDEADLK; 120266733Speter else { 121266733Speter do { 122266733Speter count = SPIN_COUNT; 123266733Speter while (lck->s_lock) { 124266733Speter#ifdef __i386__ 125266733Speter /* tell cpu we are spinning */ 126266733Speter __asm __volatile("pause"); 127266733Speter#endif 128266733Speter if (--count <= 0) { 129266733Speter count = SPIN_COUNT; 130266733Speter _pthread_yield(); 131266733Speter } 132266733Speter } 133266733Speter atomic_swap_int((int *)&(lck)->s_lock, 1, &oldval); 134266733Speter } while (oldval); 135266733Speter 136266733Speter lck->s_owner = self; 137266733Speter ret = 0; 138266733Speter } 139266733Speter 140266733Speter return (ret); 141266733Speter} 142266733Speter 143266733Speterint 144266733Speter_pthread_spin_unlock(pthread_spinlock_t *lock) 145266733Speter{ 146266733Speter struct pthread_spinlock *lck; 147266733Speter int ret; 148266733Speter 149266733Speter if (lock == NULL || (lck = *lock) == NULL) 150266733Speter ret = EINVAL; 151266733Speter else { 152266733Speter if (lck->s_owner != _pthread_self()) 153266733Speter ret = EPERM; 154266733Speter else { 155266733Speter lck->s_owner = NULL; 156266733Speter atomic_swap_int((int *)&lck->s_lock, 0, &ret); 157266733Speter ret = 0; 158266733Speter } 159266733Speter } 160266733Speter 161266733Speter return (ret); 162266733Speter} 163266733Speter 164266733Speter