thr_pspinlock.c revision 122071
110122SJordan.Brown@Sun.COM/*- 210122SJordan.Brown@Sun.COM * Copyright (c) 2003 David Xu <davidxu@freebsd.org> 310122SJordan.Brown@Sun.COM * All rights reserved. 410122SJordan.Brown@Sun.COM * 510122SJordan.Brown@Sun.COM * Redistribution and use in source and binary forms, with or without 610122SJordan.Brown@Sun.COM * modification, are permitted provided that the following conditions 710122SJordan.Brown@Sun.COM * are met: 810122SJordan.Brown@Sun.COM * 1. Redistributions of source code must retain the above copyright 910122SJordan.Brown@Sun.COM * notice, this list of conditions and the following disclaimer. 1010122SJordan.Brown@Sun.COM * 2. Redistributions in binary form must reproduce the above copyright 1110122SJordan.Brown@Sun.COM * notice, this list of conditions and the following disclaimer in the 1210122SJordan.Brown@Sun.COM * documentation and/or other materials provided with the distribution. 1310122SJordan.Brown@Sun.COM * 1410122SJordan.Brown@Sun.COM * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1510122SJordan.Brown@Sun.COM * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1610122SJordan.Brown@Sun.COM * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1710122SJordan.Brown@Sun.COM * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1810122SJordan.Brown@Sun.COM * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1910122SJordan.Brown@Sun.COM * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2010122SJordan.Brown@Sun.COM * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2110122SJordan.Brown@Sun.COM * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2210122SJordan.Brown@Sun.COM * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2312890SJoyce.McIntosh@Sun.COM * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2410122SJordan.Brown@Sun.COM * SUCH DAMAGE. 2510122SJordan.Brown@Sun.COM * 2610122SJordan.Brown@Sun.COM * $FreeBSD: head/lib/libkse/thread/thr_pspinlock.c 122071 2003-11-04 19:56:12Z deischen $ 2710122SJordan.Brown@Sun.COM */ 2810122SJordan.Brown@Sun.COM 2910122SJordan.Brown@Sun.COM#include <errno.h> 3010122SJordan.Brown@Sun.COM#include <stdlib.h> 3110122SJordan.Brown@Sun.COM#include <pthread.h> 3210122SJordan.Brown@Sun.COM#include <atomic_ops.h> 3310122SJordan.Brown@Sun.COM#include "thr_private.h" 3410122SJordan.Brown@Sun.COM 3510122SJordan.Brown@Sun.COM#define SPIN_COUNT 10000 3610122SJordan.Brown@Sun.COM 3712890SJoyce.McIntosh@Sun.COM__weak_reference(_pthread_spin_init, pthread_spin_init); 3810122SJordan.Brown@Sun.COM__weak_reference(_pthread_spin_destroy, pthread_spin_destroy); 3910122SJordan.Brown@Sun.COM__weak_reference(_pthread_spin_trylock, pthread_spin_trylock); 4010122SJordan.Brown@Sun.COM__weak_reference(_pthread_spin_lock, pthread_spin_lock); 4110122SJordan.Brown@Sun.COM__weak_reference(_pthread_spin_unlock, pthread_spin_unlock); 4210122SJordan.Brown@Sun.COM 4310122SJordan.Brown@Sun.COMint 4410122SJordan.Brown@Sun.COM_pthread_spin_init(pthread_spinlock_t *lock, int pshared) 4510122SJordan.Brown@Sun.COM{ 4610122SJordan.Brown@Sun.COM struct pthread_spinlock *lck; 4710122SJordan.Brown@Sun.COM int ret; 4810122SJordan.Brown@Sun.COM 4910122SJordan.Brown@Sun.COM if (lock == NULL || pshared != PTHREAD_PROCESS_PRIVATE) 5010122SJordan.Brown@Sun.COM ret = EINVAL; 5110122SJordan.Brown@Sun.COM else if ((lck = malloc(sizeof(struct pthread_spinlock))) == NULL) 5210122SJordan.Brown@Sun.COM ret = ENOMEM; 5310122SJordan.Brown@Sun.COM else { 5410122SJordan.Brown@Sun.COM lck->s_lock = 0; 5510122SJordan.Brown@Sun.COM lck->s_owner= NULL; 5610122SJordan.Brown@Sun.COM *lock = lck; 5710122SJordan.Brown@Sun.COM ret = 0; 5810122SJordan.Brown@Sun.COM } 5910122SJordan.Brown@Sun.COM 6010122SJordan.Brown@Sun.COM return (ret); 6110122SJordan.Brown@Sun.COM} 6210122SJordan.Brown@Sun.COM 6310122SJordan.Brown@Sun.COMint 6410122SJordan.Brown@Sun.COM_pthread_spin_destroy(pthread_spinlock_t *lock) 6510122SJordan.Brown@Sun.COM{ 6610122SJordan.Brown@Sun.COM int ret; 6710122SJordan.Brown@Sun.COM 6810122SJordan.Brown@Sun.COM if (lock == NULL || *lock == NULL) 6910122SJordan.Brown@Sun.COM ret = EINVAL; 7010122SJordan.Brown@Sun.COM else if ((*lock)->s_owner != NULL) 7110122SJordan.Brown@Sun.COM ret = EBUSY; 7210122SJordan.Brown@Sun.COM else { 7310122SJordan.Brown@Sun.COM free(*lock); 7410122SJordan.Brown@Sun.COM *lock = NULL; 7510122SJordan.Brown@Sun.COM ret = 0; 7610122SJordan.Brown@Sun.COM } 7710122SJordan.Brown@Sun.COM 7810122SJordan.Brown@Sun.COM return (ret); 7910122SJordan.Brown@Sun.COM} 8010122SJordan.Brown@Sun.COM 8110122SJordan.Brown@Sun.COMint 8210122SJordan.Brown@Sun.COM_pthread_spin_trylock(pthread_spinlock_t *lock) 8310122SJordan.Brown@Sun.COM{ 8410122SJordan.Brown@Sun.COM struct pthread_spinlock *lck; 8510122SJordan.Brown@Sun.COM struct pthread *self = _pthread_self(); 8610122SJordan.Brown@Sun.COM int oldval, ret; 8710122SJordan.Brown@Sun.COM 8810122SJordan.Brown@Sun.COM if (lock == NULL || (lck = *lock) == NULL) 8910122SJordan.Brown@Sun.COM ret = EINVAL; 9010122SJordan.Brown@Sun.COM else if (lck->s_owner == self) 9110122SJordan.Brown@Sun.COM ret = EDEADLK; 9210122SJordan.Brown@Sun.COM else if (lck->s_lock != 0) 9310122SJordan.Brown@Sun.COM ret = EBUSY; 9410122SJordan.Brown@Sun.COM else { 9510122SJordan.Brown@Sun.COM atomic_swap_int((int *)&(lck)->s_lock, 1, &oldval); 9610122SJordan.Brown@Sun.COM if (oldval) 9710122SJordan.Brown@Sun.COM ret = EBUSY; 9810122SJordan.Brown@Sun.COM else { 9910122SJordan.Brown@Sun.COM lck->s_owner = _pthread_self(); 10010122SJordan.Brown@Sun.COM ret = 0; 10110122SJordan.Brown@Sun.COM } 10210122SJordan.Brown@Sun.COM } 10310122SJordan.Brown@Sun.COM return (ret); 10410122SJordan.Brown@Sun.COM} 10510122SJordan.Brown@Sun.COM 10610122SJordan.Brown@Sun.COMint 10710122SJordan.Brown@Sun.COM_pthread_spin_lock(pthread_spinlock_t *lock) 10810122SJordan.Brown@Sun.COM{ 10910122SJordan.Brown@Sun.COM struct pthread_spinlock *lck; 11010122SJordan.Brown@Sun.COM struct pthread *self = _pthread_self(); 11110122SJordan.Brown@Sun.COM int count, oldval, ret; 11210122SJordan.Brown@Sun.COM 11310122SJordan.Brown@Sun.COM if (lock == NULL || (lck = *lock) == NULL) 11410122SJordan.Brown@Sun.COM ret = EINVAL; 11510122SJordan.Brown@Sun.COM else if (lck->s_owner == self) 11610122SJordan.Brown@Sun.COM ret = EDEADLK; 11710122SJordan.Brown@Sun.COM else { 11810122SJordan.Brown@Sun.COM do { 11910122SJordan.Brown@Sun.COM count = SPIN_COUNT; 12010122SJordan.Brown@Sun.COM while (lck->s_lock) { 12110122SJordan.Brown@Sun.COM#ifdef __i386__ 12210122SJordan.Brown@Sun.COM /* tell cpu we are spinning */ 12310122SJordan.Brown@Sun.COM __asm __volatile("pause"); 12410122SJordan.Brown@Sun.COM#endif 12510122SJordan.Brown@Sun.COM if (--count <= 0) { 12610122SJordan.Brown@Sun.COM count = SPIN_COUNT; 12710122SJordan.Brown@Sun.COM _pthread_yield(); 12810122SJordan.Brown@Sun.COM } 12910122SJordan.Brown@Sun.COM } 13010122SJordan.Brown@Sun.COM atomic_swap_int((int *)&(lck)->s_lock, 1, &oldval); 13110122SJordan.Brown@Sun.COM } while (oldval); 13210122SJordan.Brown@Sun.COM 13310122SJordan.Brown@Sun.COM lck->s_owner = self; 13410122SJordan.Brown@Sun.COM ret = 0; 13510122SJordan.Brown@Sun.COM } 13610122SJordan.Brown@Sun.COM 13710122SJordan.Brown@Sun.COM return (ret); 13810122SJordan.Brown@Sun.COM} 13910122SJordan.Brown@Sun.COM 14010122SJordan.Brown@Sun.COMint 14110122SJordan.Brown@Sun.COM_pthread_spin_unlock(pthread_spinlock_t *lock) 14210122SJordan.Brown@Sun.COM{ 14310122SJordan.Brown@Sun.COM struct pthread_spinlock *lck; 14410122SJordan.Brown@Sun.COM int ret; 14510122SJordan.Brown@Sun.COM 14610122SJordan.Brown@Sun.COM if (lock == NULL || (lck = *lock) == NULL) 14710122SJordan.Brown@Sun.COM ret = EINVAL; 14810122SJordan.Brown@Sun.COM else { 14910122SJordan.Brown@Sun.COM if (lck->s_owner != _pthread_self()) 15010122SJordan.Brown@Sun.COM ret = EPERM; 15110122SJordan.Brown@Sun.COM else { 15210122SJordan.Brown@Sun.COM lck->s_owner = NULL; 15310122SJordan.Brown@Sun.COM atomic_swap_int((int *)&lck->s_lock, 0, &ret); 15410122SJordan.Brown@Sun.COM ret = 0; 15510122SJordan.Brown@Sun.COM } 15610122SJordan.Brown@Sun.COM } 15710122SJordan.Brown@Sun.COM 15810122SJordan.Brown@Sun.COM return (ret); 15910122SJordan.Brown@Sun.COM} 16010122SJordan.Brown@Sun.COM 16110122SJordan.Brown@Sun.COM