xref: /freebsd/sys/kern/subr_lock.c (revision 83a81bcb147872dd34555a6e1c6877943c414e12)
183a81bcbSJohn Baldwin /*-
283a81bcbSJohn Baldwin  * Copyright (c) 2006 John Baldwin <jhb@FreeBSD.org>
383a81bcbSJohn Baldwin  * All rights reserved.
483a81bcbSJohn Baldwin  *
583a81bcbSJohn Baldwin  * Redistribution and use in source and binary forms, with or without
683a81bcbSJohn Baldwin  * modification, are permitted provided that the following conditions
783a81bcbSJohn Baldwin  * are met:
883a81bcbSJohn Baldwin  * 1. Redistributions of source code must retain the above copyright
983a81bcbSJohn Baldwin  *    notice, this list of conditions and the following disclaimer.
1083a81bcbSJohn Baldwin  * 2. Redistributions in binary form must reproduce the above copyright
1183a81bcbSJohn Baldwin  *    notice, this list of conditions and the following disclaimer in the
1283a81bcbSJohn Baldwin  *    documentation and/or other materials provided with the distribution.
1383a81bcbSJohn Baldwin  * 3. Neither the name of the author nor the names of any co-contributors
1483a81bcbSJohn Baldwin  *    may be used to endorse or promote products derived from this software
1583a81bcbSJohn Baldwin  *    without specific prior written permission.
1683a81bcbSJohn Baldwin  *
1783a81bcbSJohn Baldwin  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1883a81bcbSJohn Baldwin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1983a81bcbSJohn Baldwin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2083a81bcbSJohn Baldwin  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2183a81bcbSJohn Baldwin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2283a81bcbSJohn Baldwin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2383a81bcbSJohn Baldwin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2483a81bcbSJohn Baldwin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2583a81bcbSJohn Baldwin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2683a81bcbSJohn Baldwin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2783a81bcbSJohn Baldwin  * SUCH DAMAGE.
2883a81bcbSJohn Baldwin  */
2983a81bcbSJohn Baldwin 
3083a81bcbSJohn Baldwin /*
3183a81bcbSJohn Baldwin  * This module holds the global variables and functions used to maintain
3283a81bcbSJohn Baldwin  * lock_object structures.
3383a81bcbSJohn Baldwin  */
3483a81bcbSJohn Baldwin 
3583a81bcbSJohn Baldwin #include <sys/cdefs.h>
3683a81bcbSJohn Baldwin __FBSDID("$FreeBSD$");
3783a81bcbSJohn Baldwin 
3883a81bcbSJohn Baldwin #include <sys/param.h>
3983a81bcbSJohn Baldwin #include <sys/systm.h>
4083a81bcbSJohn Baldwin #include <sys/ktr.h>
4183a81bcbSJohn Baldwin #include <sys/lock.h>
4283a81bcbSJohn Baldwin 
4383a81bcbSJohn Baldwin #ifdef DDB
4483a81bcbSJohn Baldwin #include <ddb/ddb.h>
4583a81bcbSJohn Baldwin #endif
4683a81bcbSJohn Baldwin 
4783a81bcbSJohn Baldwin CTASSERT(LOCK_CLASS_MAX == 15);
4883a81bcbSJohn Baldwin 
4983a81bcbSJohn Baldwin #if LOCK_DEBUG > 0 || defined(DDB)
5083a81bcbSJohn Baldwin struct lock_class *lock_classes[LOCK_CLASS_MAX + 1] = {
5183a81bcbSJohn Baldwin 	&lock_class_mtx_spin,
5283a81bcbSJohn Baldwin 	&lock_class_mtx_sleep,
5383a81bcbSJohn Baldwin 	&lock_class_sx,
5483a81bcbSJohn Baldwin };
5583a81bcbSJohn Baldwin #endif
5683a81bcbSJohn Baldwin 
5783a81bcbSJohn Baldwin void
5883a81bcbSJohn Baldwin lock_init(struct lock_object *lock, struct lock_class *class, const char *name,
5983a81bcbSJohn Baldwin     const char *type, int flags)
6083a81bcbSJohn Baldwin {
6183a81bcbSJohn Baldwin 	int i;
6283a81bcbSJohn Baldwin 
6383a81bcbSJohn Baldwin 	/* Check for double-init and zero object. */
6483a81bcbSJohn Baldwin 	KASSERT(!lock_initalized(lock), ("lock \"%s\" %p already initialized",
6583a81bcbSJohn Baldwin 	    name, lock));
6683a81bcbSJohn Baldwin 
6783a81bcbSJohn Baldwin 	/* Look up lock class to find its index. */
6883a81bcbSJohn Baldwin 	for (i = 0; i < LOCK_CLASS_MAX; i++)
6983a81bcbSJohn Baldwin 		if (lock_classes[i] == class) {
7083a81bcbSJohn Baldwin 			lock->lo_flags = i << LO_CLASSSHIFT;
7183a81bcbSJohn Baldwin 			break;
7283a81bcbSJohn Baldwin 		}
7383a81bcbSJohn Baldwin 	KASSERT(i < LOCK_CLASS_MAX, ("unknown lock class %p", class));
7483a81bcbSJohn Baldwin 
7583a81bcbSJohn Baldwin 	/* Initialize the lock object. */
7683a81bcbSJohn Baldwin 	lock->lo_name = name;
7783a81bcbSJohn Baldwin 	lock->lo_type = type != NULL ? type : name;
7883a81bcbSJohn Baldwin 	lock->lo_flags |= flags | LO_INITIALIZED;
7983a81bcbSJohn Baldwin 	LOCK_LOG_INIT(lock, 0);
8083a81bcbSJohn Baldwin 	WITNESS_INIT(lock);
8183a81bcbSJohn Baldwin }
8283a81bcbSJohn Baldwin 
8383a81bcbSJohn Baldwin void
8483a81bcbSJohn Baldwin lock_destroy(struct lock_object *lock)
8583a81bcbSJohn Baldwin {
8683a81bcbSJohn Baldwin 
8783a81bcbSJohn Baldwin 	KASSERT(lock_initalized(lock), ("lock %p is not initialized", lock));
8883a81bcbSJohn Baldwin 	WITNESS_DESTROY(lock);
8983a81bcbSJohn Baldwin 	LOCK_LOG_DESTROY(lock, 0);
9083a81bcbSJohn Baldwin 	lock->lo_flags &= ~LO_INITIALIZED;
9183a81bcbSJohn Baldwin }
9283a81bcbSJohn Baldwin 
9383a81bcbSJohn Baldwin #ifdef DDB
9483a81bcbSJohn Baldwin DB_SHOW_COMMAND(lock, db_show_lock)
9583a81bcbSJohn Baldwin {
9683a81bcbSJohn Baldwin 	struct lock_object *lock;
9783a81bcbSJohn Baldwin 	struct lock_class *class;
9883a81bcbSJohn Baldwin 
9983a81bcbSJohn Baldwin 	if (!have_addr)
10083a81bcbSJohn Baldwin 		return;
10183a81bcbSJohn Baldwin 	lock = (struct lock_object *)addr;
10283a81bcbSJohn Baldwin 	if (LO_CLASSINDEX(lock) > LOCK_CLASS_MAX) {
10383a81bcbSJohn Baldwin 		db_printf("Unknown lock class: %d\n", LO_CLASSINDEX(lock));
10483a81bcbSJohn Baldwin 		return;
10583a81bcbSJohn Baldwin 	}
10683a81bcbSJohn Baldwin 	class = LOCK_CLASS(lock);
10783a81bcbSJohn Baldwin 	db_printf(" class: %s\n", class->lc_name);
10883a81bcbSJohn Baldwin 	db_printf(" name: %s\n", lock->lo_name);
10983a81bcbSJohn Baldwin 	if (lock->lo_type && lock->lo_type != lock->lo_name)
11083a81bcbSJohn Baldwin 		db_printf(" type: %s\n", lock->lo_type);
11183a81bcbSJohn Baldwin 	class->lc_ddb_show(lock);
11283a81bcbSJohn Baldwin }
11383a81bcbSJohn Baldwin #endif
114