source: GPL/alsa-kernel/synth/util_mem.c@ 18

Last change on this file since 18 was 18, checked in by vladest, 20 years ago

initial import

File size: 4.7 KB
Line 
1/*
2 * Copyright (C) 2000 Takashi Iwai <tiwai@suse.de>
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., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21#define SNDRV_MAIN_OBJECT_FILE
22#include <sound/driver.h>
23#include <sound/util_mem.h>
24
25MODULE_AUTHOR("Takashi Iwai");
26
27#define get_memblk(p) list_entry(p, snd_util_memblk_t, list)
28
29/*
30 * create a new memory manager
31 */
32snd_util_memhdr_t *
33 snd_util_memhdr_new(int memsize)
34{
35 snd_util_memhdr_t *hdr;
36
37 hdr = kcalloc(1, sizeof(*hdr), GFP_KERNEL);
38 if (hdr == NULL)
39 return NULL;
40 hdr->size = memsize;
41 init_MUTEX(&hdr->block_mutex);
42 INIT_LIST_HEAD(&hdr->block);
43
44 return hdr;
45}
46
47/*
48 * free a memory manager
49 */
50void snd_util_memhdr_free(snd_util_memhdr_t *hdr)
51{
52 struct list_head *p;
53
54 snd_assert(hdr != NULL, return);
55 /* release all blocks */
56 while ((p = hdr->block.next) != &hdr->block) {
57 list_del(p);
58 kfree(get_memblk(p));
59 }
60 kfree(hdr);
61}
62
63/*
64 * allocate a memory block (without mutex)
65 */
66snd_util_memblk_t *
67__snd_util_mem_alloc(snd_util_memhdr_t *hdr, int size)
68{
69 snd_util_memblk_t *blk;
70 snd_util_unit_t units, prev_offset;
71 struct list_head *p;
72
73 snd_assert(hdr != NULL, return NULL);
74 snd_assert(size > 0, return NULL);
75 /* word alignment */
76 units = size;
77 if (units & 1)
78 units++;
79 if (units > hdr->size)
80 return NULL;
81
82 /* look for empty block */
83 prev_offset = 0;
84 list_for_each(p, &hdr->block) {
85 blk = get_memblk(p);
86 if (blk->offset - prev_offset >= units)
87 goto __found;
88 prev_offset = blk->offset + blk->size;
89 }
90 if (hdr->size - prev_offset < units)
91 return NULL;
92
93__found:
94 return __snd_util_memblk_new(hdr, units, p->prev);
95}
96
97
98/*
99 * create a new memory block with the given size
100 * the block is linked next to prev
101 */
102snd_util_memblk_t *
103__snd_util_memblk_new(snd_util_memhdr_t *hdr, snd_util_unit_t units,
104 struct list_head *prev)
105{
106 snd_util_memblk_t *blk;
107
108 blk = kmalloc(sizeof(snd_util_memblk_t) + hdr->block_extra_size, GFP_KERNEL);
109 if (blk == NULL)
110 return NULL;
111
112 if (! prev || prev == &hdr->block)
113 blk->offset = 0;
114 else {
115 snd_util_memblk_t *p = get_memblk(prev);
116 blk->offset = p->offset + p->size;
117 }
118 blk->size = units;
119 list_add(&blk->list, prev);
120 hdr->nblocks++;
121 hdr->used += units;
122 return blk;
123}
124
125
126/*
127 * allocate a memory block (with mutex)
128 */
129snd_util_memblk_t *
130snd_util_mem_alloc(snd_util_memhdr_t *hdr, int size)
131{
132 snd_util_memblk_t *blk;
133 down(&hdr->block_mutex);
134 blk = __snd_util_mem_alloc(hdr, size);
135 up(&hdr->block_mutex);
136 return blk;
137}
138
139
140/*
141 * remove the block from linked-list and free resource
142 * (without mutex)
143 */
144void
145__snd_util_mem_free(snd_util_memhdr_t *hdr, snd_util_memblk_t *blk)
146{
147 list_del(&blk->list);
148 hdr->nblocks--;
149 hdr->used -= blk->size;
150 kfree(blk);
151}
152
153/*
154 * free a memory block (with mutex)
155 */
156int snd_util_mem_free(snd_util_memhdr_t *hdr, snd_util_memblk_t *blk)
157{
158 snd_assert(hdr && blk, return -EINVAL);
159
160 down(&hdr->block_mutex);
161 __snd_util_mem_free(hdr, blk);
162 up(&hdr->block_mutex);
163 return 0;
164}
165
166/*
167 * return available memory size
168 */
169int snd_util_mem_avail(snd_util_memhdr_t *hdr)
170{
171 unsigned int size;
172 down(&hdr->block_mutex);
173 size = hdr->size - hdr->used;
174 up(&hdr->block_mutex);
175 return size;
176}
177
178
179EXPORT_SYMBOL(snd_util_memhdr_new);
180EXPORT_SYMBOL(snd_util_memhdr_free);
181EXPORT_SYMBOL(snd_util_mem_alloc);
182EXPORT_SYMBOL(snd_util_mem_free);
183EXPORT_SYMBOL(snd_util_mem_avail);
184EXPORT_SYMBOL(__snd_util_mem_alloc);
185EXPORT_SYMBOL(__snd_util_mem_free);
186EXPORT_SYMBOL(__snd_util_memblk_new);
187
188/*
189 * INIT part
190 */
191
192static int __init alsa_util_mem_init(void)
193{
194 return 0;
195}
196
197static void __exit alsa_util_mem_exit(void)
198{
199}
200
201module_init(alsa_util_mem_init)
202module_exit(alsa_util_mem_exit)
Note: See TracBrowser for help on using the repository browser.