thr_spinlock.c revision 103388
135509Sjb/* 235509Sjb * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>. 335509Sjb * All rights reserved. 435509Sjb * 535509Sjb * Redistribution and use in source and binary forms, with or without 635509Sjb * modification, are permitted provided that the following conditions 735509Sjb * are met: 835509Sjb * 1. Redistributions of source code must retain the above copyright 935509Sjb * notice, this list of conditions and the following disclaimer. 1035509Sjb * 2. Redistributions in binary form must reproduce the above copyright 1135509Sjb * notice, this list of conditions and the following disclaimer in the 1235509Sjb * documentation and/or other materials provided with the distribution. 1335509Sjb * 3. All advertising materials mentioning features or use of this software 1435509Sjb * must display the following acknowledgement: 1535509Sjb * This product includes software developed by John Birrell. 1635509Sjb * 4. Neither the name of the author nor the names of any co-contributors 1735509Sjb * may be used to endorse or promote products derived from this software 1835509Sjb * without specific prior written permission. 1935509Sjb * 2035509Sjb * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND 2135509Sjb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2235509Sjb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2349439Sdeischen * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2435509Sjb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2535509Sjb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2635509Sjb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2735509Sjb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2835509Sjb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2935509Sjb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3035509Sjb * SUCH DAMAGE. 3135509Sjb * 3250476Speter * $FreeBSD: head/lib/libkse/thread/thr_spinlock.c 103388 2002-09-16 08:45:36Z mini $ 3335509Sjb * 3435509Sjb */ 3535509Sjb 3693399Smarkm#include <stdlib.h> 3735509Sjb#include <stdio.h> 3893399Smarkm#include <string.h> 3935509Sjb#include <sched.h> 4093399Smarkm#include <pthread.h> 4135509Sjb#include <unistd.h> 4293399Smarkm 4393399Smarkm#include <libc_private.h> 4493399Smarkm 45103388Smini#include "thr_private.h" 4635509Sjb 4735509Sjb/* 4835509Sjb * Lock a location for the running thread. Yield to allow other 4935509Sjb * threads to run if this thread is blocked because the lock is 5035509Sjb * not available. Note that this function does not sleep. It 5135509Sjb * assumes that the lock will be available very soon. 5235509Sjb */ 5335509Sjbvoid 5436828Sjb_spinlock(spinlock_t *lck) 5535509Sjb{ 5671581Sdeischen struct pthread *curthread = _get_curthread(); 5771581Sdeischen 5836828Sjb /* 5936828Sjb * Try to grab the lock and loop if another thread grabs 6036828Sjb * it before we do. 6136828Sjb */ 6236828Sjb while(_atomic_lock(&lck->access_lock)) { 6344963Sjb /* Block the thread until the lock. */ 6471581Sdeischen curthread->data.spinlock = lck; 6544963Sjb _thread_kern_sched_state(PS_SPINBLOCK, __FILE__, __LINE__); 6636828Sjb } 6735509Sjb 6836828Sjb /* The running thread now owns the lock: */ 6971581Sdeischen lck->lock_owner = (long) curthread; 7036828Sjb} 7136828Sjb 7236828Sjb/* 7336828Sjb * Lock a location for the running thread. Yield to allow other 7436828Sjb * threads to run if this thread is blocked because the lock is 7536828Sjb * not available. Note that this function does not sleep. It 7636828Sjb * assumes that the lock will be available very soon. 7736828Sjb * 7836828Sjb * This function checks if the running thread has already locked the 7936828Sjb * location, warns if this occurs and creates a thread dump before 8036828Sjb * returning. 8136828Sjb */ 8236828Sjbvoid 8336828Sjb_spinlock_debug(spinlock_t *lck, char *fname, int lineno) 8436828Sjb{ 8571581Sdeischen struct pthread *curthread = _get_curthread(); 8644963Sjb int cnt = 0; 8744963Sjb 8835509Sjb /* 8935509Sjb * Try to grab the lock and loop if another thread grabs 9035509Sjb * it before we do. 9135509Sjb */ 9236828Sjb while(_atomic_lock(&lck->access_lock)) { 9344963Sjb cnt++; 9444963Sjb if (cnt > 100) { 9536828Sjb char str[256]; 9697204Sdeischen snprintf(str, sizeof(str), "%s - Warning: Thread %p attempted to lock %p from %s (%d) was left locked from %s (%d)\n", getprogname(), curthread, lck, fname, lineno, lck->fname, lck->lineno); 9771581Sdeischen __sys_write(2,str,strlen(str)); 9856698Sjasone __sleep(1); 9944963Sjb cnt = 0; 10044963Sjb } 10136828Sjb 10244963Sjb /* Block the thread until the lock. */ 10371581Sdeischen curthread->data.spinlock = lck; 10444963Sjb _thread_kern_sched_state(PS_SPINBLOCK, fname, lineno); 10536828Sjb } 10636828Sjb 10736828Sjb /* The running thread now owns the lock: */ 10871581Sdeischen lck->lock_owner = (long) curthread; 10936828Sjb lck->fname = fname; 11036828Sjb lck->lineno = lineno; 11135509Sjb} 112