1bb535300SJeff Roberson /* 2bb535300SJeff Roberson * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>. 3bb535300SJeff Roberson * All rights reserved. 4bb535300SJeff Roberson * 5bb535300SJeff Roberson * Redistribution and use in source and binary forms, with or without 6bb535300SJeff Roberson * modification, are permitted provided that the following conditions 7bb535300SJeff Roberson * are met: 8bb535300SJeff Roberson * 1. Redistributions of source code must retain the above copyright 9bb535300SJeff Roberson * notice, this list of conditions and the following disclaimer. 10bb535300SJeff Roberson * 2. Redistributions in binary form must reproduce the above copyright 11bb535300SJeff Roberson * notice, this list of conditions and the following disclaimer in the 12bb535300SJeff Roberson * documentation and/or other materials provided with the distribution. 13bb535300SJeff Roberson * 3. All advertising materials mentioning features or use of this software 14bb535300SJeff Roberson * must display the following acknowledgement: 15bb535300SJeff Roberson * This product includes software developed by John Birrell. 16bb535300SJeff Roberson * 4. Neither the name of the author nor the names of any co-contributors 17bb535300SJeff Roberson * may be used to endorse or promote products derived from this software 18bb535300SJeff Roberson * without specific prior written permission. 19bb535300SJeff Roberson * 20bb535300SJeff Roberson * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND 21bb535300SJeff Roberson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22bb535300SJeff Roberson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23bb535300SJeff Roberson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24bb535300SJeff Roberson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25bb535300SJeff Roberson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26bb535300SJeff Roberson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27bb535300SJeff Roberson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28bb535300SJeff Roberson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29bb535300SJeff Roberson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30bb535300SJeff Roberson * SUCH DAMAGE. 31bb535300SJeff Roberson * 32bb535300SJeff Roberson * $FreeBSD$ 33bb535300SJeff Roberson * 34bb535300SJeff Roberson */ 35bb535300SJeff Roberson 36dec04f43SMike Makonnen #include <sys/types.h> 37bb535300SJeff Roberson #include <pthread.h> 38bb535300SJeff Roberson #include <libc_private.h> 39a091d823SDavid Xu #include <spinlock.h> 40bb535300SJeff Roberson 41bb535300SJeff Roberson #include "thr_private.h" 42bb535300SJeff Roberson 4390dc7952SJason Evans #define MAX_SPINLOCKS 72 44dec04f43SMike Makonnen 45dec04f43SMike Makonnen /* 46a091d823SDavid Xu * These data structures are used to trace all spinlocks 47a091d823SDavid Xu * in libc. 48dec04f43SMike Makonnen */ 49a091d823SDavid Xu struct spinlock_extra { 50a091d823SDavid Xu spinlock_t *owner; 51a091d823SDavid Xu }; 52dec04f43SMike Makonnen 53a091d823SDavid Xu static umtx_t spinlock_static_lock; 54a091d823SDavid Xu static struct spinlock_extra extra[MAX_SPINLOCKS]; 55a091d823SDavid Xu static int spinlock_count; 56a091d823SDavid Xu static int initialized; 57dec04f43SMike Makonnen 58a091d823SDavid Xu static void init_spinlock(spinlock_t *lck); 59a091d823SDavid Xu 60a091d823SDavid Xu /* 61a091d823SDavid Xu * These are for compatability only. Spinlocks of this type 62a091d823SDavid Xu * are deprecated. 63a091d823SDavid Xu */ 64dec04f43SMike Makonnen 65bb535300SJeff Roberson void 66bb535300SJeff Roberson _spinunlock(spinlock_t *lck) 67bb535300SJeff Roberson { 68a091d823SDavid Xu THR_UMTX_UNLOCK(_get_curthread(), (umtx_t *)&lck->access_lock); 69bb535300SJeff Roberson } 70bb535300SJeff Roberson 71bb535300SJeff Roberson void 72bb535300SJeff Roberson _spinlock(spinlock_t *lck) 73bb535300SJeff Roberson { 74a091d823SDavid Xu if (!__isthreaded) 75a091d823SDavid Xu PANIC("Spinlock called when not threaded."); 76a091d823SDavid Xu if (!initialized) 77a091d823SDavid Xu PANIC("Spinlocks not initialized."); 78a091d823SDavid Xu if (lck->fname == NULL) 79a091d823SDavid Xu init_spinlock(lck); 80a091d823SDavid Xu THR_UMTX_LOCK(_get_curthread(), (umtx_t *)&lck->access_lock); 8159a47b31SMike Makonnen } 8259a47b31SMike Makonnen 83bb535300SJeff Roberson void 84bb535300SJeff Roberson _spinlock_debug(spinlock_t *lck, char *fname, int lineno) 85bb535300SJeff Roberson { 86a091d823SDavid Xu _spinlock(lck); 87a091d823SDavid Xu } 88a091d823SDavid Xu 89a091d823SDavid Xu static void 90a091d823SDavid Xu init_spinlock(spinlock_t *lck) 91a091d823SDavid Xu { 92a091d823SDavid Xu static int count = 0; 93a091d823SDavid Xu 94a091d823SDavid Xu THR_UMTX_LOCK(_get_curthread(), &spinlock_static_lock); 95a091d823SDavid Xu if ((lck->fname == NULL) && (spinlock_count < MAX_SPINLOCKS)) { 96a091d823SDavid Xu lck->fname = (char *)&extra[spinlock_count]; 97a091d823SDavid Xu extra[spinlock_count].owner = lck; 98a091d823SDavid Xu spinlock_count++; 99a091d823SDavid Xu } 100a091d823SDavid Xu THR_UMTX_UNLOCK(_get_curthread(), &spinlock_static_lock); 101a091d823SDavid Xu if (lck->fname == NULL && ++count < 5) 102a091d823SDavid Xu stderr_debug("Warning: exceeded max spinlocks"); 103a091d823SDavid Xu } 104a091d823SDavid Xu 105a091d823SDavid Xu void 106a091d823SDavid Xu _thr_spinlock_init(void) 107a091d823SDavid Xu { 108a091d823SDavid Xu int i; 109a091d823SDavid Xu 110a091d823SDavid Xu _thr_umtx_init(&spinlock_static_lock); 111a091d823SDavid Xu if (initialized != 0) { 112a091d823SDavid Xu /* 113a091d823SDavid Xu * called after fork() to reset state of libc spin locks, 114a091d823SDavid Xu * it is not quite right since libc may be in inconsistent 115a091d823SDavid Xu * state, resetting the locks to allow current thread to be 116a091d823SDavid Xu * able to hold them may not help things too much, but 117a091d823SDavid Xu * anyway, we do our best. 118a091d823SDavid Xu * it is better to do pthread_atfork in libc. 119a091d823SDavid Xu */ 120a091d823SDavid Xu for (i = 0; i < spinlock_count; i++) 121a091d823SDavid Xu _thr_umtx_init((umtx_t *)&extra[i].owner->access_lock); 122a091d823SDavid Xu } else { 123a091d823SDavid Xu initialized = 1; 124a091d823SDavid Xu } 125bb535300SJeff Roberson } 126