kern_mtxpool.c revision 116305
116234Smichaelm/*- 216234Smichaelm * Copyright (c) 2001 Matthew Dillon. All Rights Reserved. Copyright 316234Smichaelm * terms are as specified in the COPYRIGHT file at the base of the source 416234Smichaelm * tree. 516234Smichaelm * 616234Smichaelm * Mutex pool routines. These routines are designed to be used as short 716234Smichaelm * term leaf mutexes (e.g. the last mutex you might aquire other then 816234Smichaelm * calling msleep()). They operate using a shared pool. A mutex is chosen 916234Smichaelm * from the pool based on the supplied pointer (which may or may not be 1016234Smichaelm * valid). 1116234Smichaelm * 1216234Smichaelm * Advantages: 1316234Smichaelm * - no structural overhead. Mutexes can be associated with structures 1416234Smichaelm * without adding bloat to the structures. 1516234Smichaelm * - mutexes can be obtained for invalid pointers, useful when uses 1616234Smichaelm * mutexes to interlock destructor ops. 1716234Smichaelm * - no initialization/destructor overhead. 1816234Smichaelm * - can be used with msleep. 1916234Smichaelm * 2016234Smichaelm * Disadvantages: 2116234Smichaelm * - should generally only be used as leaf mutexes. 2216234Smichaelm * - pool/pool dependancy ordering cannot be depended on. 2316234Smichaelm * - possible L1 cache mastersip contention between cpus. 2416234Smichaelm */ 2516234Smichaelm 2616234Smichaelm#include <sys/cdefs.h> 2716234Smichaelm__FBSDID("$FreeBSD: head/sys/kern/kern_mtxpool.c 116305 2003-06-13 19:39:21Z mux $"); 2816234Smichaelm 2916234Smichaelm#include <sys/param.h> 3016234Smichaelm#include <sys/proc.h> 3116234Smichaelm#include <sys/kernel.h> 3216234Smichaelm#include <sys/ktr.h> 3316234Smichaelm#include <sys/lock.h> 3416234Smichaelm#include <sys/malloc.h> 3516234Smichaelm#include <sys/mutex.h> 3616234Smichaelm#include <sys/systm.h> 3716234Smichaelm 3816234Smichaelm#ifndef MTX_POOL_SIZE 3916234Smichaelm#define MTX_POOL_SIZE 128 4016234Smichaelm#endif 4116234Smichaelm#define MTX_POOL_MASK (MTX_POOL_SIZE - 1) 4216234Smichaelm 4316234Smichaelmstatic struct mtx mtx_pool_ary[MTX_POOL_SIZE]; 4416234Smichaelm 4516234Smichaelmint mtx_pool_valid = 0; 4616234Smichaelm 4716234Smichaelm/* 4816234Smichaelm * Inline version of mtx_pool_find(), used to streamline our main API 4916234Smichaelm * function calls. 5016234Smichaelm */ 5116234Smichaelmstatic __inline struct mtx * 5216234Smichaelm_mtx_pool_find(void *ptr) 5316234Smichaelm{ 5416234Smichaelm int p; 5516234Smichaelm 5616234Smichaelm p = (int)(uintptr_t)ptr; 5716234Smichaelm return (&mtx_pool_ary[(p ^ (p >> 6)) & MTX_POOL_MASK]); 5816234Smichaelm} 5916234Smichaelm 6016234Smichaelmstatic void 6116234Smichaelmmtx_pool_setup(void *dummy __unused) 6216234Smichaelm{ 6316234Smichaelm int i; 6416234Smichaelm 6516234Smichaelm for (i = 0; i < MTX_POOL_SIZE; ++i) 6616234Smichaelm mtx_init(&mtx_pool_ary[i], "pool mutex", NULL, 6716234Smichaelm MTX_DEF | MTX_NOWITNESS | MTX_QUIET); 6816234Smichaelm mtx_pool_valid = 1; 6916234Smichaelm} 7016234Smichaelm 7116234Smichaelm/* 7216234Smichaelm * Obtain a (shared) mutex from the pool. The returned mutex is a leaf 7316234Smichaelm * level mutex, meaning that if you obtain it you cannot obtain any other 7416234Smichaelm * mutexes until you release it. You can legally msleep() on the mutex. 7516234Smichaelm */ 7616234Smichaelmstruct mtx * 7716234Smichaelmmtx_pool_alloc(void) 7816234Smichaelm{ 7916234Smichaelm static int si; 8016234Smichaelm 8116234Smichaelm return (&mtx_pool_ary[si++ & MTX_POOL_MASK]); 8216234Smichaelm} 8316234Smichaelm 8416234Smichaelm/* 8516234Smichaelm * Return the (shared) pool mutex associated with the specified address. 8616234Smichaelm * The returned mutex is a leaf level mutex, meaning that if you obtain it 8716234Smichaelm * you cannot obtain any other mutexes until you release it. You can 8816234Smichaelm * legally msleep() on the mutex. 8916234Smichaelm */ 9016234Smichaelmstruct mtx * 9116234Smichaelmmtx_pool_find(void *ptr) 9216234Smichaelm{ 9316234Smichaelm 9416234Smichaelm return (_mtx_pool_find(ptr)); 9516234Smichaelm} 9616234Smichaelm 9716234Smichaelm/* 9816234Smichaelm * Combined find/lock operation. Lock the pool mutex associated with 9916234Smichaelm * the specified address. 10016234Smichaelm */ 10116234Smichaelmvoid 10216234Smichaelmmtx_pool_lock(void *ptr) 10316234Smichaelm{ 10416234Smichaelm 10516234Smichaelm mtx_lock(_mtx_pool_find(ptr)); 10616234Smichaelm} 10716234Smichaelm 10816234Smichaelm/* 10916234Smichaelm * Combined find/unlock operation. Unlock the pool mutex associated with 11016234Smichaelm * the specified address. 11116234Smichaelm */ 11216234Smichaelmvoid 11316234Smichaelmmtx_pool_unlock(void *ptr) 11416234Smichaelm{ 11516234Smichaelm 11616234Smichaelm mtx_unlock(_mtx_pool_find(ptr)); 11716234Smichaelm} 11816234Smichaelm 11916234SmichaelmSYSINIT(mtxpooli, SI_SUB_MTX_POOL, SI_ORDER_FIRST, mtx_pool_setup, NULL); 12016234Smichaelm