2
* Copyright (C) 2000 Takashi Iwai <tiwai@suse.de>
4
* Generic memory management routines for soundcard memory allocation
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.
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.
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
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>
28
MODULE_AUTHOR("Takashi Iwai");
29
MODULE_DESCRIPTION("Generic memory management routines for soundcard memory allocation");
30
MODULE_LICENSE("GPL");
32
#define get_memblk(p) list_entry(p, struct snd_util_memblk, list)
35
* create a new memory manager
37
struct snd_util_memhdr *
38
snd_util_memhdr_new(int memsize)
40
struct snd_util_memhdr *hdr;
42
hdr = kzalloc(sizeof(*hdr), GFP_KERNEL);
46
mutex_init(&hdr->block_mutex);
47
INIT_LIST_HEAD(&hdr->block);
53
* free a memory manager
55
void snd_util_memhdr_free(struct snd_util_memhdr *hdr)
61
/* release all blocks */
62
while ((p = hdr->block.next) != &hdr->block) {
70
* allocate a memory block (without mutex)
72
struct snd_util_memblk *
73
__snd_util_mem_alloc(struct snd_util_memhdr *hdr, int size)
75
struct snd_util_memblk *blk;
76
unsigned int units, prev_offset;
79
if (snd_BUG_ON(!hdr || size <= 0))
86
if (units > hdr->size)
89
/* look for empty block */
91
list_for_each(p, &hdr->block) {
93
if (blk->offset - prev_offset >= units)
95
prev_offset = blk->offset + blk->size;
97
if (hdr->size - prev_offset < units)
101
return __snd_util_memblk_new(hdr, units, p->prev);
106
* create a new memory block with the given size
107
* the block is linked next to prev
109
struct snd_util_memblk *
110
__snd_util_memblk_new(struct snd_util_memhdr *hdr, unsigned int units,
111
struct list_head *prev)
113
struct snd_util_memblk *blk;
115
blk = kmalloc(sizeof(struct snd_util_memblk) + hdr->block_extra_size,
120
if (prev == &hdr->block)
123
struct snd_util_memblk *p = get_memblk(prev);
124
blk->offset = p->offset + p->size;
127
list_add(&blk->list, prev);
135
* allocate a memory block (with mutex)
137
struct snd_util_memblk *
138
snd_util_mem_alloc(struct snd_util_memhdr *hdr, int size)
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);
149
* remove the block from linked-list and free resource
153
__snd_util_mem_free(struct snd_util_memhdr *hdr, struct snd_util_memblk *blk)
155
list_del(&blk->list);
157
hdr->used -= blk->size;
162
* free a memory block (with mutex)
164
int snd_util_mem_free(struct snd_util_memhdr *hdr, struct snd_util_memblk *blk)
166
if (snd_BUG_ON(!hdr || !blk))
169
mutex_lock(&hdr->block_mutex);
170
__snd_util_mem_free(hdr, blk);
171
mutex_unlock(&hdr->block_mutex);
176
* return available memory size
178
int snd_util_mem_avail(struct snd_util_memhdr *hdr)
181
mutex_lock(&hdr->block_mutex);
182
size = hdr->size - hdr->used;
183
mutex_unlock(&hdr->block_mutex);
188
EXPORT_SYMBOL(snd_util_memhdr_new);
189
EXPORT_SYMBOL(snd_util_memhdr_free);
190
EXPORT_SYMBOL(snd_util_mem_alloc);
191
EXPORT_SYMBOL(snd_util_mem_free);
192
EXPORT_SYMBOL(snd_util_mem_avail);
193
EXPORT_SYMBOL(__snd_util_mem_alloc);
194
EXPORT_SYMBOL(__snd_util_mem_free);
195
EXPORT_SYMBOL(__snd_util_memblk_new);
201
static int __init alsa_util_mem_init(void)
206
static void __exit alsa_util_mem_exit(void)
210
module_init(alsa_util_mem_init)
211
module_exit(alsa_util_mem_exit)