kern_mtxpool.c revision 116305
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 26#include <sys/cdefs.h> 27__FBSDID("$FreeBSD: head/sys/kern/kern_mtxpool.c 116305 2003-06-13 19:39:21Z mux $"); 28 29#include <sys/param.h> 30#include <sys/proc.h> 31#include <sys/kernel.h> 32#include <sys/ktr.h> 33#include <sys/lock.h> 34#include <sys/malloc.h> 35#include <sys/mutex.h> 36#include <sys/systm.h> 37 38#ifndef MTX_POOL_SIZE 39#define MTX_POOL_SIZE 128 40#endif 41#define MTX_POOL_MASK (MTX_POOL_SIZE - 1) 42 43static struct mtx mtx_pool_ary[MTX_POOL_SIZE]; 44 45int mtx_pool_valid = 0; 46 47/* 48 * Inline version of mtx_pool_find(), used to streamline our main API 49 * function calls. 50 */ 51static __inline struct mtx * 52_mtx_pool_find(void *ptr) 53{ 54 int p; 55 56 p = (int)(uintptr_t)ptr; 57 return (&mtx_pool_ary[(p ^ (p >> 6)) & MTX_POOL_MASK]); 58} 59 60static void 61mtx_pool_setup(void *dummy __unused) 62{ 63 int i; 64 65 for (i = 0; i < MTX_POOL_SIZE; ++i) 66 mtx_init(&mtx_pool_ary[i], "pool mutex", NULL, 67 MTX_DEF | MTX_NOWITNESS | MTX_QUIET); 68 mtx_pool_valid = 1; 69} 70 71/* 72 * Obtain a (shared) mutex from the pool. The returned mutex is a leaf 73 * level mutex, meaning that if you obtain it you cannot obtain any other 74 * mutexes until you release it. You can legally msleep() on the mutex. 75 */ 76struct mtx * 77mtx_pool_alloc(void) 78{ 79 static int si; 80 81 return (&mtx_pool_ary[si++ & MTX_POOL_MASK]); 82} 83 84/* 85 * Return the (shared) pool mutex associated with the specified address. 86 * The returned mutex is a leaf level mutex, meaning that if you obtain it 87 * you cannot obtain any other mutexes until you release it. You can 88 * legally msleep() on the mutex. 89 */ 90struct mtx * 91mtx_pool_find(void *ptr) 92{ 93 94 return (_mtx_pool_find(ptr)); 95} 96 97/* 98 * Combined find/lock operation. Lock the pool mutex associated with 99 * the specified address. 100 */ 101void 102mtx_pool_lock(void *ptr) 103{ 104 105 mtx_lock(_mtx_pool_find(ptr)); 106} 107 108/* 109 * Combined find/unlock operation. Unlock the pool mutex associated with 110 * the specified address. 111 */ 112void 113mtx_pool_unlock(void *ptr) 114{ 115 116 mtx_unlock(_mtx_pool_find(ptr)); 117} 118 119SYSINIT(mtxpooli, SI_SUB_MTX_POOL, SI_ORDER_FIRST, mtx_pool_setup, NULL); 120