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
0008
0009
0010
0011
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);