root/sound/synth/util_mem.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. snd_util_memhdr_new
  2. snd_util_memhdr_free
  3. __snd_util_mem_alloc
  4. __snd_util_memblk_new
  5. snd_util_mem_alloc
  6. __snd_util_mem_free
  7. snd_util_mem_free
  8. snd_util_mem_avail

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  *  Copyright (C) 2000 Takashi Iwai <tiwai@suse.de>
   4  *
   5  *  Generic memory management routines for soundcard memory allocation
   6  */
   7 
   8 #include <linux/mutex.h>
   9 #include <linux/init.h>
  10 #include <linux/slab.h>
  11 #include <linux/module.h>
  12 #include <sound/core.h>
  13 #include <sound/util_mem.h>
  14 
  15 MODULE_AUTHOR("Takashi Iwai");
  16 MODULE_DESCRIPTION("Generic memory management routines for soundcard memory allocation");
  17 MODULE_LICENSE("GPL");
  18 
  19 #define get_memblk(p)   list_entry(p, struct snd_util_memblk, list)
  20 
  21 /*
  22  * create a new memory manager
  23  */
  24 struct snd_util_memhdr *
  25 snd_util_memhdr_new(int memsize)
  26 {
  27         struct snd_util_memhdr *hdr;
  28 
  29         hdr = kzalloc(sizeof(*hdr), GFP_KERNEL);
  30         if (hdr == NULL)
  31                 return NULL;
  32         hdr->size = memsize;
  33         mutex_init(&hdr->block_mutex);
  34         INIT_LIST_HEAD(&hdr->block);
  35 
  36         return hdr;
  37 }
  38 
  39 /*
  40  * free a memory manager
  41  */
  42 void snd_util_memhdr_free(struct snd_util_memhdr *hdr)
  43 {
  44         struct list_head *p;
  45 
  46         if (!hdr)
  47                 return;
  48         /* release all blocks */
  49         while ((p = hdr->block.next) != &hdr->block) {
  50                 list_del(p);
  51                 kfree(get_memblk(p));
  52         }
  53         kfree(hdr);
  54 }
  55 
  56 /*
  57  * allocate a memory block (without mutex)
  58  */
  59 struct snd_util_memblk *
  60 __snd_util_mem_alloc(struct snd_util_memhdr *hdr, int size)
  61 {
  62         struct snd_util_memblk *blk;
  63         unsigned int units, prev_offset;
  64         struct list_head *p;
  65 
  66         if (snd_BUG_ON(!hdr || size <= 0))
  67                 return NULL;
  68 
  69         /* word alignment */
  70         units = size;
  71         if (units & 1)
  72                 units++;
  73         if (units > hdr->size)
  74                 return NULL;
  75 
  76         /* look for empty block */
  77         prev_offset = 0;
  78         list_for_each(p, &hdr->block) {
  79                 blk = get_memblk(p);
  80                 if (blk->offset - prev_offset >= units)
  81                         goto __found;
  82                 prev_offset = blk->offset + blk->size;
  83         }
  84         if (hdr->size - prev_offset < units)
  85                 return NULL;
  86 
  87 __found:
  88         return __snd_util_memblk_new(hdr, units, p->prev);
  89 }
  90 
  91 
  92 /*
  93  * create a new memory block with the given size
  94  * the block is linked next to prev
  95  */
  96 struct snd_util_memblk *
  97 __snd_util_memblk_new(struct snd_util_memhdr *hdr, unsigned int units,
  98                       struct list_head *prev)
  99 {
 100         struct snd_util_memblk *blk;
 101 
 102         blk = kmalloc(sizeof(struct snd_util_memblk) + hdr->block_extra_size,
 103                       GFP_KERNEL);
 104         if (blk == NULL)
 105                 return NULL;
 106 
 107         if (prev == &hdr->block)
 108                 blk->offset = 0;
 109         else {
 110                 struct snd_util_memblk *p = get_memblk(prev);
 111                 blk->offset = p->offset + p->size;
 112         }
 113         blk->size = units;
 114         list_add(&blk->list, prev);
 115         hdr->nblocks++;
 116         hdr->used += units;
 117         return blk;
 118 }
 119 
 120 
 121 /*
 122  * allocate a memory block (with mutex)
 123  */
 124 struct snd_util_memblk *
 125 snd_util_mem_alloc(struct snd_util_memhdr *hdr, int size)
 126 {
 127         struct snd_util_memblk *blk;
 128         mutex_lock(&hdr->block_mutex);
 129         blk = __snd_util_mem_alloc(hdr, size);
 130         mutex_unlock(&hdr->block_mutex);
 131         return blk;
 132 }
 133 
 134 
 135 /*
 136  * remove the block from linked-list and free resource
 137  * (without mutex)
 138  */
 139 void
 140 __snd_util_mem_free(struct snd_util_memhdr *hdr, struct snd_util_memblk *blk)
 141 {
 142         list_del(&blk->list);
 143         hdr->nblocks--;
 144         hdr->used -= blk->size;
 145         kfree(blk);
 146 }
 147 
 148 /*
 149  * free a memory block (with mutex)
 150  */
 151 int snd_util_mem_free(struct snd_util_memhdr *hdr, struct snd_util_memblk *blk)
 152 {
 153         if (snd_BUG_ON(!hdr || !blk))
 154                 return -EINVAL;
 155 
 156         mutex_lock(&hdr->block_mutex);
 157         __snd_util_mem_free(hdr, blk);
 158         mutex_unlock(&hdr->block_mutex);
 159         return 0;
 160 }
 161 
 162 /*
 163  * return available memory size
 164  */
 165 int snd_util_mem_avail(struct snd_util_memhdr *hdr)
 166 {
 167         unsigned int size;
 168         mutex_lock(&hdr->block_mutex);
 169         size = hdr->size - hdr->used;
 170         mutex_unlock(&hdr->block_mutex);
 171         return size;
 172 }
 173 
 174 
 175 EXPORT_SYMBOL(snd_util_memhdr_new);
 176 EXPORT_SYMBOL(snd_util_memhdr_free);
 177 EXPORT_SYMBOL(snd_util_mem_alloc);
 178 EXPORT_SYMBOL(snd_util_mem_free);
 179 EXPORT_SYMBOL(snd_util_mem_avail);
 180 EXPORT_SYMBOL(__snd_util_mem_alloc);
 181 EXPORT_SYMBOL(__snd_util_mem_free);
 182 EXPORT_SYMBOL(__snd_util_memblk_new);

/* [<][>][^][v][top][bottom][index][help] */