kern_mtxpool.c revision 86333
1/*- 2 * Copyright (c) 2001 Matthew Dillon. All Rights Reserved. Copyright 3 * terms are as specified in the COPYRIGHT file at the base of the source 4 * tree. 5 * 6 * Mutex pool routines. These routines are designed to be used as short 7 * term leaf mutexes (e.g. the last mutex you might aquire other then 8 * calling msleep()). They operate using a shared pool. A mutex is chosen 9 * from the pool based on the supplied pointer (which may or may not be 10 * valid). 11 * 12 * Advantages: 13 * - no structural overhead. Mutexes can be associated with structures 14 * without adding bloat to the structures. 15 * - mutexes can be obtained for invalid pointers, useful when uses 16 * mutexes to interlock destructor ops. 17 * - no initialization/destructor overhead 18 * - can be used with msleep. 19 * 20 * Disadvantages: 21 * - should generally only be used as leaf mutexes 22 * - pool/pool dependancy ordering cannot be depended on. 23 * - possible L1 cache mastersip contention between cpus 24 * 25 * $FreeBSD: head/sys/kern/kern_mtxpool.c 86333 2001-11-13 21:55:13Z dillon $ 26 */ 27 28#include <sys/param.h> 29#include <sys/proc.h> 30#include <sys/kernel.h> 31#include <sys/ktr.h> 32#include <sys/lock.h> 33#include <sys/malloc.h> 34#include <sys/mutex.h> 35#include <sys/systm.h> 36 37#ifndef MTX_POOL_SIZE 38#define MTX_POOL_SIZE 128 39#endif 40#define MTX_POOL_MASK (MTX_POOL_SIZE-1) 41 42static struct mtx mtx_pool_ary[MTX_POOL_SIZE]; 43 44int mtx_pool_valid = 0; 45 46/* 47 * Inline version of mtx_pool_find(), used to streamline our main API 48 * function calls. 49 */ 50static __inline 51struct mtx * 52_mtx_pool_find(void *ptr) 53{ 54 return(&mtx_pool_ary[((int)ptr ^ ((int)ptr >> 6)) & MTX_POOL_MASK]); 55} 56 57static void 58mtx_pool_setup(void *dummy __unused) 59{ 60 int i; 61 62 for (i = 0; i < MTX_POOL_SIZE; ++i) 63 mtx_init(&mtx_pool_ary[i], "pool mutex", MTX_DEF); 64 mtx_pool_valid = 1; 65} 66 67/* 68 * Obtain a (shared) mutex from the pool. The returned mutex is a leaf 69 * level mutex, meaning that if you obtain it you cannot obtain any other 70 * mutexes until you release it. You can legally msleep() on the mutex. 71 */ 72struct mtx * 73mtx_pool_alloc(void) 74{ 75 static int si; 76 return(&mtx_pool_ary[si++ & MTX_POOL_MASK]); 77} 78 79/* 80 * Return the (shared) pool mutex associated with the specified address. 81 * The returned mutex is a leaf level mutex, meaning that if you obtain it 82 * you cannot obtain any other mutexes until you release it. You can 83 * legally msleep() on the mutex. 84 */ 85struct mtx * 86mtx_pool_find(void *ptr) 87{ 88 return(_mtx_pool_find(ptr)); 89} 90 91/* 92 * Combined find/lock operation. Lock the pool mutex associated with 93 * the specified address. 94 */ 95void 96mtx_pool_lock(void *ptr) 97{ 98 mtx_lock(_mtx_pool_find(ptr)); 99} 100 101/* 102 * Combined find/unlock operation. Unlock the pool mutex associated with 103 * the specified address. 104 */ 105void 106mtx_pool_unlock(void *ptr) 107{ 108 mtx_unlock(_mtx_pool_find(ptr)); 109} 110 111SYSINIT(mtxpooli, SI_SUB_MUTEX, SI_ORDER_FIRST, mtx_pool_setup, NULL) 112 113