Back to home page

OSCL-LXR

 
 

    


0001 #include <linux/export.h>
0002 #include <linux/kernel.h>
0003 #include <linux/mm.h>
0004 #include <linux/slab.h>
0005 #include <linux/vmalloc.h>
0006 
0007 /* Allocate an array of spinlocks to be accessed by a hash. Two arguments
0008  * indicate the number of elements to allocate in the array. max_size
0009  * gives the maximum number of elements to allocate. cpu_mult gives
0010  * the number of locks per CPU to allocate. The size is rounded up
0011  * to a power of 2 to be suitable as a hash table.
0012  */
0013 
0014 int __alloc_bucket_spinlocks(spinlock_t **locks, unsigned int *locks_mask,
0015                  size_t max_size, unsigned int cpu_mult, gfp_t gfp,
0016                  const char *name, struct lock_class_key *key)
0017 {
0018     spinlock_t *tlocks = NULL;
0019     unsigned int i, size;
0020 #if defined(CONFIG_PROVE_LOCKING)
0021     unsigned int nr_pcpus = 2;
0022 #else
0023     unsigned int nr_pcpus = num_possible_cpus();
0024 #endif
0025 
0026     if (cpu_mult) {
0027         nr_pcpus = min_t(unsigned int, nr_pcpus, 64UL);
0028         size = min_t(unsigned int, nr_pcpus * cpu_mult, max_size);
0029     } else {
0030         size = max_size;
0031     }
0032 
0033     if (sizeof(spinlock_t) != 0) {
0034         tlocks = kvmalloc_array(size, sizeof(spinlock_t), gfp);
0035         if (!tlocks)
0036             return -ENOMEM;
0037         for (i = 0; i < size; i++) {
0038             spin_lock_init(&tlocks[i]);
0039             lockdep_init_map(&tlocks[i].dep_map, name, key, 0);
0040         }
0041     }
0042 
0043     *locks = tlocks;
0044     *locks_mask = size - 1;
0045 
0046     return 0;
0047 }
0048 EXPORT_SYMBOL(__alloc_bucket_spinlocks);
0049 
0050 void free_bucket_spinlocks(spinlock_t *locks)
0051 {
0052     kvfree(locks);
0053 }
0054 EXPORT_SYMBOL(free_bucket_spinlocks);