thr_spinlock.c revision 123314
1/* 2 * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by John Birrell. 16 * 4. Neither the name of the author nor the names of any co-contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * $FreeBSD: head/lib/libkse/thread/thr_spinlock.c 123314 2003-12-09 02:37:40Z davidxu $ 33 * 34 */ 35 36#include <sys/types.h> 37#include <machine/atomic.h> 38 39#include <libc_private.h> 40#include "spinlock.h" 41#include "thr_private.h" 42 43#define MAX_SPINLOCKS 5 44 45struct spinlock_extra { 46 spinlock_t *owner; 47 pthread_mutex_t lock; 48}; 49 50static void init_spinlock(spinlock_t *lck); 51 52static pthread_mutex_t spinlock_static_lock; 53static struct spinlock_extra extra[MAX_SPINLOCKS]; 54static int spinlock_count = 0; 55static int initialized = 0; 56 57/* 58 * These are for compatability only. Spinlocks of this type 59 * are deprecated. 60 */ 61 62void 63_spinunlock(spinlock_t *lck) 64{ 65 struct spinlock_extra *extra; 66 67 extra = (struct spinlock_extra *)lck->fname; 68 pthread_mutex_unlock(&extra->lock); 69} 70 71/* 72 * Lock a location for the running thread. Yield to allow other 73 * threads to run if this thread is blocked because the lock is 74 * not available. Note that this function does not sleep. It 75 * assumes that the lock will be available very soon. 76 */ 77void 78_spinlock(spinlock_t *lck) 79{ 80 struct spinlock_extra *extra; 81 82 if (!__isthreaded) 83 PANIC("Spinlock called when not threaded."); 84 if (!initialized) 85 PANIC("Spinlocks not initialized."); 86 /* 87 * Try to grab the lock and loop if another thread grabs 88 * it before we do. 89 */ 90 if (lck->fname == NULL) 91 init_spinlock(lck); 92 extra = (struct spinlock_extra *)lck->fname; 93 pthread_mutex_lock(&extra->lock); 94} 95 96/* 97 * Lock a location for the running thread. Yield to allow other 98 * threads to run if this thread is blocked because the lock is 99 * not available. Note that this function does not sleep. It 100 * assumes that the lock will be available very soon. 101 * 102 * This function checks if the running thread has already locked the 103 * location, warns if this occurs and creates a thread dump before 104 * returning. 105 */ 106void 107_spinlock_debug(spinlock_t *lck, char *fname, int lineno) 108{ 109 _spinlock(lck); 110} 111 112static void 113init_spinlock(spinlock_t *lck) 114{ 115 pthread_mutex_lock(&spinlock_static_lock); 116 if ((lck->fname == NULL) && (spinlock_count < MAX_SPINLOCKS)) { 117 lck->fname = (char *)&extra[spinlock_count]; 118 extra[spinlock_count].owner = lck; 119 spinlock_count++; 120 } 121 pthread_mutex_unlock(&spinlock_static_lock); 122 if (lck->fname == NULL) 123 PANIC("Exceeded max spinlocks"); 124} 125 126void 127_thr_spinlock_init(void) 128{ 129 int i; 130 131 if (initialized != 0) { 132 _thr_mutex_reinit(&spinlock_static_lock); 133 for (i = 0; i < spinlock_count; i++) 134 _thr_mutex_reinit(&extra[i].lock); 135 } else { 136 if (pthread_mutex_init(&spinlock_static_lock, NULL)) 137 PANIC("Cannot initialize spinlock_static_lock"); 138 for (i = 0; i < MAX_SPINLOCKS; i++) { 139 if (pthread_mutex_init(&extra[i].lock, NULL)) 140 PANIC("Cannot initialize spinlock extra"); 141 } 142 initialized = 1; 143 } 144} 145