thr_pspinlock.c revision 144518
1144518Sdavidxu/*- 2144518Sdavidxu * Copyright (c) 2003 David Xu <davidxu@freebsd.org> 3144518Sdavidxu * All rights reserved. 4144518Sdavidxu * 5144518Sdavidxu * Redistribution and use in source and binary forms, with or without 6144518Sdavidxu * modification, are permitted provided that the following conditions 7144518Sdavidxu * are met: 8144518Sdavidxu * 1. Redistributions of source code must retain the above copyright 9144518Sdavidxu * notice, this list of conditions and the following disclaimer. 10144518Sdavidxu * 2. Redistributions in binary form must reproduce the above copyright 11144518Sdavidxu * notice, this list of conditions and the following disclaimer in the 12144518Sdavidxu * documentation and/or other materials provided with the distribution. 13144518Sdavidxu * 14144518Sdavidxu * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15144518Sdavidxu * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16144518Sdavidxu * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17144518Sdavidxu * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18144518Sdavidxu * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19144518Sdavidxu * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20144518Sdavidxu * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21144518Sdavidxu * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22144518Sdavidxu * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23144518Sdavidxu * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24144518Sdavidxu * SUCH DAMAGE. 25144518Sdavidxu * 26144518Sdavidxu * $FreeBSD: head/lib/libthr/thread/thr_pspinlock.c 144518 2005-04-02 01:20:00Z davidxu $ 27144518Sdavidxu */ 28144518Sdavidxu 29144518Sdavidxu#include <errno.h> 30144518Sdavidxu#include <stdlib.h> 31144518Sdavidxu#include <pthread.h> 32144518Sdavidxu#include "thr_private.h" 33144518Sdavidxu 34144518Sdavidxu#define SPIN_COUNT 100000 35144518Sdavidxu 36144518Sdavidxu__weak_reference(_pthread_spin_init, pthread_spin_init); 37144518Sdavidxu__weak_reference(_pthread_spin_destroy, pthread_spin_destroy); 38144518Sdavidxu__weak_reference(_pthread_spin_trylock, pthread_spin_trylock); 39144518Sdavidxu__weak_reference(_pthread_spin_lock, pthread_spin_lock); 40144518Sdavidxu__weak_reference(_pthread_spin_unlock, pthread_spin_unlock); 41144518Sdavidxu 42144518Sdavidxuint 43144518Sdavidxu_pthread_spin_init(pthread_spinlock_t *lock, int pshared) 44144518Sdavidxu{ 45144518Sdavidxu struct pthread_spinlock *lck; 46144518Sdavidxu int ret; 47144518Sdavidxu 48144518Sdavidxu if (lock == NULL || pshared != PTHREAD_PROCESS_PRIVATE) 49144518Sdavidxu ret = EINVAL; 50144518Sdavidxu else if ((lck = malloc(sizeof(struct pthread_spinlock))) == NULL) 51144518Sdavidxu ret = ENOMEM; 52144518Sdavidxu else { 53144518Sdavidxu _thr_umtx_init(&lck->s_lock); 54144518Sdavidxu *lock = lck; 55144518Sdavidxu ret = 0; 56144518Sdavidxu } 57144518Sdavidxu 58144518Sdavidxu return (ret); 59144518Sdavidxu} 60144518Sdavidxu 61144518Sdavidxuint 62144518Sdavidxu_pthread_spin_destroy(pthread_spinlock_t *lock) 63144518Sdavidxu{ 64144518Sdavidxu int ret; 65144518Sdavidxu 66144518Sdavidxu if (lock == NULL || *lock == NULL) 67144518Sdavidxu ret = EINVAL; 68144518Sdavidxu else { 69144518Sdavidxu free(*lock); 70144518Sdavidxu *lock = NULL; 71144518Sdavidxu ret = 0; 72144518Sdavidxu } 73144518Sdavidxu 74144518Sdavidxu return (ret); 75144518Sdavidxu} 76144518Sdavidxu 77144518Sdavidxuint 78144518Sdavidxu_pthread_spin_trylock(pthread_spinlock_t *lock) 79144518Sdavidxu{ 80144518Sdavidxu struct pthread *curthread = _get_curthread(); 81144518Sdavidxu struct pthread_spinlock *lck; 82144518Sdavidxu int ret; 83144518Sdavidxu 84144518Sdavidxu if (lock == NULL || (lck = *lock) == NULL) 85144518Sdavidxu ret = EINVAL; 86144518Sdavidxu else 87144518Sdavidxu ret = THR_UMTX_TRYLOCK(curthread, &lck->s_lock); 88144518Sdavidxu return (ret); 89144518Sdavidxu} 90144518Sdavidxu 91144518Sdavidxuint 92144518Sdavidxu_pthread_spin_lock(pthread_spinlock_t *lock) 93144518Sdavidxu{ 94144518Sdavidxu struct pthread *curthread = _get_curthread(); 95144518Sdavidxu struct pthread_spinlock *lck; 96144518Sdavidxu int ret, count; 97144518Sdavidxu 98144518Sdavidxu if (lock == NULL || (lck = *lock) == NULL) 99144518Sdavidxu ret = EINVAL; 100144518Sdavidxu else { 101144518Sdavidxu count = SPIN_COUNT; 102144518Sdavidxu while ((ret = THR_UMTX_TRYLOCK(curthread, &lck->s_lock)) != 0) { 103144518Sdavidxu while (lck->s_lock) { 104144518Sdavidxu#ifdef __i386__ 105144518Sdavidxu /* tell cpu we are spinning */ 106144518Sdavidxu __asm __volatile("pause"); 107144518Sdavidxu#endif 108144518Sdavidxu if (--count <= 0) { 109144518Sdavidxu count = SPIN_COUNT; 110144518Sdavidxu _pthread_yield(); 111144518Sdavidxu } 112144518Sdavidxu } 113144518Sdavidxu } 114144518Sdavidxu ret = 0; 115144518Sdavidxu } 116144518Sdavidxu 117144518Sdavidxu return (ret); 118144518Sdavidxu} 119144518Sdavidxu 120144518Sdavidxuint 121144518Sdavidxu_pthread_spin_unlock(pthread_spinlock_t *lock) 122144518Sdavidxu{ 123144518Sdavidxu struct pthread *curthread = _get_curthread(); 124144518Sdavidxu struct pthread_spinlock *lck; 125144518Sdavidxu int ret; 126144518Sdavidxu 127144518Sdavidxu if (lock == NULL || (lck = *lock) == NULL) 128144518Sdavidxu ret = EINVAL; 129144518Sdavidxu else { 130144518Sdavidxu ret = THR_UMTX_UNLOCK(curthread, &lck->s_lock); 131144518Sdavidxu } 132144518Sdavidxu return (ret); 133144518Sdavidxu} 134