kern_mtxpool.c revision 86563
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 86563 2001-11-19 00:20:36Z 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 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", MTX_DEF | MTX_NOWITNESS | MTX_QUIET); 67 mtx_pool_valid = 1; 68} 69 70/* 71 * Obtain a (shared) mutex from the pool. The returned mutex is a leaf 72 * level mutex, meaning that if you obtain it you cannot obtain any other 73 * mutexes until you release it. You can legally msleep() on the mutex. 74 */ 75struct mtx * 76mtx_pool_alloc(void) 77{ 78 static int si; 79 return(&mtx_pool_ary[si++ & MTX_POOL_MASK]); 80} 81 82/* 83 * Return the (shared) pool mutex associated with the specified address. 84 * The returned mutex is a leaf level mutex, meaning that if you obtain it 85 * you cannot obtain any other mutexes until you release it. You can 86 * legally msleep() on the mutex. 87 */ 88struct mtx * 89mtx_pool_find(void *ptr) 90{ 91 return(_mtx_pool_find(ptr)); 92} 93 94/* 95 * Combined find/lock operation. Lock the pool mutex associated with 96 * the specified address. 97 */ 98void 99mtx_pool_lock(void *ptr) 100{ 101 mtx_lock(_mtx_pool_find(ptr)); 102} 103 104/* 105 * Combined find/unlock operation. Unlock the pool mutex associated with 106 * the specified address. 107 */ 108void 109mtx_pool_unlock(void *ptr) 110{ 111 mtx_unlock(_mtx_pool_find(ptr)); 112} 113 114SYSINIT(mtxpooli, SI_SUB_MUTEX, SI_ORDER_FIRST, mtx_pool_setup, NULL) 115 116