brintos

brintos / linux-shallow public Read only

0
0
Text · 3.7 KiB · 304a8f1 Raw
183 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 *  Copyright (C) 2000 Takashi Iwai <tiwai@suse.de>4 *5 *  Generic memory management routines for soundcard memory allocation6 */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 15MODULE_AUTHOR("Takashi Iwai");16MODULE_DESCRIPTION("Generic memory management routines for soundcard memory allocation");17MODULE_LICENSE("GPL");18 19#define get_memblk(p)	list_entry(p, struct snd_util_memblk, list)20 21/*22 * create a new memory manager23 */24struct snd_util_memhdr *25snd_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 manager41 */42void 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 */59struct 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 size94 * the block is linked next to prev95 */96struct 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 */124struct snd_util_memblk *125snd_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 resource137 * (without mutex)138 */139void140__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 */151int 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 size164 */165int 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 175EXPORT_SYMBOL(snd_util_memhdr_new);176EXPORT_SYMBOL(snd_util_memhdr_free);177EXPORT_SYMBOL(snd_util_mem_alloc);178EXPORT_SYMBOL(snd_util_mem_free);179EXPORT_SYMBOL(snd_util_mem_avail);180EXPORT_SYMBOL(__snd_util_mem_alloc);181EXPORT_SYMBOL(__snd_util_mem_free);182EXPORT_SYMBOL(__snd_util_memblk_new);183