Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
util_mem.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2000 Takashi Iwai <[email protected]>
3  *
4  * Generic memory management routines for soundcard memory allocation
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  */
20 
21 #include <linux/mutex.h>
22 #include <linux/init.h>
23 #include <linux/slab.h>
24 #include <linux/module.h>
25 #include <sound/core.h>
26 #include <sound/util_mem.h>
27 
28 MODULE_AUTHOR("Takashi Iwai");
29 MODULE_DESCRIPTION("Generic memory management routines for soundcard memory allocation");
30 MODULE_LICENSE("GPL");
31 
32 #define get_memblk(p) list_entry(p, struct snd_util_memblk, list)
33 
34 /*
35  * create a new memory manager
36  */
37 struct snd_util_memhdr *
39 {
40  struct snd_util_memhdr *hdr;
41 
42  hdr = kzalloc(sizeof(*hdr), GFP_KERNEL);
43  if (hdr == NULL)
44  return NULL;
45  hdr->size = memsize;
46  mutex_init(&hdr->block_mutex);
47  INIT_LIST_HEAD(&hdr->block);
48 
49  return hdr;
50 }
51 
52 /*
53  * free a memory manager
54  */
56 {
57  struct list_head *p;
58 
59  if (!hdr)
60  return;
61  /* release all blocks */
62  while ((p = hdr->block.next) != &hdr->block) {
63  list_del(p);
64  kfree(get_memblk(p));
65  }
66  kfree(hdr);
67 }
68 
69 /*
70  * allocate a memory block (without mutex)
71  */
72 struct snd_util_memblk *
74 {
75  struct snd_util_memblk *blk;
76  unsigned int units, prev_offset;
77  struct list_head *p;
78 
79  if (snd_BUG_ON(!hdr || size <= 0))
80  return NULL;
81 
82  /* word alignment */
83  units = size;
84  if (units & 1)
85  units++;
86  if (units > hdr->size)
87  return NULL;
88 
89  /* look for empty block */
90  prev_offset = 0;
91  list_for_each(p, &hdr->block) {
92  blk = get_memblk(p);
93  if (blk->offset - prev_offset >= units)
94  goto __found;
95  prev_offset = blk->offset + blk->size;
96  }
97  if (hdr->size - prev_offset < units)
98  return NULL;
99 
100 __found:
101  return __snd_util_memblk_new(hdr, units, p->prev);
102 }
103 
104 
105 /*
106  * create a new memory block with the given size
107  * the block is linked next to prev
108  */
109 struct snd_util_memblk *
110 __snd_util_memblk_new(struct snd_util_memhdr *hdr, unsigned int units,
111  struct list_head *prev)
112 {
113  struct snd_util_memblk *blk;
114 
115  blk = kmalloc(sizeof(struct snd_util_memblk) + hdr->block_extra_size,
116  GFP_KERNEL);
117  if (blk == NULL)
118  return NULL;
119 
120  if (prev == &hdr->block)
121  blk->offset = 0;
122  else {
123  struct snd_util_memblk *p = get_memblk(prev);
124  blk->offset = p->offset + p->size;
125  }
126  blk->size = units;
127  list_add(&blk->list, prev);
128  hdr->nblocks++;
129  hdr->used += units;
130  return blk;
131 }
132 
133 
134 /*
135  * allocate a memory block (with mutex)
136  */
137 struct snd_util_memblk *
139 {
140  struct snd_util_memblk *blk;
141  mutex_lock(&hdr->block_mutex);
142  blk = __snd_util_mem_alloc(hdr, size);
143  mutex_unlock(&hdr->block_mutex);
144  return blk;
145 }
146 
147 
148 /*
149  * remove the block from linked-list and free resource
150  * (without mutex)
151  */
152 void
154 {
155  list_del(&blk->list);
156  hdr->nblocks--;
157  hdr->used -= blk->size;
158  kfree(blk);
159 }
160 
161 /*
162  * free a memory block (with mutex)
163  */
165 {
166  if (snd_BUG_ON(!hdr || !blk))
167  return -EINVAL;
168 
169  mutex_lock(&hdr->block_mutex);
170  __snd_util_mem_free(hdr, blk);
171  mutex_unlock(&hdr->block_mutex);
172  return 0;
173 }
174 
175 /*
176  * return available memory size
177  */
179 {
180  unsigned int size;
181  mutex_lock(&hdr->block_mutex);
182  size = hdr->size - hdr->used;
183  mutex_unlock(&hdr->block_mutex);
184  return size;
185 }
186 
187 
196 
197 /*
198  * INIT part
199  */
200 
201 static int __init alsa_util_mem_init(void)
202 {
203  return 0;
204 }
205 
206 static void __exit alsa_util_mem_exit(void)
207 {
208 }
209 
210 module_init(alsa_util_mem_init)
211 module_exit(alsa_util_mem_exit)