1*88459642SOmar Sandoval /* 2*88459642SOmar Sandoval * Copyright (C) 2016 Facebook 3*88459642SOmar Sandoval * Copyright (C) 2013-2014 Jens Axboe 4*88459642SOmar Sandoval * 5*88459642SOmar Sandoval * This program is free software; you can redistribute it and/or 6*88459642SOmar Sandoval * modify it under the terms of the GNU General Public 7*88459642SOmar Sandoval * License v2 as published by the Free Software Foundation. 8*88459642SOmar Sandoval * 9*88459642SOmar Sandoval * This program is distributed in the hope that it will be useful, 10*88459642SOmar Sandoval * but WITHOUT ANY WARRANTY; without even the implied warranty of 11*88459642SOmar Sandoval * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12*88459642SOmar Sandoval * General Public License for more details. 13*88459642SOmar Sandoval * 14*88459642SOmar Sandoval * You should have received a copy of the GNU General Public License 15*88459642SOmar Sandoval * along with this program. If not, see <https://www.gnu.org/licenses/>. 16*88459642SOmar Sandoval */ 17*88459642SOmar Sandoval 18*88459642SOmar Sandoval #include <linux/sbitmap.h> 19*88459642SOmar Sandoval 20*88459642SOmar Sandoval int sbitmap_init_node(struct sbitmap *sb, unsigned int depth, int shift, 21*88459642SOmar Sandoval gfp_t flags, int node) 22*88459642SOmar Sandoval { 23*88459642SOmar Sandoval unsigned int bits_per_word; 24*88459642SOmar Sandoval unsigned int i; 25*88459642SOmar Sandoval 26*88459642SOmar Sandoval if (shift < 0) { 27*88459642SOmar Sandoval shift = ilog2(BITS_PER_LONG); 28*88459642SOmar Sandoval /* 29*88459642SOmar Sandoval * If the bitmap is small, shrink the number of bits per word so 30*88459642SOmar Sandoval * we spread over a few cachelines, at least. If less than 4 31*88459642SOmar Sandoval * bits, just forget about it, it's not going to work optimally 32*88459642SOmar Sandoval * anyway. 33*88459642SOmar Sandoval */ 34*88459642SOmar Sandoval if (depth >= 4) { 35*88459642SOmar Sandoval while ((4U << shift) > depth) 36*88459642SOmar Sandoval shift--; 37*88459642SOmar Sandoval } 38*88459642SOmar Sandoval } 39*88459642SOmar Sandoval bits_per_word = 1U << shift; 40*88459642SOmar Sandoval if (bits_per_word > BITS_PER_LONG) 41*88459642SOmar Sandoval return -EINVAL; 42*88459642SOmar Sandoval 43*88459642SOmar Sandoval sb->shift = shift; 44*88459642SOmar Sandoval sb->depth = depth; 45*88459642SOmar Sandoval sb->map_nr = DIV_ROUND_UP(sb->depth, bits_per_word); 46*88459642SOmar Sandoval 47*88459642SOmar Sandoval if (depth == 0) { 48*88459642SOmar Sandoval sb->map = NULL; 49*88459642SOmar Sandoval return 0; 50*88459642SOmar Sandoval } 51*88459642SOmar Sandoval 52*88459642SOmar Sandoval sb->map = kzalloc_node(sb->map_nr * sizeof(*sb->map), flags, node); 53*88459642SOmar Sandoval if (!sb->map) 54*88459642SOmar Sandoval return -ENOMEM; 55*88459642SOmar Sandoval 56*88459642SOmar Sandoval for (i = 0; i < sb->map_nr; i++) { 57*88459642SOmar Sandoval sb->map[i].depth = min(depth, bits_per_word); 58*88459642SOmar Sandoval depth -= sb->map[i].depth; 59*88459642SOmar Sandoval } 60*88459642SOmar Sandoval return 0; 61*88459642SOmar Sandoval } 62*88459642SOmar Sandoval EXPORT_SYMBOL_GPL(sbitmap_init_node); 63*88459642SOmar Sandoval 64*88459642SOmar Sandoval void sbitmap_resize(struct sbitmap *sb, unsigned int depth) 65*88459642SOmar Sandoval { 66*88459642SOmar Sandoval unsigned int bits_per_word = 1U << sb->shift; 67*88459642SOmar Sandoval unsigned int i; 68*88459642SOmar Sandoval 69*88459642SOmar Sandoval sb->depth = depth; 70*88459642SOmar Sandoval sb->map_nr = DIV_ROUND_UP(sb->depth, bits_per_word); 71*88459642SOmar Sandoval 72*88459642SOmar Sandoval for (i = 0; i < sb->map_nr; i++) { 73*88459642SOmar Sandoval sb->map[i].depth = min(depth, bits_per_word); 74*88459642SOmar Sandoval depth -= sb->map[i].depth; 75*88459642SOmar Sandoval } 76*88459642SOmar Sandoval } 77*88459642SOmar Sandoval EXPORT_SYMBOL_GPL(sbitmap_resize); 78*88459642SOmar Sandoval 79*88459642SOmar Sandoval static int __sbitmap_get_word(struct sbitmap_word *word, unsigned int hint, 80*88459642SOmar Sandoval bool wrap) 81*88459642SOmar Sandoval { 82*88459642SOmar Sandoval unsigned int orig_hint = hint; 83*88459642SOmar Sandoval int nr; 84*88459642SOmar Sandoval 85*88459642SOmar Sandoval while (1) { 86*88459642SOmar Sandoval nr = find_next_zero_bit(&word->word, word->depth, hint); 87*88459642SOmar Sandoval if (unlikely(nr >= word->depth)) { 88*88459642SOmar Sandoval /* 89*88459642SOmar Sandoval * We started with an offset, and we didn't reset the 90*88459642SOmar Sandoval * offset to 0 in a failure case, so start from 0 to 91*88459642SOmar Sandoval * exhaust the map. 92*88459642SOmar Sandoval */ 93*88459642SOmar Sandoval if (orig_hint && hint && wrap) { 94*88459642SOmar Sandoval hint = orig_hint = 0; 95*88459642SOmar Sandoval continue; 96*88459642SOmar Sandoval } 97*88459642SOmar Sandoval return -1; 98*88459642SOmar Sandoval } 99*88459642SOmar Sandoval 100*88459642SOmar Sandoval if (!test_and_set_bit(nr, &word->word)) 101*88459642SOmar Sandoval break; 102*88459642SOmar Sandoval 103*88459642SOmar Sandoval hint = nr + 1; 104*88459642SOmar Sandoval if (hint >= word->depth - 1) 105*88459642SOmar Sandoval hint = 0; 106*88459642SOmar Sandoval } 107*88459642SOmar Sandoval 108*88459642SOmar Sandoval return nr; 109*88459642SOmar Sandoval } 110*88459642SOmar Sandoval 111*88459642SOmar Sandoval int sbitmap_get(struct sbitmap *sb, unsigned int alloc_hint, bool round_robin) 112*88459642SOmar Sandoval { 113*88459642SOmar Sandoval unsigned int i, index; 114*88459642SOmar Sandoval int nr = -1; 115*88459642SOmar Sandoval 116*88459642SOmar Sandoval index = SB_NR_TO_INDEX(sb, alloc_hint); 117*88459642SOmar Sandoval 118*88459642SOmar Sandoval for (i = 0; i < sb->map_nr; i++) { 119*88459642SOmar Sandoval nr = __sbitmap_get_word(&sb->map[index], 120*88459642SOmar Sandoval SB_NR_TO_BIT(sb, alloc_hint), 121*88459642SOmar Sandoval !round_robin); 122*88459642SOmar Sandoval if (nr != -1) { 123*88459642SOmar Sandoval nr += index << sb->shift; 124*88459642SOmar Sandoval break; 125*88459642SOmar Sandoval } 126*88459642SOmar Sandoval 127*88459642SOmar Sandoval /* Jump to next index. */ 128*88459642SOmar Sandoval index++; 129*88459642SOmar Sandoval alloc_hint = index << sb->shift; 130*88459642SOmar Sandoval 131*88459642SOmar Sandoval if (index >= sb->map_nr) { 132*88459642SOmar Sandoval index = 0; 133*88459642SOmar Sandoval alloc_hint = 0; 134*88459642SOmar Sandoval } 135*88459642SOmar Sandoval } 136*88459642SOmar Sandoval 137*88459642SOmar Sandoval return nr; 138*88459642SOmar Sandoval } 139*88459642SOmar Sandoval EXPORT_SYMBOL_GPL(sbitmap_get); 140*88459642SOmar Sandoval 141*88459642SOmar Sandoval bool sbitmap_any_bit_set(const struct sbitmap *sb) 142*88459642SOmar Sandoval { 143*88459642SOmar Sandoval unsigned int i; 144*88459642SOmar Sandoval 145*88459642SOmar Sandoval for (i = 0; i < sb->map_nr; i++) { 146*88459642SOmar Sandoval if (sb->map[i].word) 147*88459642SOmar Sandoval return true; 148*88459642SOmar Sandoval } 149*88459642SOmar Sandoval return false; 150*88459642SOmar Sandoval } 151*88459642SOmar Sandoval EXPORT_SYMBOL_GPL(sbitmap_any_bit_set); 152*88459642SOmar Sandoval 153*88459642SOmar Sandoval bool sbitmap_any_bit_clear(const struct sbitmap *sb) 154*88459642SOmar Sandoval { 155*88459642SOmar Sandoval unsigned int i; 156*88459642SOmar Sandoval 157*88459642SOmar Sandoval for (i = 0; i < sb->map_nr; i++) { 158*88459642SOmar Sandoval const struct sbitmap_word *word = &sb->map[i]; 159*88459642SOmar Sandoval unsigned long ret; 160*88459642SOmar Sandoval 161*88459642SOmar Sandoval ret = find_first_zero_bit(&word->word, word->depth); 162*88459642SOmar Sandoval if (ret < word->depth) 163*88459642SOmar Sandoval return true; 164*88459642SOmar Sandoval } 165*88459642SOmar Sandoval return false; 166*88459642SOmar Sandoval } 167*88459642SOmar Sandoval EXPORT_SYMBOL_GPL(sbitmap_any_bit_clear); 168*88459642SOmar Sandoval 169*88459642SOmar Sandoval unsigned int sbitmap_weight(const struct sbitmap *sb) 170*88459642SOmar Sandoval { 171*88459642SOmar Sandoval unsigned int i, weight; 172*88459642SOmar Sandoval 173*88459642SOmar Sandoval for (i = 0; i < sb->map_nr; i++) { 174*88459642SOmar Sandoval const struct sbitmap_word *word = &sb->map[i]; 175*88459642SOmar Sandoval 176*88459642SOmar Sandoval weight += bitmap_weight(&word->word, word->depth); 177*88459642SOmar Sandoval } 178*88459642SOmar Sandoval return weight; 179*88459642SOmar Sandoval } 180*88459642SOmar Sandoval EXPORT_SYMBOL_GPL(sbitmap_weight); 181*88459642SOmar Sandoval 182*88459642SOmar Sandoval static unsigned int sbq_calc_wake_batch(unsigned int depth) 183*88459642SOmar Sandoval { 184*88459642SOmar Sandoval unsigned int wake_batch; 185*88459642SOmar Sandoval 186*88459642SOmar Sandoval /* 187*88459642SOmar Sandoval * For each batch, we wake up one queue. We need to make sure that our 188*88459642SOmar Sandoval * batch size is small enough that the full depth of the bitmap is 189*88459642SOmar Sandoval * enough to wake up all of the queues. 190*88459642SOmar Sandoval */ 191*88459642SOmar Sandoval wake_batch = SBQ_WAKE_BATCH; 192*88459642SOmar Sandoval if (wake_batch > depth / SBQ_WAIT_QUEUES) 193*88459642SOmar Sandoval wake_batch = max(1U, depth / SBQ_WAIT_QUEUES); 194*88459642SOmar Sandoval 195*88459642SOmar Sandoval return wake_batch; 196*88459642SOmar Sandoval } 197*88459642SOmar Sandoval 198*88459642SOmar Sandoval int sbitmap_queue_init_node(struct sbitmap_queue *sbq, unsigned int depth, 199*88459642SOmar Sandoval int shift, gfp_t flags, int node) 200*88459642SOmar Sandoval { 201*88459642SOmar Sandoval int ret; 202*88459642SOmar Sandoval int i; 203*88459642SOmar Sandoval 204*88459642SOmar Sandoval ret = sbitmap_init_node(&sbq->sb, depth, shift, flags, node); 205*88459642SOmar Sandoval if (ret) 206*88459642SOmar Sandoval return ret; 207*88459642SOmar Sandoval 208*88459642SOmar Sandoval sbq->wake_batch = sbq_calc_wake_batch(depth); 209*88459642SOmar Sandoval atomic_set(&sbq->wake_index, 0); 210*88459642SOmar Sandoval 211*88459642SOmar Sandoval sbq->ws = kzalloc(SBQ_WAIT_QUEUES * sizeof(*sbq->ws), flags); 212*88459642SOmar Sandoval if (!sbq->ws) { 213*88459642SOmar Sandoval sbitmap_free(&sbq->sb); 214*88459642SOmar Sandoval return -ENOMEM; 215*88459642SOmar Sandoval } 216*88459642SOmar Sandoval 217*88459642SOmar Sandoval for (i = 0; i < SBQ_WAIT_QUEUES; i++) { 218*88459642SOmar Sandoval init_waitqueue_head(&sbq->ws[i].wait); 219*88459642SOmar Sandoval atomic_set(&sbq->ws[i].wait_cnt, sbq->wake_batch); 220*88459642SOmar Sandoval } 221*88459642SOmar Sandoval return 0; 222*88459642SOmar Sandoval } 223*88459642SOmar Sandoval EXPORT_SYMBOL_GPL(sbitmap_queue_init_node); 224*88459642SOmar Sandoval 225*88459642SOmar Sandoval void sbitmap_queue_resize(struct sbitmap_queue *sbq, unsigned int depth) 226*88459642SOmar Sandoval { 227*88459642SOmar Sandoval sbq->wake_batch = sbq_calc_wake_batch(depth); 228*88459642SOmar Sandoval sbitmap_resize(&sbq->sb, depth); 229*88459642SOmar Sandoval } 230*88459642SOmar Sandoval EXPORT_SYMBOL_GPL(sbitmap_queue_resize); 231*88459642SOmar Sandoval 232*88459642SOmar Sandoval static struct sbq_wait_state *sbq_wake_ptr(struct sbitmap_queue *sbq) 233*88459642SOmar Sandoval { 234*88459642SOmar Sandoval int i, wake_index; 235*88459642SOmar Sandoval 236*88459642SOmar Sandoval wake_index = atomic_read(&sbq->wake_index); 237*88459642SOmar Sandoval for (i = 0; i < SBQ_WAIT_QUEUES; i++) { 238*88459642SOmar Sandoval struct sbq_wait_state *ws = &sbq->ws[wake_index]; 239*88459642SOmar Sandoval 240*88459642SOmar Sandoval if (waitqueue_active(&ws->wait)) { 241*88459642SOmar Sandoval int o = atomic_read(&sbq->wake_index); 242*88459642SOmar Sandoval 243*88459642SOmar Sandoval if (wake_index != o) 244*88459642SOmar Sandoval atomic_cmpxchg(&sbq->wake_index, o, wake_index); 245*88459642SOmar Sandoval return ws; 246*88459642SOmar Sandoval } 247*88459642SOmar Sandoval 248*88459642SOmar Sandoval wake_index = sbq_index_inc(wake_index); 249*88459642SOmar Sandoval } 250*88459642SOmar Sandoval 251*88459642SOmar Sandoval return NULL; 252*88459642SOmar Sandoval } 253*88459642SOmar Sandoval 254*88459642SOmar Sandoval static void sbq_wake_up(struct sbitmap_queue *sbq) 255*88459642SOmar Sandoval { 256*88459642SOmar Sandoval struct sbq_wait_state *ws; 257*88459642SOmar Sandoval int wait_cnt; 258*88459642SOmar Sandoval 259*88459642SOmar Sandoval /* Ensure that the wait list checks occur after clear_bit(). */ 260*88459642SOmar Sandoval smp_mb(); 261*88459642SOmar Sandoval 262*88459642SOmar Sandoval ws = sbq_wake_ptr(sbq); 263*88459642SOmar Sandoval if (!ws) 264*88459642SOmar Sandoval return; 265*88459642SOmar Sandoval 266*88459642SOmar Sandoval wait_cnt = atomic_dec_return(&ws->wait_cnt); 267*88459642SOmar Sandoval if (unlikely(wait_cnt < 0)) 268*88459642SOmar Sandoval wait_cnt = atomic_inc_return(&ws->wait_cnt); 269*88459642SOmar Sandoval if (wait_cnt == 0) { 270*88459642SOmar Sandoval atomic_add(sbq->wake_batch, &ws->wait_cnt); 271*88459642SOmar Sandoval sbq_index_atomic_inc(&sbq->wake_index); 272*88459642SOmar Sandoval wake_up(&ws->wait); 273*88459642SOmar Sandoval } 274*88459642SOmar Sandoval } 275*88459642SOmar Sandoval 276*88459642SOmar Sandoval void sbitmap_queue_clear(struct sbitmap_queue *sbq, unsigned int nr) 277*88459642SOmar Sandoval { 278*88459642SOmar Sandoval sbitmap_clear_bit(&sbq->sb, nr); 279*88459642SOmar Sandoval sbq_wake_up(sbq); 280*88459642SOmar Sandoval } 281*88459642SOmar Sandoval EXPORT_SYMBOL_GPL(sbitmap_queue_clear); 282*88459642SOmar Sandoval 283*88459642SOmar Sandoval void sbitmap_queue_wake_all(struct sbitmap_queue *sbq) 284*88459642SOmar Sandoval { 285*88459642SOmar Sandoval int i, wake_index; 286*88459642SOmar Sandoval 287*88459642SOmar Sandoval /* 288*88459642SOmar Sandoval * Make sure all changes prior to this are visible from other CPUs. 289*88459642SOmar Sandoval */ 290*88459642SOmar Sandoval smp_mb(); 291*88459642SOmar Sandoval wake_index = atomic_read(&sbq->wake_index); 292*88459642SOmar Sandoval for (i = 0; i < SBQ_WAIT_QUEUES; i++) { 293*88459642SOmar Sandoval struct sbq_wait_state *ws = &sbq->ws[wake_index]; 294*88459642SOmar Sandoval 295*88459642SOmar Sandoval if (waitqueue_active(&ws->wait)) 296*88459642SOmar Sandoval wake_up(&ws->wait); 297*88459642SOmar Sandoval 298*88459642SOmar Sandoval wake_index = sbq_index_inc(wake_index); 299*88459642SOmar Sandoval } 300*88459642SOmar Sandoval } 301*88459642SOmar Sandoval EXPORT_SYMBOL_GPL(sbitmap_queue_wake_all); 302